@@ -1052,8 +1052,8 @@ | |||
* ==================== | |||
*/ | |||
// Limit how many bans can be removed via the ban list. Set to -1 for no limit. | |||
$config['mod']['unban_limit'] = -1; | |||
// Limit how many bans can be removed via the ban list. Set to false (or zero) for no limit. | |||
$config['mod']['unban_limit'] = false; | |||
// Whether or not to lock moderator sessions to IP addresses. This makes cookie theft ineffective. | |||
$config['mod']['lock_ip'] = true; | |||
@@ -1098,14 +1098,6 @@ | |||
// 'color:red;font-weight:bold' // Change tripcode style; optional | |||
//); | |||
// Enable IP range bans (eg. "127.*.0.1", "127.0.0.*", and "12*.0.0.1" all match "127.0.0.1"). Puts a | |||
// little more load on the database | |||
$config['ban_range'] = true; | |||
// Enable CDIR netmask bans (eg. "10.0.0.0/8" for 10.0.0.0.0 - 10.255.255.255). Useful for stopping | |||
// persistent spammers and ban evaders. Again, a little more database load. | |||
$config['ban_cidr'] = true; | |||
// How often (minimum) to purge the ban list of expired bans (which have been seen). Only works when | |||
// $config['cache'] is enabled and working. | |||
$config['purge_bans'] = 60 * 60 * 12; // 12 hours | |||
@@ -22,7 +22,7 @@ class PreparedQueryDebug { | |||
if ($config['debug'] && $function == 'execute') { | |||
if ($this->explain_query) { | |||
$this->explain_query->execute() or error(db_error($explain_query)); | |||
$this->explain_query->execute() or error(db_error($this->explain_query)); | |||
} | |||
$start = microtime(true); | |||
} | |||
@@ -120,47 +120,13 @@ class Filter { | |||
if (!isset($this->reason)) | |||
error('The ban action requires a reason.'); | |||
$reason = $this->reason; | |||
$this->expires = isset($this->expires) ? $this->expires : false; | |||
$this->reject = isset($this->reject) ? $this->reject : true; | |||
$this->all_boards = isset($this->all_boards) ? $this->all_boards : false; | |||
if (isset($this->expires)) | |||
$expires = time() + $this->expires; | |||
else | |||
$expires = 0; // Ban indefinitely | |||
Bans::new_ban($_SERVER['REMOTE_ADDR'], $this->reason, $this->expires, $this->all_boards ? false : $board['uri'], -1); | |||
if (isset($this->reject)) | |||
$reject = $this->reject; | |||
else | |||
$reject = true; | |||
if (isset($this->all_boards)) | |||
$all_boards = $this->all_boards; | |||
else | |||
$all_boards = false; | |||
$query = prepare("INSERT INTO ``bans`` VALUES (NULL, :ip, :mod, :set, :expires, :reason, :board, 0)"); | |||
$query->bindValue(':ip', $_SERVER['REMOTE_ADDR']); | |||
$query->bindValue(':mod', -1); | |||
$query->bindValue(':set', time()); | |||
if ($expires) | |||
$query->bindValue(':expires', $expires); | |||
else | |||
$query->bindValue(':expires', null, PDO::PARAM_NULL); | |||
if ($reason) | |||
$query->bindValue(':reason', $reason); | |||
else | |||
$query->bindValue(':reason', null, PDO::PARAM_NULL); | |||
if ($all_boards) | |||
$query->bindValue(':board', null, PDO::PARAM_NULL); | |||
else | |||
$query->bindValue(':board', $board['uri']); | |||
$query->execute() or error(db_error($query)); | |||
if ($reject) { | |||
if ($this->reject) { | |||
if (isset($this->message)) | |||
error($message); | |||
@@ -18,6 +18,7 @@ require_once 'inc/template.php'; | |||
require_once 'inc/database.php'; | |||
require_once 'inc/events.php'; | |||
require_once 'inc/api.php'; | |||
require_once 'inc/bans.php'; | |||
require_once 'inc/lib/gettext/gettext.inc'; | |||
// the user is not currently logged in as a moderator | |||
@@ -619,9 +620,7 @@ function displayBan($ban) { | |||
global $config; | |||
if (!$ban['seen']) { | |||
$query = prepare("UPDATE ``bans`` SET `seen` = 1 WHERE `id` = :id"); | |||
$query->bindValue(':id', $ban['id'], PDO::PARAM_INT); | |||
$query->execute() or error(db_error($query)); | |||
Bans::seen($ban['id']); | |||
} | |||
$ban['ip'] = $_SERVER['REMOTE_ADDR']; | |||
@@ -650,62 +649,37 @@ function checkBan($board = false) { | |||
if (event('check-ban', $board)) | |||
return true; | |||
$query_where = array(); | |||
// Simple ban | |||
$query_where[] = "`ip` = :ip"; | |||
// Range ban | |||
if ($config['ban_range']) | |||
$query_where[] = ":ip LIKE REPLACE(REPLACE(`ip`, '%', '!%'), '*', '%') ESCAPE '!'"; | |||
// Subnet mask ban | |||
if ($config['ban_cidr'] && !isIPv6()) | |||
$query_where[] = "( | |||
`ip` REGEXP '^(\[0-9]+\.\[0-9]+\.\[0-9]+\.\[0-9]+\)\/(\[0-9]+)$' | |||
AND | |||
:iplong >= INET_ATON(SUBSTRING_INDEX(`ip`, '/', 1)) | |||
AND | |||
:iplong < INET_ATON(SUBSTRING_INDEX(`ip`, '/', 1)) + POW(2, 32 - SUBSTRING_INDEX(`ip`, '/', -1)) | |||
)"; | |||
$query = prepare('SELECT * FROM ``bans`` WHERE (`board` IS NULL' . ($board ? ' OR `board` = :board' : '') . | |||
') AND (' . implode(' OR ', $query_where) . ') ORDER BY `expires` IS NULL, `expires` DESC'); | |||
if ($board) | |||
$query->bindValue(':board', $board); | |||
$query->bindValue(':ip', $_SERVER['REMOTE_ADDR']); | |||
if ($config['ban_cidr'] && !isIPv6()) | |||
$query->bindValue(':iplong', ip2long($_SERVER['REMOTE_ADDR'])); | |||
$query->execute() or error(db_error($query)); | |||
$bans = Bans::find($_SERVER['REMOTE_ADDR'], $board); | |||
while ($ban = $query->fetch(PDO::FETCH_ASSOC)) { | |||
foreach ($bans as &$ban) { | |||
if ($ban['expires'] && $ban['expires'] < time()) { | |||
// Ban expired | |||
$query = prepare("DELETE FROM ``bans`` WHERE `id` = :id"); | |||
$query->bindValue(':id', $ban['id'], PDO::PARAM_INT); | |||
$query->execute() or error(db_error($query)); | |||
Bans::delete($ban['id']); | |||
if ($config['require_ban_view'] && !$ban['seen']) { | |||
displayBan($ban); | |||
if (!isset($_POST['json_response'])) { | |||
displayBan($ban); | |||
} else { | |||
header('Content-Type: text/json'); | |||
die(json_encode(array('error' => true, 'banned' => true))); | |||
} | |||
} | |||
} else { | |||
displayBan($ban); | |||
if (!isset($_POST['json_response'])) { | |||
displayBan($ban); | |||
} else { | |||
header('Content-Type: text/json'); | |||
die(json_encode(array('error' => true, 'banned' => true))); | |||
} | |||
} | |||
} | |||
// I'm not sure where else to put this. It doesn't really matter where; it just needs to be called every now and then to keep the ban list tidy. | |||
purge_bans(); | |||
} | |||
// No reason to keep expired bans in the database (except those that haven't been viewed yet) | |||
function purge_bans() { | |||
global $config; | |||
// I'm not sure where else to put this. It doesn't really matter where; it just needs to be called every | |||
// now and then to keep the ban list tidy. | |||
if ($config['cache']['enabled'] && $last_time_purged = cache::get('purged_bans_last')) { | |||
if (time() - $last_time_purged < $config['purge_bans'] ) | |||
return; | |||
} | |||
$query = prepare("DELETE FROM ``bans`` WHERE `expires` IS NOT NULL AND `expires` < :time AND `seen` = 1"); | |||
$query->bindValue(':time', time()); | |||
$query->execute() or error(db_error($query)); | |||
Bans::purge(); | |||
if ($config['cache']['enabled']) | |||
cache::set('purged_bans_last', time()); | |||
@@ -4,102 +4,7 @@ | |||
* Copyright (c) 2010-2013 Tinyboard Development Group | |||
*/ | |||
if (realpath($_SERVER['SCRIPT_FILENAME']) == str_replace('\\', '/', __FILE__)) { | |||
// You cannot request this file directly. | |||
exit; | |||
} | |||
defined('TINYBOARD') or exit; | |||
function parse_time($str) { | |||
if (empty($str)) | |||
return false; | |||
if (($time = @strtotime($str)) !== false) | |||
return $time; | |||
if (!preg_match('/^((\d+)\s?ye?a?r?s?)?\s?+((\d+)\s?mon?t?h?s?)?\s?+((\d+)\s?we?e?k?s?)?\s?+((\d+)\s?da?y?s?)?((\d+)\s?ho?u?r?s?)?\s?+((\d+)\s?mi?n?u?t?e?s?)?\s?+((\d+)\s?se?c?o?n?d?s?)?$/', $str, $matches)) | |||
return false; | |||
$expire = 0; | |||
if (isset($matches[2])) { | |||
// Years | |||
$expire += $matches[2]*60*60*24*365; | |||
} | |||
if (isset($matches[4])) { | |||
// Months | |||
$expire += $matches[4]*60*60*24*30; | |||
} | |||
if (isset($matches[6])) { | |||
// Weeks | |||
$expire += $matches[6]*60*60*24*7; | |||
} | |||
if (isset($matches[8])) { | |||
// Days | |||
$expire += $matches[8]*60*60*24; | |||
} | |||
if (isset($matches[10])) { | |||
// Hours | |||
$expire += $matches[10]*60*60; | |||
} | |||
if (isset($matches[12])) { | |||
// Minutes | |||
$expire += $matches[12]*60; | |||
} | |||
if (isset($matches[14])) { | |||
// Seconds | |||
$expire += $matches[14]; | |||
} | |||
return time() + $expire; | |||
} | |||
function ban($mask, $reason, $length, $board) { | |||
global $mod, $pdo; | |||
$query = prepare("INSERT INTO ``bans`` VALUES (NULL, :ip, :mod, :time, :expires, :reason, :board, 0)"); | |||
$query->bindValue(':ip', $mask); | |||
$query->bindValue(':mod', $mod['id']); | |||
$query->bindValue(':time', time()); | |||
if ($reason !== '') { | |||
$reason = escape_markup_modifiers($reason); | |||
markup($reason); | |||
$query->bindValue(':reason', $reason); | |||
} else | |||
$query->bindValue(':reason', null, PDO::PARAM_NULL); | |||
if ($length > 0) | |||
$query->bindValue(':expires', $length); | |||
else | |||
$query->bindValue(':expires', null, PDO::PARAM_NULL); | |||
if ($board) | |||
$query->bindValue(':board', $board); | |||
else | |||
$query->bindValue(':board', null, PDO::PARAM_NULL); | |||
$query->execute() or error(db_error($query)); | |||
modLog('Created a new ' . | |||
($length > 0 ? preg_replace('/^(\d+) (\w+?)s?$/', '$1-$2', until($length)) : 'permanent') . | |||
' ban on ' . | |||
($board ? '/' . $board . '/' : 'all boards') . | |||
' for ' . | |||
(filter_var($mask, FILTER_VALIDATE_IP) !== false ? "<a href=\"?/IP/$mask\">$mask</a>" : utf8tohtml($mask)) . | |||
' (<small>#' . $pdo->lastInsertId() . '</small>)' . | |||
' with ' . ($reason ? 'reason: ' . utf8tohtml($reason) . '' : 'no reason')); | |||
} | |||
function unban($id) { | |||
$query = prepare("SELECT `ip` FROM ``bans`` WHERE `id` = :id"); | |||
$query->bindValue(':id', $id); | |||
$query->execute() or error(db_error($query)); | |||
$mask = $query->fetchColumn(); | |||
$query = prepare("DELETE FROM ``bans`` WHERE `id` = :id"); | |||
$query->bindValue(':id', $id); | |||
$query->execute() or error(db_error($query)); | |||
if ($mask) | |||
modLog("Removed ban #{$id} for " . (filter_var($mask, FILTER_VALIDATE_IP) !== false ? "<a href=\"?/IP/$mask\">$mask</a>" : utf8tohtml($mask))); | |||
} | |||
// This file is no longer used. |
@@ -1,5 +1,11 @@ | |||
<?php | |||
/* | |||
* Copyright (c) 2010-2013 Tinyboard Development Group | |||
*/ | |||
defined('TINYBOARD') or exit; | |||
function permission_to_edit_config_var($varname) { | |||
global $config, $mod; | |||
@@ -289,7 +289,7 @@ function mod_search($type, $search_query_escaped, $page_no = 1) { | |||
} | |||
if ($type == 'bans') { | |||
$query = 'SELECT ``bans``.*, `username` FROM ``bans`` LEFT JOIN ``mods`` ON `mod` = ``mods``.`id` WHERE ' . $sql_like . ' ORDER BY (`expires` IS NOT NULL AND `expires` < UNIX_TIMESTAMP()), `set` DESC'; | |||
$query = 'SELECT ``bans``.*, `username` FROM ``bans`` LEFT JOIN ``mods`` ON `mod` = ``mods``.`id` WHERE ' . $sql_like . ' ORDER BY (`expires` IS NOT NULL AND `expires` < UNIX_TIMESTAMP()), `created` DESC'; | |||
$sql_table = 'bans'; | |||
if (!hasPermission($config['mod']['view_banlist'])) | |||
error($config['error']['noaccess']); | |||
@@ -740,9 +740,7 @@ function mod_page_ip($ip) { | |||
if (!hasPermission($config['mod']['unban'])) | |||
error($config['error']['noaccess']); | |||
require_once 'inc/mod/ban.php'; | |||
unban($_POST['ban_id']); | |||
Bans::delete($_POST['ban_id'], true); | |||
header('Location: ?/IP/' . $ip . '#bans', true, $config['redirect_http']); | |||
return; | |||
@@ -801,10 +799,7 @@ function mod_page_ip($ip) { | |||
$args['token'] = make_secure_link_token('ban'); | |||
if (hasPermission($config['mod']['view_ban'])) { | |||
$query = prepare("SELECT ``bans``.*, `username` FROM ``bans`` LEFT JOIN ``mods`` ON `mod` = ``mods``.`id` WHERE `ip` = :ip ORDER BY `set` DESC"); | |||
$query->bindValue(':ip', $ip); | |||
$query->execute() or error(db_error($query)); | |||
$args['bans'] = $query->fetchAll(PDO::FETCH_ASSOC); | |||
$args['bans'] = Bans::find($ip, false, true); | |||
} | |||
if (hasPermission($config['mod']['view_notes'])) { | |||
@@ -839,7 +834,7 @@ function mod_ban() { | |||
require_once 'inc/mod/ban.php'; | |||
ban($_POST['ip'], $_POST['reason'], parse_time($_POST['length']), $_POST['board'] == '*' ? false : $_POST['board']); | |||
Bans::new_ban($_POST['ip'], $_POST['reason'], $_POST['length'], $_POST['board'] == '*' ? false : $_POST['board']); | |||
if (isset($_POST['redirect'])) | |||
header('Location: ' . $_POST['redirect'], true, $config['redirect_http']); | |||
@@ -865,58 +860,27 @@ function mod_bans($page_no = 1) { | |||
if (preg_match('/^ban_(\d+)$/', $name, $match)) | |||
$unban[] = $match[1]; | |||
} | |||
if (isset($config['mod']['unban_limit'])){ | |||
if (count($unban) <= $config['mod']['unban_limit'] || $config['mod']['unban_limit'] == -1){ | |||
if (!empty($unban)) { | |||
query('DELETE FROM ``bans`` WHERE `id` = ' . implode(' OR `id` = ', $unban)) or error(db_error()); | |||
if (isset($config['mod']['unban_limit']) && $config['mod']['unban_limit'] && count($unban) > $config['mod']['unban_limit']) | |||
error(sprintf($config['error']['toomanyunban'], $config['mod']['unban_limit'], count($unban))); | |||
foreach ($unban as $id) { | |||
modLog("Removed ban #{$id}"); | |||
} | |||
foreach ($unban as $id) { | |||
Bans::delete($id, true); | |||
} | |||
} else { | |||
error(sprintf($config['error']['toomanyunban'], $config['mod']['unban_limit'], count($unban) )); | |||
} | |||
} else { | |||
if (!empty($unban)) { | |||
query('DELETE FROM ``bans`` WHERE `id` = ' . implode(' OR `id` = ', $unban)) or error(db_error()); | |||
foreach ($unban as $id) { | |||
modLog("Removed ban #{$id}"); | |||
} | |||
} | |||
} | |||
header('Location: ?/bans', true, $config['redirect_http']); | |||
return; | |||
} | |||
if ($config['mod']['view_banexpired']) { | |||
$query = prepare("SELECT ``bans``.*, `username` FROM ``bans`` LEFT JOIN ``mods`` ON `mod` = ``mods``.`id` ORDER BY (`expires` IS NOT NULL AND `expires` < :time), `set` DESC LIMIT :offset, :limit"); | |||
} else { | |||
// Filter out expired bans | |||
$query = prepare("SELECT ``bans``.*, `username` FROM ``bans`` INNER JOIN ``mods`` ON `mod` = ``mods``.`id` WHERE `expires` = 0 OR `expires` > :time ORDER BY `set` DESC LIMIT :offset, :limit"); | |||
} | |||
$query->bindValue(':time', time(), PDO::PARAM_INT); | |||
$query->bindValue(':limit', $config['mod']['banlist_page'], PDO::PARAM_INT); | |||
$query->bindValue(':offset', ($page_no - 1) * $config['mod']['banlist_page'], PDO::PARAM_INT); | |||
$query->execute() or error(db_error($query)); | |||
$bans = $query->fetchAll(PDO::FETCH_ASSOC); | |||
$bans = Bans::list_all(($page_no - 1) * $config['mod']['banlist_page'], $config['mod']['banlist_page']); | |||
if (empty($bans) && $page_no > 1) | |||
error($config['error']['404']); | |||
$query = prepare("SELECT COUNT(*) FROM ``bans``"); | |||
$query->execute() or error(db_error($query)); | |||
$count = $query->fetchColumn(); | |||
foreach ($bans as &$ban) { | |||
if (filter_var($ban['ip'], FILTER_VALIDATE_IP) !== false) | |||
$ban['real_ip'] = true; | |||
if (filter_var($ban['mask'], FILTER_VALIDATE_IP) !== false) | |||
$ban['single_addr'] = true; | |||
} | |||
mod_page(_('Ban list'), 'mod/ban_list.html', array('bans' => $bans, 'count' => $count)); | |||
mod_page(_('Ban list'), 'mod/ban_list.html', array('bans' => $bans, 'count' => Bans::count())); | |||
} | |||
@@ -1217,7 +1181,7 @@ function mod_ban_post($board, $delete, $post, $token = false) { | |||
if (isset($_POST['ip'])) | |||
$ip = $_POST['ip']; | |||
ban($ip, $_POST['reason'], parse_time($_POST['length']), $_POST['board'] == '*' ? false : $_POST['board']); | |||
Bans::new_ban($_POST['ip'], $_POST['reason'], $_POST['length'], $_POST['board'] == '*' ? false : $_POST['board']); | |||
if (isset($_POST['public_message'], $_POST['message'])) { | |||
// public ban message | |||
@@ -1,7 +1,7 @@ | |||
<?php | |||
// Installation/upgrade file | |||
define('VERSION', 'v0.9.6-dev-20'); | |||
define('VERSION', 'v0.9.6-dev-21'); | |||
require 'inc/functions.php'; | |||
@@ -412,6 +412,61 @@ if (file_exists($config['has_installed'])) { | |||
query("UPDATE ``mods`` SET `type` = 20 WHERE `type` = 1") or error(db_error()); | |||
query("UPDATE ``mods`` SET `type` = 30 WHERE `type` = 2") or error(db_error()); | |||
query("ALTER TABLE ``mods`` CHANGE `type` `type` smallint(1) NOT NULL") or error(db_error()); | |||
case 'v0.9.6-dev-20': | |||
query("CREATE TABLE IF NOT EXISTS `bans_new_temp` ( | |||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, | |||
`ipstart` varbinary(16) NOT NULL, | |||
`ipend` varbinary(16) DEFAULT NULL, | |||
`created` int(10) unsigned NOT NULL, | |||
`expires` int(10) unsigned DEFAULT NULL, | |||
`board` varchar(58) DEFAULT NULL, | |||
`creator` int(10) NOT NULL, | |||
`reason` text, | |||
`seen` tinyint(1) NOT NULL, | |||
`post` blob, | |||
PRIMARY KEY (`id`), | |||
KEY `expires` (`expires`), | |||
KEY `ipstart` (`ipstart`,`ipend`) | |||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1") or error(db_error()); | |||
$listquery = query("SELECT * FROM ``bans`` ORDER BY `id`") or error(db_error()); | |||
while ($ban = $listquery->fetch(PDO::FETCH_ASSOC)) { | |||
$query = prepare("INSERT INTO ``bans_new_temp`` VALUES | |||
(NULL, :ipstart, :ipend, :created, :expires, :board, :creator, :reason, :seen, NULL)"); | |||
$range = Bans::parse_range($ban['ip']); | |||
if ($range === false) { | |||
// Invalid retard ban; just skip it. | |||
continue; | |||
} | |||
$query->bindValue(':ipstart', $range[0]); | |||
if ($range[1] !== false && $range[1] != $range[0]) | |||
$query->bindValue(':ipend', $range[1]); | |||
else | |||
$query->bindValue(':ipend', null, PDO::PARAM_NULL); | |||
$query->bindValue(':created', $ban['set']); | |||
if ($ban['expires']) | |||
$query->bindValue(':expires', $ban['expires']); | |||
else | |||
$query->bindValue(':expires', null, PDO::PARAM_NULL); | |||
if ($ban['board']) | |||
$query->bindValue(':board', $ban['board']); | |||
else | |||
$query->bindValue(':board', null, PDO::PARAM_NULL); | |||
$query->bindValue(':creator', $ban['mod']); | |||
if ($ban['reason']) | |||
$query->bindValue(':reason', $ban['reason']); | |||
else | |||
$query->bindValue(':reason', null, PDO::PARAM_NULL); | |||
$query->bindValue(':seen', $ban['seen']); | |||
$query->execute() or error(db_error($query)); | |||
} | |||
case false: | |||
// Update version number | |||
file_write($config['has_installed'], VERSION); | |||
@@ -43,9 +43,23 @@ $(window).ready(function() { | |||
}, | |||
success: function(post_response) { | |||
if (post_response.error) { | |||
alert(post_response.error); | |||
$(form).find('input[type="submit"]').val(submit_txt); | |||
$(form).find('input[type="submit"]').removeAttr('disabled'); | |||
if (post_response.banned) { | |||
// You are banned. Must post the form normally so the user can see the ban message. | |||
do_not_ajax = true; | |||
$(form).find('input[type="submit"]').each(function() { | |||
var $replacement = $('<input type="hidden">'); | |||
$replacement.attr('name', $(this).attr('name')); | |||
$replacement.val(submit_txt); | |||
$(this) | |||
.after($replacement) | |||
.replaceWith($('<input type="button">').val(submit_txt)); | |||
}); | |||
$(form).submit(); | |||
} else { | |||
alert(post_response.error); | |||
$(form).find('input[type="submit"]').val(submit_txt); | |||
$(form).find('input[type="submit"]').removeAttr('disabled'); | |||
} | |||
} else if (post_response.redirect && post_response.id) { | |||
if (!$(form).find('input[name="thread"]').length) { | |||
document.location = post_response.redirect; | |||
@@ -84,7 +98,6 @@ $(window).ready(function() { | |||
}, | |||
error: function(xhr, status, er) { | |||
// An error occured | |||
// TODO | |||
do_not_ajax = true; | |||
$(form).find('input[type="submit"]').each(function() { | |||
var $replacement = $('<input type="hidden">'); | |||
@@ -30,7 +30,7 @@ | |||
{% endif %} | |||
<p> | |||
{% trans %}Your ban was filed on{% endtrans %} | |||
<strong>{{ ban.set|date(config.ban_date) }}</strong> {% trans %}and{% endtrans %} <span id="expires"> | |||
<strong>{{ ban.created|date(config.ban_date) }}</strong> {% trans %}and{% endtrans %} <span id="expires"> | |||
{% if ban.expires and time() >= ban.expires %} | |||
{% trans %} has since expired. Refresh the page to continue.{% endtrans %} | |||
{% elseif ban.expires %} | |||
@@ -17,10 +17,10 @@ | |||
<tr{% if ban.expires != 0 and ban.expires < time() %} style="text-decoration:line-through"{% endif %}> | |||
<td style="white-space: nowrap"> | |||
<input type="checkbox" name="ban_{{ ban.id }}"> | |||
{% if ban.real_ip %} | |||
<a href="?/IP/{{ ban.ip }}">{{ ban.ip }}</a> | |||
{% if ban.single_addr %} | |||
<a href="?/IP/{{ ban.mask }}">{{ ban.mask }}</a> | |||
{% else %} | |||
{{ ban.ip|e }} | |||
{{ ban.mask }} | |||
{% endif %} | |||
</td> | |||
<td> | |||
@@ -38,8 +38,8 @@ | |||
{% endif %} | |||
</td> | |||
<td style="white-space: nowrap"> | |||
<span title="{{ ban.set|date(config.post_date) }}"> | |||
{{ ban.set|ago }} ago | |||
<span title="{{ ban.created|date(config.post_date) }}"> | |||
{{ ban.created|ago }} ago | |||
</span> | |||
</td> | |||
<td style="white-space: nowrap"> | |||
@@ -77,7 +77,7 @@ | |||
{% endif %} | |||
{% endif %} | |||
{% elseif ban.mod == -1 %} | |||
{% elseif ban.creator == -1 %} | |||
<em>system</em> | |||
{% else %} | |||
<em>{% trans 'deleted?' %}</em> | |||
@@ -100,7 +100,7 @@ | |||
</tr> | |||
<tr> | |||
<th>{% trans 'IP' %}</th> | |||
<td>{{ ban.ip }}</td> | |||
<td>{{ ban.mask }}</td> | |||
</tr> | |||
<tr> | |||
<th>{% trans 'Reason' %}</th> | |||
@@ -124,7 +124,7 @@ | |||
</tr> | |||
<tr> | |||
<th>{% trans 'Set' %}</th> | |||
<td>{{ ban.set|date(config.post_date) }}</td> | |||
<td>{{ ban.created|date(config.post_date) }}</td> | |||
</tr> | |||
<tr> | |||
<th>{% trans 'Expires' %}</th> | |||