1
0
mirror of https://github.com/vichan-devel/vichan.git synced 2025-01-31 04:13:49 +01:00

Attempt to hide IPs from board volunteers

This commit is contained in:
8chan 2014-10-09 21:39:37 -04:00
parent 3e88cc23fb
commit fe9297aaaa
9 changed files with 326 additions and 3 deletions

2
.gitignore vendored
View File

@ -43,3 +43,5 @@ Thumbs.db
#vichan custom
favicon.ico
/static/spoiler.png
/inc/locale/ja_JP/*

View File

@ -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);
}

View File

@ -77,6 +77,8 @@
'<span class="capcode" style="color:brown;font-weight:bold"> <img src="/static/paw.svg" height="12" width="12"> %s</span>',
);
//$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;

View File

@ -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);
}

View File

@ -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 <a href=\"?/IP/{$ip}\">{$ip}</a>");
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'])) {

View File

@ -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

View File

@ -23,7 +23,13 @@
{% if not hide_ip %}
<input type="text" name="ip" id="ip" size="30" maxlength="40" value="{{ ip }}">
{% else %}
<em>{% trans 'hidden' %}</em>
{{ ip|less_ip }}&nbsp;
<select name="range">
<option value="">no range ban</option>
{% for i in range(29, 12) %}
<option value="/{{i}}">/{{i}}</option>
{% endfor %}
</select>
{% endif %}
</td>
</tr>

View File

@ -0,0 +1,170 @@
{% for board_posts in posts %}
{% if board_posts.board in mod.boards or mod.boards.0 == '*' %}
<fieldset>
<legend>
<a href="?/{{ config.board_path|sprintf(board_posts.board) }}{{ config.file_index }}">
{{ config.board_abbreviation|sprintf(board_posts.board) }}
</a>
</legend>
{{ board_posts.posts|join('<hr>') }}
</fieldset>
{% endif %}
{% endfor %}
{% if mod|hasPermission(config.mod.view_notes) %}
<fieldset id="notes">
<legend>
{% set notes_on_record = 'note' ~ (notes|count != 1 ? 's' : '') ~ ' on record' %}
<legend>{{ notes|count }} {% trans notes_on_record %}</legend>
</legend>
{% if notes|count > 0 %}
<table class="modlog">
<tr>
<th>{% trans 'Staff' %}</th>
<th>{% trans 'Note' %}</th>
<th>{% trans 'Date' %}</th>
{% if mod|hasPermission(config.mod.remove_notes) %}
<th>{% trans 'Actions' %}</th>
{% endif %}
</tr>
{% for note in notes %}
<tr>
<td class="minimal">
{% if note.username %}
<a href="?/new_PM/{{ note.username|e }}">{{ note.username|e }}</a>
{% else %}
<em>{% trans 'deleted?' %}</em>
{% endif %}
</td>
<td>
{{ note.body }}
</td>
<td class="minimal">
{{ note.time|date(config.post_date) }}
</td>
{% if mod|hasPermission(config.mod.remove_notes) %}
<td class="minimal">
<a href="?/IP/{{ ip }}/remove_note/{{ note.id }}">
<small>[{% trans 'remove' %}]</small>
</a>
</td>
{% endif %}
</tr>
{% endfor %}
</table>
{% endif %}
{% if mod|hasPermission(config.mod.create_notes) %}
<form action="" method="post" style="margin:0">
<input type="hidden" name="token" value="{{ security_token }}">
<table>
<tr>
<th>{% trans 'Staff' %}</th>
<td>{{ mod.username|e }}</td>
</tr>
<tr>
<th>
<label for="note">{% trans 'Note' %}</label>
</th>
<td>
<textarea id="note" name="note" rows="5" cols="30"></textarea>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="{% trans 'New note' %}"></td>
</tr>
</table>
</form>
{% endif %}
</fieldset>
{% endif %}
{% if bans|count > 0 and mod|hasPermission(config.mod.view_ban) %}
<fieldset id="bans">
{% set bans_on_record = 'ban' ~ (bans|count != 1 ? 's' : '') ~ ' on record' %}
<legend>{{ bans|count }} {% trans bans_on_record %}</legend>
{% for ban in bans %}
{% if ban.board in mod.boards or mod.boards.0 == '*' %}
<form action="" method="post" style="text-align:center">
<input type="hidden" name="token" value="{{ security_token }}">
<table style="width:400px;margin-bottom:10px;border-bottom:1px solid #ddd;padding:5px">
<tr>
<th>{% trans 'Status' %}</th>
<td>
{% if config.mod.view_banexpired and ban.expires != 0 and ban.expires < time() %}
{% trans 'Expired' %}
{% else %}
{% trans 'Active' %}
{% endif %}
</td>
</tr>
<tr>
<th>{% trans 'IP' %}</th>
<td>{{ ban.mask }}</td>
</tr>
<tr>
<th>{% trans 'Reason' %}</th>
<td>
{% if ban.reason %}
{{ ban.reason }}
{% else %}
<em>{% trans 'no reason' %}</em>
{% endif %}
</td>
</tr>
<tr>
<th>{% trans 'Board' %}</th>
<td>
{% if ban.board %}
{{ config.board_abbreviation|sprintf(ban.board) }}
{% else %}
<em>{% trans 'all boards' %}</em>
{% endif %}
</td>
</tr>
<tr>
<th>{% trans 'Set' %}</th>
<td>{{ ban.created|date(config.post_date) }}</td>
</tr>
<tr>
<th>{% trans 'Expires' %}</th>
<td>
{% if ban.expires %}
{{ ban.expires|date(config.post_date) }}
{% else %}
<em>{% trans 'never' %}</em>
{% endif %}
</td>
</tr>
<tr>
<th>{% trans 'Seen' %}</th>
<td>
{% if ban.seen %}
{% trans 'Yes' %}
{% else %}
{% trans 'No' %}
{% endif %}
</td>
</tr>
<tr>
<th>{% trans 'Staff' %}</th>
<td>
{% if ban.username %}
{{ ban.username|e }}
{% else %}
<em>{% trans 'deleted?' %}</em>
{% endif %}
</td>
</tr>
</table>
<input type="hidden" name="ban_id" value="{{ ban.id }}">
<input type="submit" name="unban" value="{% trans 'Remove ban' %}">
</form>
{% endif %}
{% endfor %}
</fieldset>
{% endif %}

View File

@ -1,3 +1,5 @@
{% if post.mod and post.mod|hasPermission(config.mod.show_ip, board.uri) %}
[<a class="ip-link" style="margin:0;" href="?/IP/{{ post.ip }}">{{ post.ip }}</a>]
{% elseif post.mod and post.mod|hasPermission(config.mod.show_ip_less, board.uri) %}
[<a class="ip-link" style="margin:0;" href="?/IP_less/{{ board.dir }}{{ post.id }}">{{ post.ip|less_ip }}</a>]
{% endif %}