From 583b50af56ed99d5fb46cdb582870642c7ad3073 Mon Sep 17 00:00:00 2001 From: Zankaria Date: Tue, 18 Feb 2025 12:16:52 +0100 Subject: [PATCH 1/3] IpNoteQueries.php: add ip notes wrapper --- inc/Data/IpNoteQueries.php | 76 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 inc/Data/IpNoteQueries.php diff --git a/inc/Data/IpNoteQueries.php b/inc/Data/IpNoteQueries.php new file mode 100644 index 00000000..ba6fdb15 --- /dev/null +++ b/inc/Data/IpNoteQueries.php @@ -0,0 +1,76 @@ +pdo = $pdo; + $this->cache = $cache; + } + + /** + * Get all the notes relative to an IP. + * + * @param string $ip The IP of the notes. THE STRING IS NOT VALIDATED. + * @return array Returns an array of notes sorted by the most recent. Includes the username of the mods. + */ + public function getByIp(string $ip) { + $ret = $this->cache->get("ip_note_queries_$ip"); + if ($ret !== null) { + return $ret; + } + + $query = $this->pdo->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(); + $ret = $query->fetchAll(\PDO::FETCH_ASSOC); + + $this->cache->set("ip_note_queries_$ip", $ret); + return $ret; + } + + /** + * Creates a new note relative to the given ip. + * + * @param string $ip The IP of the note. THE STRING IS NOT VALIDATED. + * @param int $mod_id The id of the mod who created the note. + * @param string $body The text of the note. + * @return void + */ + public function add(string $ip, int $mod_id, string $body) { + $query = $this->pdo->prepare('INSERT INTO `ip_notes` (`ip`, `mod`, `time`, `body`) VALUES (:ip, :mod, :time, :body)'); + $query->bindValue(':ip', $ip); + $query->bindValue(':mod', $mod_id); + $query->bindValue(':time', time()); + $query->bindValue(':body', $body); + $query->execute(); + + $this->cache->delete("ip_note_queries_$ip"); + } + + /** + * Delete a note only if it's of a particular IP address. + * + * @param int $id The id of the note. + * @param int $ip The expected IP of the note. THE STRING IS NOT VALIDATED. + * @return bool True if any note was deleted. + */ + public function deleteWhereIp(int $id, string $ip): bool { + $query = $this->pdo->prepare('DELETE FROM `ip_notes` WHERE `ip` = :ip AND `id` = :id'); + $query->bindValue(':ip', $ip); + $query->bindValue(':id', $id); + $query->execute(); + $any = $query->rowCount() != 0; + + if ($any) { + $this->cache->delete("ip_note_queries_$ip"); + } + return $any; + } +} From 5d52f6b32acca7de545cd70616b5c48551937eae Mon Sep 17 00:00:00 2001 From: Zankaria Date: Tue, 18 Feb 2025 12:17:06 +0100 Subject: [PATCH 2/3] pages.php: use IpNoteQueries --- inc/mod/pages.php | 99 +++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 55 deletions(-) diff --git a/inc/mod/pages.php b/inc/mod/pages.php index 52b4ee2c..ec33b128 100644 --- a/inc/mod/pages.php +++ b/inc/mod/pages.php @@ -3,7 +3,7 @@ * Copyright (c) 2010-2013 Tinyboard Development Group */ use Vichan\Context; -use Vichan\Data\{UserPostQueries, ReportQueries}; +use Vichan\Data\{IpNoteQueries, UserPostQueries, ReportQueries}; use Vichan\Functions\Net; defined('TINYBOARD') or exit; @@ -851,18 +851,26 @@ function mod_view_thread50(Context $ctx, $boardName, $thread) { } function mod_ip_remove_note(Context $ctx, $ip, $id) { - global $config; + $config = $ctx->get('config'); - if (!hasPermission($config['mod']['remove_notes'])) - error($config['error']['noaccess']); + if (!hasPermission($config['mod']['remove_notes'])) { + error($config['error']['noaccess']); + } - if (filter_var($ip, FILTER_VALIDATE_IP) === false) + if (filter_var($ip, \FILTER_VALIDATE_IP) === false) { 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)); + if (!is_numeric($id)) { + error('Invalid note ID'); + } + + $queries = $ctx->get(IpNoteQueries::class); + $deleted = $queries->deleteWhereIp((int)$id, $ip); + + if (!$deleted) { + error("Note $id does not exist for $ip"); + } modLog("Removed a note for {$ip}"); @@ -870,14 +878,17 @@ function mod_ip_remove_note(Context $ctx, $ip, $id) { } function mod_ip(Context $ctx, $ip, string $encoded_cursor = null) { - global $config, $mod; + global $mod; + $config = $ctx->get('config'); - if (filter_var($ip, FILTER_VALIDATE_IP) === false) + if (filter_var($ip, FILTER_VALIDATE_IP) === false) { error('Invalid IP address'); + } if (isset($_POST['ban_id'], $_POST['unban'])) { - if (!hasPermission($config['mod']['unban'])) + if (!hasPermission($config['mod']['unban'])) { error($config['error']['noaccess']); + } Bans::delete($_POST['ban_id'], true, $mod['boards']); @@ -890,17 +901,15 @@ function mod_ip(Context $ctx, $ip, string $encoded_cursor = null) { } if (isset($_POST['note'])) { - if (!hasPermission($config['mod']['create_notes'])) + 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)); + + $note_queries = $ctx->get(IpNoteQueries::class); + $note_queries->add($ip, $mod['id'], $_POST['note']); Cache::delete("mod_page_ip_view_notes_$ip"); @@ -952,15 +961,8 @@ function mod_user_posts_by_ip(Context $ctx, string $ip, string $encoded_cursor = } if (hasPermission($config['mod']['view_notes'])) { - $ret = Cache::get("mod_page_ip_view_notes_$ip"); - if (!$ret) { - $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)); - $ret = $query->fetchAll(PDO::FETCH_ASSOC); - Cache::set("mod_page_ip_view_notes_$ip", $ret, 900); - } - $args['notes'] = $ret; + $note_queries = $ctx->get(IpNoteQueries::class); + $args['notes'] = $note_queries->getByIp($ip); } if (hasPermission($config['mod']['modlog_ip'])) { @@ -1998,13 +2000,9 @@ function mod_ban_post(Context $ctx, $board, $delete, $post, $token = false) { $autotag .= "/${board}/" . " " . $filehash . " " . $filename ."\r\n"; $autotag .= $body . "\r\n"; $autotag = escape_markup_modifiers($autotag); - markup($autotag); - $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', $autotag); - $query->execute() or error(db_error($query)); + + $note_queries = $ctx->get(IpNoteQueries::class); + $note_queries->add($ip, $mod['id'], $autotag); modLog("Added a note for {$ip}"); } } @@ -2110,12 +2108,9 @@ function mod_warning_post(Context $ctx, $board, $post, $token = false) { $autotag .= $body . "\r\n"; $autotag = escape_markup_modifiers($autotag); markup($autotag); - $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', $autotag); - $query->execute() or error(db_error($query)); + + $note_queries = $ctx->get(IpNoteQueries::class); + $note_queries->add($ip, $mod['id'], $autotag); modLog("Added a note for {$ip}"); } } @@ -2221,7 +2216,7 @@ function mod_edit_post(Context $ctx, $board, $edit_raw_html, $postID) { } function mod_delete(Context $ctx, $board, $post) { - global $config; + global $config, $mod; if (!openBoard($board)) error($config['error']['noboard']); @@ -2262,12 +2257,9 @@ function mod_delete(Context $ctx, $board, $post) { $autotag .= $body . "\r\n"; $autotag = escape_markup_modifiers($autotag); markup($autotag); - $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', $autotag); - $query->execute() or error(db_error($query)); + + $note_queries = $ctx->get(IpNoteQueries::class); + $note_queries->add($ip, $mod['id'], $autotag); modLog("Added a note for {$ip}"); } } @@ -2355,7 +2347,7 @@ function mod_spoiler_image(Context $ctx, $board, $post, $file) { } function mod_deletebyip(Context $ctx, $boardName, $post, $global = false) { - global $config, $board; + global $config, $board, $mod; $global = (bool)$global; @@ -2433,12 +2425,9 @@ function mod_deletebyip(Context $ctx, $boardName, $post, $global = false) { $autotag .= $body . "\r\n"; $autotag = escape_markup_modifiers($autotag); markup($autotag); - $query2 = prepare('INSERT INTO ``ip_notes`` VALUES (NULL, :ip, :mod, :time, :body)'); - $query2->bindValue(':ip', $ip); - $query2->bindValue(':mod', $mod['id']); - $query2->bindValue(':time', time()); - $query2->bindValue(':body', $autotag); - $query2->execute() or error(db_error($query2)); + + $note_queries = $ctx->get(IpNoteQueries::class); + $note_queries->add($ip, $mod['id'], $autotag); modLog("Added a note for {$ip}"); } } From b61653230dc8c7de10ca12bde242c9b415063fdd Mon Sep 17 00:00:00 2001 From: Zankaria Date: Fri, 21 Feb 2025 11:52:19 +0100 Subject: [PATCH 3/3] context.php: provide IpNoteQueries --- inc/context.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/inc/context.php b/inc/context.php index c744f9d8..3207d7ea 100644 --- a/inc/context.php +++ b/inc/context.php @@ -2,7 +2,7 @@ namespace Vichan; use Vichan\Data\Driver\CacheDriver; -use Vichan\Data\{ReportQueries, UserPostQueries}; +use Vichan\Data\{IpNoteQueries, ReportQueries, UserPostQueries}; defined('TINYBOARD') or exit; @@ -48,6 +48,7 @@ function build_context(array $config): Context { }, UserPostQueries::class => function($c) { return new UserPostQueries($c->get(\PDO::class)); - } + }, + IpNoteQueries::class => fn($c) => new IpNoteQueries($c->get(\PDO::class), $c->get(CacheDriver::class)), ]); }