forked from leftypol/leftypol
Merge branch '22-browse-by-password' into 'config'
Resolve "Browse by password" Closes #22 See merge request leftypol/leftypol!17
This commit is contained in:
commit
5c176b95e7
8 changed files with 310 additions and 117 deletions
|
@ -17,16 +17,7 @@ class UserPostQueries {
|
|||
$this->pdo = $pdo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a page of user posts.
|
||||
*
|
||||
* @param array $board_uris The uris of the boards that should be included.
|
||||
* @param string $ip The IP of the target user.
|
||||
* @param integer $page_size The Number of posts that should be fetched.
|
||||
* @param string|null $cursor The directional cursor to fetch the next or previous page. Null to start from the beginning.
|
||||
* @return PageFetchResult
|
||||
*/
|
||||
public function fetchPaginatedByIp(array $board_uris, string $ip, int $page_size, ?string $cursor = null): PageFetchResult {
|
||||
private function paginate(array $board_uris, int $page_size, ?string $cursor, callable $callback): PageFetchResult {
|
||||
// Decode the cursor.
|
||||
if ($cursor !== null) {
|
||||
list($cursor_type, $uri_id_cursor_map) = Net\decode_cursor($cursor);
|
||||
|
@ -41,37 +32,15 @@ class UserPostQueries {
|
|||
|
||||
foreach ($board_uris as $uri) {
|
||||
// Extract the cursor relative to the board.
|
||||
$id_cursor = false;
|
||||
if (isset($uri_id_cursor_map[$uri])) {
|
||||
$start_id = null;
|
||||
if ($cursor_type !== null && isset($uri_id_cursor_map[$uri])) {
|
||||
$value = $uri_id_cursor_map[$uri];
|
||||
if (\is_numeric($value)) {
|
||||
$id_cursor = (int)$value;
|
||||
$start_id = (int)$value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($id_cursor === false) {
|
||||
$query = $this->pdo->prepare(sprintf('SELECT * FROM `posts_%s` WHERE `ip` = :ip ORDER BY `sticky` DESC, `id` DESC LIMIT :limit', $uri));
|
||||
$query->bindValue(':ip', $ip);
|
||||
$query->bindValue(':limit', $page_size + 1, \PDO::PARAM_INT); // Always fetch more.
|
||||
$query->execute();
|
||||
$posts = $query->fetchAll(\PDO::FETCH_ASSOC);
|
||||
} elseif ($cursor_type === self::CURSOR_TYPE_NEXT) {
|
||||
$query = $this->pdo->prepare(sprintf('SELECT * FROM `posts_%s` WHERE `ip` = :ip AND `id` <= :start_id ORDER BY `sticky` DESC, `id` DESC LIMIT :limit', $uri));
|
||||
$query->bindValue(':ip', $ip);
|
||||
$query->bindValue(':start_id', $id_cursor, \PDO::PARAM_INT);
|
||||
$query->bindValue(':limit', $page_size + 2, \PDO::PARAM_INT); // Always fetch more.
|
||||
$query->execute();
|
||||
$posts = $query->fetchAll(\PDO::FETCH_ASSOC);
|
||||
} elseif ($cursor_type === self::CURSOR_TYPE_PREV) {
|
||||
$query = $this->pdo->prepare(sprintf('SELECT * FROM `posts_%s` WHERE `ip` = :ip AND `id` >= :start_id ORDER BY `sticky` ASC, `id` ASC LIMIT :limit', $uri));
|
||||
$query->bindValue(':ip', $ip);
|
||||
$query->bindValue(':start_id', $id_cursor, \PDO::PARAM_INT);
|
||||
$query->bindValue(':limit', $page_size + 2, \PDO::PARAM_INT); // Always fetch more.
|
||||
$query->execute();
|
||||
$posts = \array_reverse($query->fetchAll(\PDO::FETCH_ASSOC));
|
||||
} else {
|
||||
throw new \RuntimeException("Unknown cursor type '$cursor_type'");
|
||||
}
|
||||
$posts = $callback($uri, $cursor_type, $start_id, $page_size);
|
||||
|
||||
$posts_count = \count($posts);
|
||||
|
||||
|
@ -79,7 +48,7 @@ class UserPostQueries {
|
|||
$has_extra_prev_post = true;
|
||||
$has_extra_end_post = true;
|
||||
} elseif ($posts_count === $page_size + 1) {
|
||||
$has_extra_prev_post = $id_cursor !== false && $id_cursor === (int)$posts[0]['id'];
|
||||
$has_extra_prev_post = $start_id !== null && $start_id === (int)$posts[0]['id'];
|
||||
$has_extra_end_post = !$has_extra_prev_post;
|
||||
} else {
|
||||
$has_extra_prev_post = false;
|
||||
|
@ -112,4 +81,78 @@ class UserPostQueries {
|
|||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a page of user posts.
|
||||
*
|
||||
* @param array $board_uris The uris of the boards that should be included.
|
||||
* @param string $ip The IP of the target user.
|
||||
* @param integer $page_size The Number of posts that should be fetched.
|
||||
* @param string|null $cursor The directional cursor to fetch the next or previous page. Null to start from the beginning.
|
||||
* @return PageFetchResult
|
||||
*/
|
||||
public function fetchPaginatedByIp(array $board_uris, string $ip, int $page_size, ?string $cursor = null): PageFetchResult {
|
||||
return $this->paginate($board_uris, $page_size, $cursor, function($uri, $cursor_type, $start_id, $page_size) use ($ip) {
|
||||
if ($cursor_type === null) {
|
||||
$query = $this->pdo->prepare(sprintf('SELECT * FROM `posts_%s` WHERE `ip` = :ip ORDER BY `sticky` DESC, `id` DESC LIMIT :limit', $uri));
|
||||
$query->bindValue(':ip', $ip);
|
||||
$query->bindValue(':limit', $page_size + 1, \PDO::PARAM_INT); // Always fetch more.
|
||||
$query->execute();
|
||||
return $query->fetchAll(\PDO::FETCH_ASSOC);
|
||||
} elseif ($cursor_type === self::CURSOR_TYPE_NEXT) {
|
||||
$query = $this->pdo->prepare(sprintf('SELECT * FROM `posts_%s` WHERE `ip` = :ip AND `id` <= :start_id ORDER BY `sticky` DESC, `id` DESC LIMIT :limit', $uri));
|
||||
$query->bindValue(':ip', $ip);
|
||||
$query->bindValue(':start_id', $start_id, \PDO::PARAM_INT);
|
||||
$query->bindValue(':limit', $page_size + 2, \PDO::PARAM_INT); // Always fetch more.
|
||||
$query->execute();
|
||||
return $query->fetchAll(\PDO::FETCH_ASSOC);
|
||||
} elseif ($cursor_type === self::CURSOR_TYPE_PREV) {
|
||||
$query = $this->pdo->prepare(sprintf('SELECT * FROM `posts_%s` WHERE `ip` = :ip AND `id` >= :start_id ORDER BY `sticky` ASC, `id` ASC LIMIT :limit', $uri));
|
||||
$query->bindValue(':ip', $ip);
|
||||
$query->bindValue(':start_id', $start_id, \PDO::PARAM_INT);
|
||||
$query->bindValue(':limit', $page_size + 2, \PDO::PARAM_INT); // Always fetch more.
|
||||
$query->execute();
|
||||
return \array_reverse($query->fetchAll(\PDO::FETCH_ASSOC));
|
||||
} else {
|
||||
throw new \RuntimeException("Unknown cursor type '$cursor_type'");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a page of user posts.
|
||||
*
|
||||
* @param array $board_uris The uris of the boards that should be included.
|
||||
* @param string $password The password of the target user.
|
||||
* @param integer $page_size The Number of posts that should be fetched.
|
||||
* @param string|null $cursor The directional cursor to fetch the next or previous page. Null to start from the beginning.
|
||||
* @return PageFetchResult
|
||||
*/
|
||||
public function fetchPaginateByPassword(array $board_uris, string $password, int $page_size, ?string $cursor = null): PageFetchResult {
|
||||
return $this->paginate($board_uris, $page_size, $cursor, function($uri, $cursor_type, $start_id, $page_size) use ($password) {
|
||||
if ($cursor_type === null) {
|
||||
$query = $this->pdo->prepare(sprintf('SELECT * FROM `posts_%s` WHERE `password` = :password ORDER BY `sticky` DESC, `id` DESC LIMIT :limit', $uri));
|
||||
$query->bindValue(':password', $password);
|
||||
$query->bindValue(':limit', $page_size + 1, \PDO::PARAM_INT); // Always fetch more.
|
||||
$query->execute();
|
||||
return $query->fetchAll(\PDO::FETCH_ASSOC);
|
||||
} elseif ($cursor_type === self::CURSOR_TYPE_NEXT) {
|
||||
$query = $this->pdo->prepare(sprintf('SELECT * FROM `posts_%s` WHERE `password` = :password AND `id` <= :start_id ORDER BY `sticky` DESC, `id` DESC LIMIT :limit', $uri));
|
||||
$query->bindValue(':password', $password);
|
||||
$query->bindValue(':start_id', $start_id, \PDO::PARAM_INT);
|
||||
$query->bindValue(':limit', $page_size + 2, \PDO::PARAM_INT); // Always fetch more.
|
||||
$query->execute();
|
||||
return $query->fetchAll(\PDO::FETCH_ASSOC);
|
||||
} elseif ($cursor_type === self::CURSOR_TYPE_PREV) {
|
||||
$query = $this->pdo->prepare(sprintf('SELECT * FROM `posts_%s` WHERE `password` = :ip AND `password` >= :start_id ORDER BY `sticky` ASC, `id` ASC LIMIT :limit', $uri));
|
||||
$query->bindValue(':password', $password);
|
||||
$query->bindValue(':start_id', $start_id, \PDO::PARAM_INT);
|
||||
$query->bindValue(':limit', $page_size + 2, \PDO::PARAM_INT); // Always fetch more.
|
||||
$query->execute();
|
||||
return \array_reverse($query->fetchAll(\PDO::FETCH_ASSOC));
|
||||
} else {
|
||||
throw new \RuntimeException("Unknown cursor type '$cursor_type'");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1524,8 +1524,8 @@
|
|||
|
||||
// Do DNS lookups on IP addresses to get their hostname for the moderator IP pages (?/IP/x.x.x.x).
|
||||
$config['mod']['dns_lookup'] = true;
|
||||
// How many recent posts, per board, to show in each page of ?/IP/x.x.x.x.
|
||||
$config['mod']['ip_recentposts'] = 5;
|
||||
// How many recent posts, per board, to show in ?/user_posts/ip/x.x.x.x. and ?/user_posts/passwd/xxxxxxxx
|
||||
$config['mod']['recent_user_posts'] = 5;
|
||||
|
||||
// Number of posts to display on the reports page.
|
||||
$config['mod']['recent_reports'] = 10;
|
||||
|
|
|
@ -854,23 +854,23 @@ function mod_ip_remove_note(Context $ctx, $ip, $id) {
|
|||
error($config['error']['noaccess']);
|
||||
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP) === false)
|
||||
error("Invalid IP address.");
|
||||
error('Invalid IP address');
|
||||
|
||||
$query = prepare('DELETE FROM ``ip_notes`` WHERE `ip` = :ip AND `id` = :id');
|
||||
$query->bindValue(':ip', $ip);
|
||||
$query->bindValue(':id', $id);
|
||||
$query->execute() or error(db_error($query));
|
||||
|
||||
modLog("Removed a note for <a href=\"?/IP/{$ip}\">{$ip}</a>");
|
||||
modLog("Removed a note for <a href=\"?/user_posts/ip/{$ip}\">{$ip}</a>");
|
||||
|
||||
header('Location: ?/IP/' . $ip . '#notes', true, $config['redirect_http']);
|
||||
\header("Location: ?/user_posts/ip/$ip#notes", true, $config['redirect_http']);
|
||||
}
|
||||
|
||||
function mod_ip(Context $ctx, $ip, string $encoded_cursor = null) {
|
||||
global $config, $mod;
|
||||
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP) === false)
|
||||
error("Invalid IP address.");
|
||||
error('Invalid IP address');
|
||||
|
||||
if (isset($_POST['ban_id'], $_POST['unban'])) {
|
||||
if (!hasPermission($config['mod']['unban']))
|
||||
|
@ -879,9 +879,9 @@ function mod_ip(Context $ctx, $ip, string $encoded_cursor = null) {
|
|||
Bans::delete($_POST['ban_id'], true, $mod['boards']);
|
||||
|
||||
if (empty($encoded_cursor)) {
|
||||
header("Location: ?/IP/$ip#bans", true, $config['redirect_http']);
|
||||
\header("Location: ?/user_posts/ip/$ip#bans", true, $config['redirect_http']);
|
||||
} else {
|
||||
header("Location: ?/IP/$ip/cursor/$encoded_cursor#bans", true, $config['redirect_http']);
|
||||
\header("Location: ?/user_posts/ip/$ip/cursor/$encoded_cursor#bans", true, $config['redirect_http']);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -901,64 +901,48 @@ function mod_ip(Context $ctx, $ip, string $encoded_cursor = null) {
|
|||
|
||||
Cache::delete("mod_page_ip_view_notes_$ip");
|
||||
|
||||
modLog("Added a note for <a href=\"?/IP/{$ip}\">{$ip}</a>");
|
||||
modLog("Added a note for <a href=\"?/user_posts/ip/{$ip}\">{$ip}</a>");
|
||||
|
||||
if (empty($encoded_cursor)) {
|
||||
header("Location: ?/IP/$ip#notes", true, $config['redirect_http']);
|
||||
\header("Location: ?/user_posts/ip/$ip#notes", true, $config['redirect_http']);
|
||||
} else {
|
||||
header("Location: ?/IP/$ip/cursor/$encoded_cursor#notes", true, $config['redirect_http']);
|
||||
\header("Location: ?/user_posts/ip/$ip/cursor/$encoded_cursor#notes", true, $config['redirect_http']);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($encoded_cursor)) {
|
||||
\header("Location: ?/user_posts/ip/$ip", true, 308);
|
||||
} else {
|
||||
\header("Location: ?/user_posts/ip/$ip/cursor/$encoded_cursor", true, 308);
|
||||
}
|
||||
}
|
||||
|
||||
function mod_user_posts_by_ip(Context $ctx, string $ip, string $encoded_cursor = null) {
|
||||
global $mod;
|
||||
|
||||
if (\filter_var($ip, \FILTER_VALIDATE_IP) === false){
|
||||
error('Invalid IP address');
|
||||
}
|
||||
|
||||
$config = $ctx->get('config');
|
||||
|
||||
$args = [
|
||||
'ip' => $ip,
|
||||
'posts' => []
|
||||
];
|
||||
|
||||
if (isset($config['mod']['ip_recentposts'])) {
|
||||
// TODO log to migrate.
|
||||
$page_size = $config['mod']['ip_recentposts'];
|
||||
} else {
|
||||
$page_size = $config['mod']['recent_user_posts'];
|
||||
}
|
||||
|
||||
if ($config['mod']['dns_lookup']) {
|
||||
$args['hostname'] = rDNS($ip);
|
||||
}
|
||||
|
||||
$boards = listBoards();
|
||||
|
||||
$queryable_uris = [];
|
||||
foreach ($boards as $board) {
|
||||
$uri = $board['uri'];
|
||||
if (hasPermission($config['mod']['show_ip'], $uri)) {
|
||||
$queryable_uris[] = $uri;
|
||||
}
|
||||
}
|
||||
|
||||
$queries = $ctx->get(UserPostQueries::class);
|
||||
$result = $queries->fetchPaginatedByIp($queryable_uris, $ip, $config['mod']['ip_recentposts'], $encoded_cursor);
|
||||
|
||||
$args['cursor_prev'] = $result->cursor_prev;
|
||||
$args['cursor_next'] = $result->cursor_next;
|
||||
|
||||
foreach($boards as $board) {
|
||||
$uri = $board['uri'];
|
||||
// The Thread and Post classes rely on some implicit board parameter set by openBoard.
|
||||
openBoard($uri);
|
||||
|
||||
// Finally load the post contents and build them.
|
||||
foreach ($result->by_uri[$uri] as $post) {
|
||||
if (!$post['thread']) {
|
||||
$po = new Thread($post, '?/', $mod, false);
|
||||
} else {
|
||||
$po = new Post($post, '?/', $mod);
|
||||
}
|
||||
|
||||
if (!isset($args['posts'][$uri])) {
|
||||
$args['posts'][$uri] = [ 'board' => $board, 'posts' => [] ];
|
||||
}
|
||||
$args['posts'][$uri]['posts'][] = $po->build(true);
|
||||
}
|
||||
}
|
||||
|
||||
$args['boards'] = $boards;
|
||||
$args['token'] = make_secure_link_token('ban');
|
||||
|
||||
if (hasPermission($config['mod']['view_ban'])) {
|
||||
$args['bans'] = Bans::find($ip, false, true, $config['auto_maintenance']);
|
||||
}
|
||||
|
@ -989,13 +973,122 @@ function mod_ip(Context $ctx, $ip, string $encoded_cursor = null) {
|
|||
$args['logs'] = [];
|
||||
}
|
||||
|
||||
if (empty($encoded_cursor)) {
|
||||
$args['security_token'] = make_secure_link_token("IP/$ip");
|
||||
} else {
|
||||
$args['security_token'] = make_secure_link_token("IP/$ip/cursor/$encoded_cursor");
|
||||
$boards = listBoards();
|
||||
|
||||
$queryable_uris = [];
|
||||
foreach ($boards as $board) {
|
||||
$uri = $board['uri'];
|
||||
if (hasPermission($config['mod']['show_ip'], $uri)) {
|
||||
$queryable_uris[] = $uri;
|
||||
}
|
||||
}
|
||||
|
||||
mod_page(sprintf('%s: %s', _('IP'), htmlspecialchars($ip)), 'mod/view_ip.html', $args, $args['hostname']);
|
||||
$queries = $ctx->get(UserPostQueries::class);
|
||||
$result = $queries->fetchPaginatedByIp($queryable_uris, $ip, $page_size, $encoded_cursor);
|
||||
|
||||
$args['cursor_prev'] = $result->cursor_prev;
|
||||
$args['cursor_next'] = $result->cursor_next;
|
||||
|
||||
foreach($boards as $board) {
|
||||
$uri = $board['uri'];
|
||||
// The Thread and Post classes rely on some implicit board parameter set by openBoard.
|
||||
openBoard($uri);
|
||||
|
||||
// Finally load the post contents and build them.
|
||||
foreach ($result->by_uri[$uri] as $post) {
|
||||
if (!$post['thread']) {
|
||||
$po = new Thread($post, '?/', $mod, false);
|
||||
} else {
|
||||
$po = new Post($post, '?/', $mod);
|
||||
}
|
||||
|
||||
if (!isset($args['posts'][$uri])) {
|
||||
$args['posts'][$uri] = [ 'board' => $board, 'posts' => [] ];
|
||||
}
|
||||
$args['posts'][$uri]['posts'][] = $po->build(true);
|
||||
}
|
||||
}
|
||||
|
||||
$args['boards'] = $boards;
|
||||
$args['token'] = make_secure_link_token('ban');
|
||||
|
||||
if (empty($encoded_cursor)) {
|
||||
$args['security_token'] = make_secure_link_token("user_posts/ip/$ip");
|
||||
} else {
|
||||
$args['security_token'] = make_secure_link_token("user_posts/ip/$ip/cursor/$encoded_cursor");
|
||||
}
|
||||
|
||||
mod_page(\sprintf('%s: %s', _('IP'), \htmlspecialchars($ip)), 'mod/view_ip.html', $args, $args['hostname']);
|
||||
}
|
||||
|
||||
function mod_user_posts_by_passwd(Context $ctx, string $passwd, string $encoded_cursor = null) {
|
||||
global $mod;
|
||||
|
||||
// The current hashPassword implementation uses sha3-256, which has a 64 character output in non-binary mode.
|
||||
if (\strlen($passwd) != 64) {
|
||||
error('Invalid password');
|
||||
}
|
||||
|
||||
$config = $ctx->get('config');
|
||||
|
||||
$args = [
|
||||
'passwd' => $passwd,
|
||||
'posts' => []
|
||||
];
|
||||
|
||||
if (isset($config['mod']['ip_recentposts'])) {
|
||||
// TODO log to migrate.
|
||||
$page_size = $config['mod']['ip_recentposts'];
|
||||
} else {
|
||||
$page_size = $config['mod']['recent_user_posts'];
|
||||
}
|
||||
|
||||
$boards = listBoards();
|
||||
|
||||
$queryable_uris = [];
|
||||
foreach ($boards as $board) {
|
||||
$uri = $board['uri'];
|
||||
if (hasPermission($config['mod']['show_ip'], $uri)) {
|
||||
$queryable_uris[] = $uri;
|
||||
}
|
||||
}
|
||||
|
||||
$queries = $ctx->get(UserPostQueries::class);
|
||||
$result = $queries->fetchPaginateByPassword($queryable_uris, $passwd, $page_size, $encoded_cursor);
|
||||
|
||||
$args['cursor_prev'] = $result->cursor_prev;
|
||||
$args['cursor_next'] = $result->cursor_next;
|
||||
|
||||
foreach($boards as $board) {
|
||||
$uri = $board['uri'];
|
||||
// The Thread and Post classes rely on some implicit board parameter set by openBoard.
|
||||
openBoard($uri);
|
||||
|
||||
// Finally load the post contents and build them.
|
||||
foreach ($result->by_uri[$uri] as $post) {
|
||||
if (!$post['thread']) {
|
||||
$po = new Thread($post, '?/', $mod, false);
|
||||
} else {
|
||||
$po = new Post($post, '?/', $mod);
|
||||
}
|
||||
|
||||
if (!isset($args['posts'][$uri])) {
|
||||
$args['posts'][$uri] = [ 'board' => $board, 'posts' => [] ];
|
||||
}
|
||||
$args['posts'][$uri]['posts'][] = $po->build(true);
|
||||
}
|
||||
}
|
||||
|
||||
$args['boards'] = $boards;
|
||||
$args['token'] = make_secure_link_token('ban');
|
||||
|
||||
if (empty($encoded_cursor)) {
|
||||
$args['security_token'] = make_secure_link_token("user_posts/passwd/$passwd");
|
||||
} else {
|
||||
$args['security_token'] = make_secure_link_token("user_posts/passwd/$passwd/cursor/$encoded_cursor");
|
||||
}
|
||||
|
||||
mod_page(\sprintf('%s: %s', _('Password'), \htmlspecialchars($passwd)), 'mod/view_passwd.html', $args);
|
||||
}
|
||||
|
||||
function mod_ban(Context $ctx) {
|
||||
|
@ -1913,7 +2006,7 @@ function mod_ban_post(Context $ctx, $board, $delete, $post, $token = false) {
|
|||
$query->bindValue(':time', time());
|
||||
$query->bindValue(':body', $autotag);
|
||||
$query->execute() or error(db_error($query));
|
||||
modLog("Added a note for <a href=\"?/IP/{$ip}\">{$ip}</a>");
|
||||
modLog("Added a note for <a href=\"?/user_posts/ip/{$ip}\">{$ip}</a>");
|
||||
}
|
||||
}
|
||||
deletePost($post);
|
||||
|
@ -2024,7 +2117,7 @@ function mod_warning_post(Context $ctx, $board, $post, $token = false) {
|
|||
$query->bindValue(':time', time());
|
||||
$query->bindValue(':body', $autotag);
|
||||
$query->execute() or error(db_error($query));
|
||||
modLog("Added a note for <a href=\"?/IP/{$ip}\">{$ip}</a>");
|
||||
modLog("Added a note for <a href=\"?/user_posts/ip/{$ip}\">{$ip}</a>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2176,7 +2269,7 @@ function mod_delete(Context $ctx, $board, $post) {
|
|||
$query->bindValue(':time', time());
|
||||
$query->bindValue(':body', $autotag);
|
||||
$query->execute() or error(db_error($query));
|
||||
modLog("Added a note for <a href=\"?/IP/{$ip}\">{$ip}</a>");
|
||||
modLog("Added a note for <a href=\"?/user_posts/ip/{$ip}\">{$ip}</a>");
|
||||
}
|
||||
}
|
||||
deletePost($post);
|
||||
|
@ -2347,7 +2440,7 @@ function mod_deletebyip(Context $ctx, $boardName, $post, $global = false) {
|
|||
$query2->bindValue(':time', time());
|
||||
$query2->bindValue(':body', $autotag);
|
||||
$query2->execute() or error(db_error($query2));
|
||||
modLog("Added a note for <a href=\"?/IP/{$ip}\">{$ip}</a>");
|
||||
modLog("Added a note for <a href=\"?/user_posts/ip/{$ip}\">{$ip}</a>");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2378,7 +2471,7 @@ function mod_deletebyip(Context $ctx, $boardName, $post, $global = false) {
|
|||
}
|
||||
|
||||
// Record the action
|
||||
modLog("Deleted all posts by IP address: <a href=\"?/IP/$ip\">$ip</a>");
|
||||
modLog("Deleted all posts by IP address: <a href=\"?/user_posts/ip/$ip\">$ip</a>");
|
||||
|
||||
// Redirect
|
||||
header('Location: ?/' . sprintf($config['board_path'], $boardName) . $config['file_index'], true, $config['redirect_http']);
|
||||
|
@ -2915,7 +3008,7 @@ function mod_report_dismiss(Context $ctx, $id, $all = false) {
|
|||
|
||||
if ($all) {
|
||||
$report_queries->deleteByIp($ip);
|
||||
modLog("Dismissed all reports by <a href=\"?/IP/$ip\">$ip</a>");
|
||||
modLog("Dismissed all reports by <a href=\"?/user_posts/ip/$ip\">$ip</a>");
|
||||
} else {
|
||||
$report_queries->deleteById($id);
|
||||
modLog("Dismissed a report for post #{$id}", $board);
|
||||
|
|
6
mod.php
6
mod.php
|
@ -71,6 +71,12 @@ $pages = [
|
|||
'/IP/([\w.:]+)/cursor/([\w|-|_]+)' => 'secure_POST ip', // view ip address
|
||||
'/IP/([\w.:]+)/remove_note/(\d+)' => 'secure ip_remove_note', // remove note from ip address
|
||||
|
||||
'/user_posts/ip/([\w.:]+)' => 'secure_POST user_posts_by_ip', // view user posts by ip address
|
||||
'/user_posts/ip/([\w.:]+)/cursor/([\w|-|_]+)' => 'secure_POST user_posts_by_ip', // remove note from ip address
|
||||
|
||||
'/user_posts/passwd/(\w+)' => 'secure_POST user_posts_by_passwd', // view user posts by ip address
|
||||
'/user_posts/passwd/(\w+)/cursor/([\w|-|_]+)' => 'secure_POST user_posts_by_passwd', // remove note from ip address
|
||||
|
||||
'/ban' => 'secure_POST ban', // new ban
|
||||
'/bans' => 'secure_POST bans', // ban list
|
||||
'/bans.json' => 'secure bans_json', // ban list JSON
|
||||
|
|
12
templates/mod/user_posts_list.html
Normal file
12
templates/mod/user_posts_list.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
{% for board_posts in posts %}
|
||||
<fieldset>
|
||||
<legend>
|
||||
<a href="?/{{ config.board_path|sprintf(board_posts.board.uri) }}{{ config.file_index }}">
|
||||
{{ config.board_abbreviation|sprintf(board_posts.board.uri) }}
|
||||
-
|
||||
{{ board_posts.board.title|e }}
|
||||
</a>
|
||||
</legend>
|
||||
{{ board_posts.posts|join('<hr>') }}
|
||||
</fieldset>
|
||||
{% endfor %}
|
|
@ -1,4 +1,4 @@
|
|||
{% if mod|hasPermission(config.mod.view_notes) %}
|
||||
{% if mod|hasPermission(config.mod.view_notes) and notes is not null %}
|
||||
<fieldset id="notes">
|
||||
<legend>
|
||||
{% set notes_on_record = 'note' ~ (notes|count != 1 ? 's' : '') ~ ' on record' %}
|
||||
|
@ -201,24 +201,13 @@
|
|||
</fieldset>
|
||||
{% endif %}
|
||||
|
||||
{% for board_posts in posts %}
|
||||
<fieldset>
|
||||
<legend>
|
||||
<a href="?/{{ config.board_path|sprintf(board_posts.board.uri) }}{{ config.file_index }}">
|
||||
{{ config.board_abbreviation|sprintf(board_posts.board.uri) }}
|
||||
-
|
||||
{{ board_posts.board.title|e }}
|
||||
</a>
|
||||
</legend>
|
||||
{{ board_posts.posts|join('<hr>') }}
|
||||
</fieldset>
|
||||
{% endfor %}
|
||||
{{ include('mod/user_posts_list.html', {posts: posts}) }}
|
||||
<div class="pages" style="margin-left: 50%">
|
||||
<a href="?/IP/{{ ip }}">[Page 1]</a>
|
||||
<a href="?/user_posts/ip/{{ ip }}">[Page 1]</a>
|
||||
{% if cursor_prev %}
|
||||
<a href="?/IP/{{ ip }}/cursor/{{ cursor_prev }}">[Previous Page]</a>
|
||||
<a href="?/user_posts/ip/{{ ip }}/cursor/{{ cursor_prev }}">[Previous Page]</a>
|
||||
{% endif %}
|
||||
{% if cursor_next %}
|
||||
<a href="?/IP/{{ ip }}/cursor/{{ cursor_next }}">[Next Page]</a>
|
||||
<a href="?/user_posts/ip/{{ ip }}/cursor/{{ cursor_next }}">[Next Page]</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
|
50
templates/mod/view_passwd.html
Normal file
50
templates/mod/view_passwd.html
Normal file
|
@ -0,0 +1,50 @@
|
|||
{% if logs and logs|length > 0 %}
|
||||
<fieldset id="history">
|
||||
<legend>History</legend>
|
||||
<table class="modlog" style="width:100%">
|
||||
<tr>
|
||||
<th>{% trans 'Staff' %}</th>
|
||||
<th>{% trans 'Time' %}</th>
|
||||
<th>{% trans 'Board' %}</th>
|
||||
<th>{% trans 'Action' %}</th>
|
||||
</tr>
|
||||
{% for log in logs %}
|
||||
<tr>
|
||||
<td class="minimal">
|
||||
{% if log.username %}
|
||||
<a href="?/log:{{ log.username|e }}">{{ log.username|e }}</a>
|
||||
{% elseif log.mod == -1 %}
|
||||
<em>system</em>
|
||||
{% else %}
|
||||
<em>{% trans 'deleted?' %}</em>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="minimal">
|
||||
<span title="{{ log.time|date(config.post_date) }}">{{ log.time|ago }}</span>
|
||||
</td>
|
||||
<td class="minimal">
|
||||
{% if log.board %}
|
||||
<a href="?/{{ config.board_path|sprintf(log.board) }}{{ config.file_index }}">{{ config.board_abbreviation|sprintf(log.board) }}</a>
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ log.text }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
|
||||
{{ include('mod/user_posts_list.html', {posts: posts}) }}
|
||||
<div class="pages" style="margin-left: 50%">
|
||||
<a href="?/user_posts/passwd/{{ passwd }}">[Page 1]</a>
|
||||
{% if cursor_prev %}
|
||||
<a href="?/user_posts/passwd/{{ passwd }}/cursor/{{ cursor_prev }}">[Previous Page]</a>
|
||||
{% endif %}
|
||||
{% if cursor_next %}
|
||||
<a href="?/user_posts/passwd/{{ passwd }}/cursor/{{ cursor_next }}">[Next Page]</a>
|
||||
{% endif %}
|
||||
</div>
|
|
@ -1,3 +1,3 @@
|
|||
{% 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>]
|
||||
[<a class="ip-link" style="margin:0;" href="?/user_posts/ip/{{ post.ip }}">{{ post.ip }}</a>] [<a class="ip-link" style="margin:0;" href="?/user_posts/passwd/{{ post.password }}">{{ post.password[:15] }}</a>] {# Keep this space #}
|
||||
{% endif %}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue