From fe9297aaaa9d7a9c641e141546fb54d4dfda806b Mon Sep 17 00:00:00 2001 From: 8chan Date: Thu, 9 Oct 2014 21:39:37 -0400 Subject: [PATCH] Attempt to hide IPs from board volunteers --- .gitignore | 2 + inc/functions.php | 30 +++- inc/instance-config.php | 2 + .../Twig/Extensions/Extension/Tinyboard.php | 4 + inc/mod/pages.php | 109 ++++++++++- mod.php | 2 + templates/mod/ban_form.html | 8 +- templates/mod/view_ip_less.html | 170 ++++++++++++++++++ templates/post/ip.html | 2 + 9 files changed, 326 insertions(+), 3 deletions(-) create mode 100644 templates/mod/view_ip_less.html diff --git a/.gitignore b/.gitignore index add30777..5bc45780 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,5 @@ Thumbs.db #vichan custom favicon.ico /static/spoiler.png + +/inc/locale/ja_JP/* diff --git a/inc/functions.php b/inc/functions.php index d1b1410b..85146834 100755 --- a/inc/functions.php +++ b/inc/functions.php @@ -335,7 +335,7 @@ function create_antibot($board, $thread = null) { } function rebuildThemes($action, $boardname = false) { - global $config, $board, $current_locale; + global $config, $board, $current_locale, $error; // Save the global variables $_config = $config; @@ -2406,3 +2406,31 @@ function diceRoller($post) { } } } + +function less_ip($ip) { + $ipv6 = (strstr($ip, ':') !== false); + + $in_addr = inet_pton($ip); + + if ($ipv6) { + // Not sure how many to mask for IPv6, opinions? + $mask = inet_pton('ffff:ffff:ffff:ffff:ffff:0:0:0'); + } else { + $mask = inet_pton('255.255.0.0'); + } + + $final = inet_ntop($in_addr & $mask); + return str_replace(array(':0', '.0'), array(':x', '.x'), $final); +} + +function less_hostmask($hostmask) { + $parts = explode('.', $hostmask); + + if (sizeof($parts) < 3) + return $hostmask; + + $parts[0] = 'x'; + $parts[1] = 'x'; + + return implode('.', $parts); +} diff --git a/inc/instance-config.php b/inc/instance-config.php index cebf00c8..ee5474e0 100644 --- a/inc/instance-config.php +++ b/inc/instance-config.php @@ -77,6 +77,8 @@ ' %s', ); //$config['mod']['view_banlist'] = SUPERMOD; + $config['mod']['show_ip'] = SUPERMOD; + $config['mod']['show_ip_less'] = MOD; $config['mod']['manageusers'] = SUPERMOD; $config['mod']['noticeboard_post'] = SUPERMOD; $config['mod']['search'] = SUPERMOD; diff --git a/inc/lib/Twig/Extensions/Extension/Tinyboard.php b/inc/lib/Twig/Extensions/Extension/Tinyboard.php index 75af6890..65578582 100644 --- a/inc/lib/Twig/Extensions/Extension/Tinyboard.php +++ b/inc/lib/Twig/Extensions/Extension/Tinyboard.php @@ -20,6 +20,7 @@ class Twig_Extensions_Extension_Tinyboard extends Twig_Extension new Twig_SimpleFilter('hasPermission', 'twig_hasPermission_filter'), new Twig_SimpleFilter('date', 'twig_date_filter'), new Twig_SimpleFilter('remove_whitespace', 'twig_remove_whitespace_filter'), + new Twig_SimpleFilter('less_ip', 'twig_less_ip'), new Twig_SimpleFilter('count', 'count'), new Twig_SimpleFilter('ago', 'ago'), new Twig_SimpleFilter('until', 'until'), @@ -131,3 +132,6 @@ function twig_secure_link_confirm($text, $title, $confirm_message, $href) { function twig_secure_link($href) { return $href . '/' . make_secure_link_token($href); } +function twig_less_ip($ip) { + return less_ip($ip); +} diff --git a/inc/mod/pages.php b/inc/mod/pages.php index 2bb14be9..95375914 100644 --- a/inc/mod/pages.php +++ b/inc/mod/pages.php @@ -775,6 +775,9 @@ function mod_ip_remove_note($ip, $id) { function mod_page_ip($ip) { global $config, $mod; + + if (!hasPermission($config['mod']['show_ip'])) + error($config['error']['noaccess']); if (filter_var($ip, FILTER_VALIDATE_IP) === false) error("Invalid IP address."); @@ -865,6 +868,107 @@ function mod_page_ip($ip) { mod_page(sprintf('%s: %s', _('IP'), $ip), 'mod/view_ip.html', $args, $args['hostname']); } +function mod_page_ip_less($b, $id) { + global $config, $mod; + + $query = prepare(sprintf('SELECT `ip` FROM ``posts_%s`` WHERE `id` = :id', $b)); + $query->bindValue(':id', $id); + $query->execute() or error(db_error($query)); + + $result = $query->fetch(PDO::FETCH_ASSOC); + + if ($result) { + $ip = $result['ip']; + } else { + error(_('Could not find that post.')); + } + + if (filter_var($ip, FILTER_VALIDATE_IP) === false) + error("Invalid IP address."); + + if (isset($_POST['ban_id'], $_POST['unban'])) { + if (!hasPermission($config['mod']['unban'])) + error($config['error']['noaccess']); + + Bans::delete($_POST['ban_id'], true); + + header('Location: ?/IP/' . $ip . '#bans', true, $config['redirect_http']); + return; + } + + if (isset($_POST['note'])) { + if (!hasPermission($config['mod']['create_notes'])) + error($config['error']['noaccess']); + + $_POST['note'] = escape_markup_modifiers($_POST['note']); + markup($_POST['note']); + $query = prepare('INSERT INTO ``ip_notes`` VALUES (NULL, :ip, :mod, :time, :body)'); + $query->bindValue(':ip', $ip); + $query->bindValue(':mod', $mod['id']); + $query->bindValue(':time', time()); + $query->bindValue(':body', $_POST['note']); + $query->execute() or error(db_error($query)); + + modLog("Added a note for {$ip}"); + + header('Location: ?/IP/' . $ip . '#notes', true, $config['redirect_http']); + return; + } + + $args = array(); + $args['ip'] = $ip; + $args['posts'] = array(); + + if ($config['mod']['dns_lookup']) + $args['hostname'] = rDNS($ip); + + openBoard($b); + + $query = prepare(sprintf('SELECT * FROM ``posts_%s`` WHERE `ip` = :ip ORDER BY `sticky` DESC, `id` DESC LIMIT :limit', $b)); + $query->bindValue(':ip', $ip); + $query->bindValue(':limit', $config['mod']['ip_recentposts'], PDO::PARAM_INT); + $query->execute() or error(db_error($query)); + + while ($post = $query->fetch(PDO::FETCH_ASSOC)) { + if (!$post['thread']) { + $po = new Thread($post, '?/', $mod, false); + } else { + $po = new Post($post, '?/', $mod); + } + + if (!isset($args['posts'][$b])) + $args['posts'][$b] = array('board' => $b, 'posts' => array()); + $args['posts'][$b]['posts'][] = $po->build(true); + } + + $args['boards'] = listBoards(); + $args['token'] = make_secure_link_token('ban'); + + if (hasPermission($config['mod']['view_ban'])) { + $args['bans'] = Bans::find($ip, false, true); + } + + if (hasPermission($config['mod']['view_notes'])) { + $query = prepare("SELECT ``ip_notes``.*, `username` FROM ``ip_notes`` LEFT JOIN ``mods`` ON `mod` = ``mods``.`id` WHERE `ip` = :ip ORDER BY `time` DESC"); + $query->bindValue(':ip', $ip); + $query->execute() or error(db_error($query)); + $args['notes'] = $query->fetchAll(PDO::FETCH_ASSOC); + } + + if (hasPermission($config['mod']['modlog_ip'])) { + $query = prepare("SELECT `username`, `mod`, `ip`, `board`, `time`, `text` FROM ``modlogs`` LEFT JOIN ``mods`` ON `mod` = ``mods``.`id` WHERE `text` LIKE :search ORDER BY `time` DESC LIMIT 50"); + $query->bindValue(':search', '%' . $ip . '%'); + $query->execute() or error(db_error($query)); + $args['logs'] = $query->fetchAll(PDO::FETCH_ASSOC); + } else { + $args['logs'] = array(); + } + + $args['security_token'] = make_secure_link_token('IP_less/' . $b . '/' . $id); + + mod_page(sprintf('%s: %s', _('IP'), less_ip($ip)), 'mod/view_ip_less.html', $args, less_hostmask($args['hostname'])); +} + function mod_ban() { global $config, $mod; @@ -1417,8 +1521,11 @@ function mod_ban_post($board, $delete, $post, $token = false) { if (isset($_POST['ip'])) $ip = $_POST['ip']; + + if (isset($_POST['range'])) + $ip = $ip . $_POST['range']; - Bans::new_ban($_POST['ip'], $_POST['reason'], $_POST['length'], $_POST['board'] == '*' ? false : $_POST['board'], + Bans::new_ban($ip, $_POST['reason'], $_POST['length'], $_POST['board'] == '*' ? false : $_POST['board'], false, $config['ban_show_post'] ? $_post : false); if (isset($_POST['public_message'], $_POST['message'])) { diff --git a/mod.php b/mod.php index 3f14e2ed..654d23fe 100644 --- a/mod.php +++ b/mod.php @@ -60,6 +60,8 @@ $pages = array( '/IP/([\w.:]+)' => 'secure_POST ip', // view ip address '/IP/([\w.:]+)/remove_note/(\d+)' => 'secure ip_remove_note', // remove note from ip address + '/IP_less/(\%b)/(\d+)' => 'secure_POST ip_less', // view ip address (limited for user privacy) + '/IP_less/([\w.:]+)/remove_note/(\d+)' => 'secure ip_remove_note', // remove note from ip address '/ban' => 'secure_POST ban', // new ban '/bans' => 'secure_POST bans', // ban list diff --git a/templates/mod/ban_form.html b/templates/mod/ban_form.html index 01cfc0a0..bf91594e 100644 --- a/templates/mod/ban_form.html +++ b/templates/mod/ban_form.html @@ -23,7 +23,13 @@ {% if not hide_ip %} {% else %} - {% trans 'hidden' %} + {{ ip|less_ip }}  + {% endif %} diff --git a/templates/mod/view_ip_less.html b/templates/mod/view_ip_less.html new file mode 100644 index 00000000..a93ee6a3 --- /dev/null +++ b/templates/mod/view_ip_less.html @@ -0,0 +1,170 @@ +{% for board_posts in posts %} + {% if board_posts.board in mod.boards or mod.boards.0 == '*' %} +
+ + + {{ config.board_abbreviation|sprintf(board_posts.board) }} + + + {{ board_posts.posts|join('
') }} +
+ {% endif %} +{% endfor %} + +{% if mod|hasPermission(config.mod.view_notes) %} +
+ + {% set notes_on_record = 'note' ~ (notes|count != 1 ? 's' : '') ~ ' on record' %} + {{ notes|count }} {% trans notes_on_record %} + + + {% if notes|count > 0 %} + + + + + + {% if mod|hasPermission(config.mod.remove_notes) %} + + {% endif %} + + {% for note in notes %} + + + + + {% if mod|hasPermission(config.mod.remove_notes) %} + + {% endif %} + + {% endfor %} +
{% trans 'Staff' %}{% trans 'Note' %}{% trans 'Date' %}{% trans 'Actions' %}
+ {% if note.username %} + {{ note.username|e }} + {% else %} + {% trans 'deleted?' %} + {% endif %} + + {{ note.body }} + + {{ note.time|date(config.post_date) }} + + + [{% trans 'remove' %}] + +
+ {% endif %} + + {% if mod|hasPermission(config.mod.create_notes) %} +
+ + + + + + + + + + + + + + +
{% trans 'Staff' %}{{ mod.username|e }}
+ + + +
+
+ {% endif %} +
+{% endif %} + +{% if bans|count > 0 and mod|hasPermission(config.mod.view_ban) %} +
+ {% set bans_on_record = 'ban' ~ (bans|count != 1 ? 's' : '') ~ ' on record' %} + {{ bans|count }} {% trans bans_on_record %} + + {% for ban in bans %} + {% if ban.board in mod.boards or mod.boards.0 == '*' %} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{% trans 'Status' %} + {% if config.mod.view_banexpired and ban.expires != 0 and ban.expires < time() %} + {% trans 'Expired' %} + {% else %} + {% trans 'Active' %} + {% endif %} +
{% trans 'IP' %}{{ ban.mask }}
{% trans 'Reason' %} + {% if ban.reason %} + {{ ban.reason }} + {% else %} + {% trans 'no reason' %} + {% endif %} +
{% trans 'Board' %} + {% if ban.board %} + {{ config.board_abbreviation|sprintf(ban.board) }} + {% else %} + {% trans 'all boards' %} + {% endif %} +
{% trans 'Set' %}{{ ban.created|date(config.post_date) }}
{% trans 'Expires' %} + {% if ban.expires %} + {{ ban.expires|date(config.post_date) }} + {% else %} + {% trans 'never' %} + {% endif %} +
{% trans 'Seen' %} + {% if ban.seen %} + {% trans 'Yes' %} + {% else %} + {% trans 'No' %} + {% endif %} +
{% trans 'Staff' %} + {% if ban.username %} + {{ ban.username|e }} + {% else %} + {% trans 'deleted?' %} + {% endif %} +
+ + +
+ {% endif %} + {% endfor %} +
+{% endif %} + diff --git a/templates/post/ip.html b/templates/post/ip.html index 11581ff9..cd53f67a 100644 --- a/templates/post/ip.html +++ b/templates/post/ip.html @@ -1,3 +1,5 @@ {% if post.mod and post.mod|hasPermission(config.mod.show_ip, board.uri) %} [{{ post.ip }}] +{% elseif post.mod and post.mod|hasPermission(config.mod.show_ip_less, board.uri) %} + [{{ post.ip|less_ip }}] {% endif %}