How to Create a Custom Ban Screen?

Need some custom code changes to the phpBB core simple enough that you feel doesn't require an extension? Then post your request here so that community members can provide some assistance.

NOTE: NO OFFICIAL SUPPORT IS PROVIDED IN THIS SUB-FORUM
Forum rules
READ: phpBB.com Board-Wide Rules and Regulations

NOTE: NO OFFICIAL SUPPORT IS PROVIDED IN THIS SUB-FORUM
paddington_bear
Registered User
Posts: 3
Joined: Thu Sep 19, 2024 4:08 am

How to Create a Custom Ban Screen?

Post by paddington_bear »

Hi. I hope you are well.

I am trying to create a custom ban screen for my phpBB installation. More specifically, when a user gets banned from my forum, I want to redirect the default screen to a separate page (that I wrote in HTML). Thus, I inserted the below code in the "functionuser.php" file (immediately after the "if ($ban_len)" tag). Thankfully, doing so did not break my site at all, but the bad news is that the code in question did not redirect the default ban screen to the intended page.

(Code referenced above: redirect(append_sid("/my/file/path.html"));)

So, what should I do? Is there an extension that could do this for me, or do I need to insert a different script in a different file? How can I redirect the default ban page to a custom ban page?

Thanks in advance.
Last edited by thecoalman on Thu Sep 19, 2024 6:01 am, edited 1 time in total.
Reason: Moved to custom coding.
User avatar
danieltj
Infrastructure Team Member
Infrastructure Team Member
Posts: 518
Joined: Thu May 03, 2018 9:32 pm
Location: United Kingdom
Name: Daniel James

Re: How to Create a Custom Ban Screen?

Post by danieltj »

Could you provide the full code of the function in that file? So not the whole file, but just the function that you’ve modified as that will help with diagnosing the issue.
💷 Purchase the Awesome Payments extension today!
Monetise your forum with one off payments and subscriptions.

Need a premium extension created? Send me a PM.
paddington_bear
Registered User
Posts: 3
Joined: Thu Sep 19, 2024 4:08 am

Re: How to Create a Custom Ban Screen?

Post by paddington_bear »

Here you go. The only modification I made is the addition of the code "redirect(append_sid("/filepath.html"));"

Code: Select all

function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason = '')
{
	global $db, $user, $cache, $phpbb_log;

	// Delete stale bans
	$sql = 'DELETE FROM ' . BANLIST_TABLE . '
		WHERE ban_end < ' . time() . '
			AND ban_end <> 0';
	$db->sql_query($sql);

	$ban_list = (!is_array($ban)) ? array_unique(explode("\n", $ban)) : $ban;
	$ban_list_log = implode(', ', $ban_list);

	$current_time = time();

	// Set $ban_end to the unix time when the ban should end. 0 is a permanent ban.
	if ($ban_len)
	{
		redirect(append_sid("/filepath.html"));
		if ($ban_len != -1 || !$ban_len_other)
		{
			$ban_end = max($current_time, $current_time + ($ban_len) * 60);
		}
		else
		{
			$ban_other = explode('-', $ban_len_other);
			if (count($ban_other) == 3 && ((int) $ban_other[0] < 9999) &&
				(strlen($ban_other[0]) == 4) && (strlen($ban_other[1]) == 2) && (strlen($ban_other[2]) == 2))
			{
				$ban_end = max($current_time, $user->create_datetime()
					->setDate((int) $ban_other[0], (int) $ban_other[1], (int) $ban_other[2])
					->setTime(0, 0, 0)
					->getTimestamp() + $user->timezone->getOffset(new DateTime('UTC')));
			}
			else
			{
				trigger_error('LENGTH_BAN_INVALID', E_USER_WARNING);
			}
		}
	}
	else
	{
		$ban_end = 0;
	}

	$founder = $founder_names = array();

	if (!$ban_exclude)
	{
		// Create a list of founder...
		$sql = 'SELECT user_id, user_email, username_clean
			FROM ' . USERS_TABLE . '
			WHERE user_type = ' . USER_FOUNDER;
		$result = $db->sql_query($sql);

		while ($row = $db->sql_fetchrow($result))
		{
			$founder[$row['user_id']] = $row['user_email'];
			$founder_names[$row['user_id']] = $row['username_clean'];
		}
		$db->sql_freeresult($result);
	}

	$banlist_ary = array();

	switch ($mode)
	{
		case 'user':
			$type = 'ban_userid';

			// At the moment we do not support wildcard username banning

			// Select the relevant user_ids.
			$sql_usernames = array();

			foreach ($ban_list as $username)
			{
				$username = trim($username);
				if ($username != '')
				{
					$clean_name = utf8_clean_string($username);
					if ($clean_name == $user->data['username_clean'])
					{
						trigger_error('CANNOT_BAN_YOURSELF', E_USER_WARNING);
					}
					if (in_array($clean_name, $founder_names))
					{
						trigger_error('CANNOT_BAN_FOUNDER', E_USER_WARNING);
					}
					$sql_usernames[] = $clean_name;
				}
			}

			// Make sure we have been given someone to ban
			if (!count($sql_usernames))
			{
				trigger_error('NO_USER_SPECIFIED', E_USER_WARNING);
			}

			$sql = 'SELECT user_id
				FROM ' . USERS_TABLE . '
				WHERE ' . $db->sql_in_set('username_clean', $sql_usernames);

			// Do not allow banning yourself, the guest account, or founders.
			$non_bannable = array($user->data['user_id'], ANONYMOUS);
			if (count($founder))
			{
				$sql .= ' AND ' . $db->sql_in_set('user_id', array_merge(array_keys($founder), $non_bannable), true);
			}
			else
			{
				$sql .= ' AND ' . $db->sql_in_set('user_id', $non_bannable, true);
			}

			$result = $db->sql_query($sql);

			if ($row = $db->sql_fetchrow($result))
			{
				do
				{
					$banlist_ary[] = (int) $row['user_id'];
				}
				while ($row = $db->sql_fetchrow($result));

				$db->sql_freeresult($result);
			}
			else
			{
				$db->sql_freeresult($result);

				trigger_error('NO_USERS', E_USER_WARNING);
			}
		break;

		case 'ip':
			$type = 'ban_ip';

			foreach ($ban_list as $ban_item)
			{
				if (preg_match('#^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})[ ]*\-[ ]*([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$#', trim($ban_item), $ip_range_explode))
				{
					// This is an IP range
					// Don't ask about all this, just don't ask ... !
					$ip_1_counter = $ip_range_explode[1];
					$ip_1_end = $ip_range_explode[5];

					while ($ip_1_counter <= $ip_1_end)
					{
						$ip_2_counter = ($ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[2] : 0;
						$ip_2_end = ($ip_1_counter < $ip_1_end) ? 254 : $ip_range_explode[6];

						if ($ip_2_counter == 0 && $ip_2_end == 254)
						{
							$ip_2_counter = 256;

							$banlist_ary[] = "$ip_1_counter.*";
						}

						while ($ip_2_counter <= $ip_2_end)
						{
							$ip_3_counter = ($ip_2_counter == $ip_range_explode[2] && $ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[3] : 0;
							$ip_3_end = ($ip_2_counter < $ip_2_end || $ip_1_counter < $ip_1_end) ? 254 : $ip_range_explode[7];

							if ($ip_3_counter == 0 && $ip_3_end == 254)
							{
								$ip_3_counter = 256;

								$banlist_ary[] = "$ip_1_counter.$ip_2_counter.*";
							}

							while ($ip_3_counter <= $ip_3_end)
							{
								$ip_4_counter = ($ip_3_counter == $ip_range_explode[3] && $ip_2_counter == $ip_range_explode[2] && $ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[4] : 0;
								$ip_4_end = ($ip_3_counter < $ip_3_end || $ip_2_counter < $ip_2_end) ? 254 : $ip_range_explode[8];

								if ($ip_4_counter == 0 && $ip_4_end == 254)
								{
									$ip_4_counter = 256;

									$banlist_ary[] = "$ip_1_counter.$ip_2_counter.$ip_3_counter.*";
								}

								while ($ip_4_counter <= $ip_4_end)
								{
									$banlist_ary[] = "$ip_1_counter.$ip_2_counter.$ip_3_counter.$ip_4_counter";
									$ip_4_counter++;
								}
								$ip_3_counter++;
							}
							$ip_2_counter++;
						}
						$ip_1_counter++;
					}
				}
				else if (preg_match('#^([0-9]{1,3})\.([0-9\*]{1,3})\.([0-9\*]{1,3})\.([0-9\*]{1,3})$#', trim($ban_item)) || preg_match('#^[a-f0-9:]+\*?$#i', trim($ban_item)))
				{
					// Normal IP address
					$banlist_ary[] = trim($ban_item);
				}
				else if (preg_match('#^\*$#', trim($ban_item)))
				{
					// Ban all IPs
					$banlist_ary[] = '*';
				}
				else if (preg_match('#^([\w\-_]\.?){2,}$#is', trim($ban_item)))
				{
					// hostname
					$ip_ary = gethostbynamel(trim($ban_item));

					if (!empty($ip_ary))
					{
						foreach ($ip_ary as $ip)
						{
							if ($ip)
							{
								if (strlen($ip) > 40)
								{
									continue;
								}

								$banlist_ary[] = $ip;
							}
						}
					}
				}

				if (empty($banlist_ary))
				{
					trigger_error('NO_IPS_DEFINED', E_USER_WARNING);
				}
			}
		break;

		case 'email':
			$type = 'ban_email';

			foreach ($ban_list as $ban_item)
			{
				$ban_item = trim($ban_item);

				if (preg_match('#^.*?@*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i', $ban_item))
				{
					if (strlen($ban_item) > 100)
					{
						continue;
					}

					if (!count($founder) || !in_array($ban_item, $founder))
					{
						$banlist_ary[] = $ban_item;
					}
				}
			}

			if (count($ban_list) == 0)
			{
				trigger_error('NO_EMAILS_DEFINED', E_USER_WARNING);
			}
		break;

		default:
			trigger_error('NO_MODE', E_USER_WARNING);
		break;
	}

	// Fetch currently set bans of the specified type and exclude state. Prevent duplicate bans.
	$sql_where = ($type == 'ban_userid') ? 'ban_userid <> 0' : "$type <> ''";

	$sql = "SELECT $type
		FROM " . BANLIST_TABLE . "
		WHERE $sql_where
			AND ban_exclude = " . (int) $ban_exclude;
	$result = $db->sql_query($sql);

	// Reset $sql_where, because we use it later...
	$sql_where = '';

	if ($row = $db->sql_fetchrow($result))
	{
		$banlist_ary_tmp = array();
		do
		{
			switch ($mode)
			{
				case 'user':
					$banlist_ary_tmp[] = $row['ban_userid'];
				break;

				case 'ip':
					$banlist_ary_tmp[] = $row['ban_ip'];
				break;

				case 'email':
					$banlist_ary_tmp[] = $row['ban_email'];
				break;
			}
		}
		while ($row = $db->sql_fetchrow($result));

		$banlist_ary_tmp = array_intersect($banlist_ary, $banlist_ary_tmp);

		if (count($banlist_ary_tmp))
		{
			// One or more entities are already banned/excluded, delete the existing bans, so they can be re-inserted with the given new length
			$sql = 'DELETE FROM ' . BANLIST_TABLE . '
				WHERE ' . $db->sql_in_set($type, $banlist_ary_tmp) . '
					AND ban_exclude = ' . (int) $ban_exclude;
			$db->sql_query($sql);
		}

		unset($banlist_ary_tmp);
	}
	$db->sql_freeresult($result);

	// We have some entities to ban
	if (count($banlist_ary))
	{
		$sql_ary = array();

		foreach ($banlist_ary as $ban_entry)
		{
			$sql_ary[] = array(
				$type				=> $ban_entry,
				'ban_start'			=> (int) $current_time,
				'ban_end'			=> (int) $ban_end,
				'ban_exclude'		=> (int) $ban_exclude,
				'ban_reason'		=> (string) $ban_reason,
				'ban_give_reason'	=> (string) $ban_give_reason,
			);
		}

		$db->sql_multi_insert(BANLIST_TABLE, $sql_ary);

		// If we are banning we want to logout anyone matching the ban
		if (!$ban_exclude)
		{
			switch ($mode)
			{
				case 'user':
					$sql_where = 'WHERE ' . $db->sql_in_set('session_user_id', $banlist_ary);
				break;

				case 'ip':
					$sql_where = 'WHERE ' . $db->sql_in_set('session_ip', $banlist_ary);
				break;

				case 'email':
					$banlist_ary_sql = array();

					foreach ($banlist_ary as $ban_entry)
					{
						$banlist_ary_sql[] = (string) str_replace('*', '%', $ban_entry);
					}

					$sql = 'SELECT user_id
						FROM ' . USERS_TABLE . '
						WHERE ' . $db->sql_in_set('user_email', $banlist_ary_sql);
					$result = $db->sql_query($sql);

					$sql_in = array();

					if ($row = $db->sql_fetchrow($result))
					{
						do
						{
							$sql_in[] = $row['user_id'];
						}
						while ($row = $db->sql_fetchrow($result));

						$sql_where = 'WHERE ' . $db->sql_in_set('session_user_id', $sql_in);
					}
					$db->sql_freeresult($result);
				break;
			}

			if (isset($sql_where) && $sql_where)
			{
				$sql = 'DELETE FROM ' . SESSIONS_TABLE . "
					$sql_where";
				$db->sql_query($sql);

				if ($mode == 'user')
				{
					$sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' ' . ((in_array('*', $banlist_ary)) ? '' : 'WHERE ' . $db->sql_in_set('user_id', $banlist_ary));
					$db->sql_query($sql);
				}
			}
		}

		// Update log
		$log_entry = ($ban_exclude) ? 'LOG_BAN_EXCLUDE_' : 'LOG_BAN_';

		// Add to admin log, moderator log and user notes
		$phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_entry . strtoupper($mode), false, array($ban_reason, $ban_list_log));
		$phpbb_log->add('mod', $user->data['user_id'], $user->ip, $log_entry . strtoupper($mode), false, array(
			'forum_id' => 0,
			'topic_id' => 0,
			$ban_reason,
			$ban_list_log
		));
		if ($mode == 'user')
		{
			foreach ($banlist_ary as $user_id)
			{
				$phpbb_log->add('user', $user->data['user_id'], $user->ip, $log_entry . strtoupper($mode), false, array(
					'reportee_id' => $user_id,
					$ban_reason,
					$ban_list_log
				));
			}
		}

		$cache->destroy('sql', BANLIST_TABLE);

		return true;
	}

	// There was nothing to ban/exclude. But destroying the cache because of the removal of stale bans.
	$cache->destroy('sql', BANLIST_TABLE);

	return false;
}
User avatar
thecoalman
Community Team Member
Community Team Member
Posts: 6290
Joined: Wed Dec 22, 2004 3:52 am
Location: Pennsylvania, U.S.A.

Re: How to Create a Custom Ban Screen?

Post by thecoalman »

1. That function is to ban the user.

2. redirect is custom phpBB function and assuming it's available within that function the only person that will get redirected is the person issuing the ban if they set length of time. Not sure why you thought that was the place to put it but it's not even remotely close.
---------------------------------------------

The easiest way to do this is change the language strings. Open /language/en/common.php and around line 135 find:

Code: Select all

	'BAN_TRIGGERED_BY_EMAIL'=> 'A ban has been issued on your email address.',
	'BAN_TRIGGERED_BY_IP'	=> 'A ban has been issued on your IP address.',
	'BAN_TRIGGERED_BY_USER'	=> 'A ban has been issued on your username.',
And just a little below it:

Code: Select all

	'BOARD_BAN_PERM'		=> 'You have been <strong>permanently</strong> banned from this board.<br /><br />Please contact the %2$sBoard Administrator%3$s for more information.',
	'BOARD_BAN_REASON'		=> 'Reason given for ban: <strong>%s</strong>',
	'BOARD_BAN_TIME'		=> 'You have been banned from this board until <strong>%1$s</strong>.<br /><br />Please contact the %2$sBoard Administrator%3$s for more information.',
This assumes you are using Brithish English, if you are using different language check that folder.

You can use HTML but special characters like ', ", &, < or >should be entity The single backtick ' cannot be used to enclose HTML attributes, use double backtick " instead. The %1$s part of the string are placeholders for other text. e.g. the time the ban is in effect too.
“Results! Why, man, I have gotten a lot of results! I have found several thousand things that won’t work.”

Attributed - Thomas Edison
paddington_bear
Registered User
Posts: 3
Joined: Thu Sep 19, 2024 4:08 am

Re: How to Create a Custom Ban Screen?

Post by paddington_bear »

This method worked! Thanks! :)
User avatar
thecoalman
Community Team Member
Community Team Member
Posts: 6290
Joined: Wed Dec 22, 2004 3:52 am
Location: Pennsylvania, U.S.A.

Re: How to Create a Custom Ban Screen?

Post by thecoalman »

Just be aware when you update you will need to edit in the changes to new files.
“Results! Why, man, I have gotten a lot of results! I have found several thousand things that won’t work.”

Attributed - Thomas Edison

Return to “phpBB Custom Coding”