From 7f45f31aa82b87384fa09d8a7e8d074c78f703e0 Mon Sep 17 00:00:00 2001 From: fowr <89118232+perdedora@users.noreply.github.com> Date: Tue, 6 Aug 2024 11:49:51 -0300 Subject: [PATCH 1/8] fix: proper delete posts in a cyclical thread --- post.php | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/post.php b/post.php index 0a0dd94a9..98eb0a068 100644 --- a/post.php +++ b/post.php @@ -185,6 +185,41 @@ function strip_image_metadata(string $img_path): int { return $ret; } +/** + * Delete posts in a cyclical thread. + * + * @param string $boardUri The URI of the board. + * @param int $threadId The ID of the thread. + * @param int $cycleLimit The number of most recent posts to retain. + */ +function delete_cyclical_posts(string $boardUri, int $threadId, int $cycleLimit): void +{ + $query = prepare(sprintf(' + SELECT p.`id` + FROM ``posts_%s`` p + LEFT JOIN ( + SELECT `id` + FROM ``posts_%s`` + WHERE `thread` = :thread + ORDER BY `id` DESC + LIMIT :limit + ) recent_posts ON p.id = recent_posts.id + WHERE p.thread = :thread + AND recent_posts.id IS NULL', + $boardUri, $boardUri + )); + + $query->bindValue(':thread', $threadId, PDO::PARAM_INT); + $query->bindValue(':limit', $cycleLimit, PDO::PARAM_INT); + + $query->execute() or error(db_error($query)); + $ids = $query->fetchAll(PDO::FETCH_COLUMN); + + foreach ($ids as $id) { + deletePost($id, false); + } +} + /** * Method handling functions */ @@ -1282,11 +1317,7 @@ function ipv4to6($ip) { // Handle cyclical threads if (!$post['op'] && isset($thread['cycle']) && $thread['cycle']) { - // Query is a bit weird due to "This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'" (MariaDB Ver 15.1 Distrib 10.0.17-MariaDB, for Linux (x86_64)) - $query = prepare(sprintf('DELETE FROM ``posts_%s`` WHERE `thread` = :thread AND `id` NOT IN (SELECT `id` FROM (SELECT `id` FROM ``posts_%s`` WHERE `thread` = :thread ORDER BY `id` DESC LIMIT :limit) i)', $board['uri'], $board['uri'])); - $query->bindValue(':thread', $post['thread']); - $query->bindValue(':limit', $config['cycle_limit'], PDO::PARAM_INT); - $query->execute() or error(db_error($query)); + delete_cyclical_posts($board['uri'], $post['thread'], $config['cycle_limit']); } if (isset($post['antispam_hash'])) { From 9f5efdddbe27f91a59fa9bf6f80c2fde09f2385a Mon Sep 17 00:00:00 2001 From: fowr <89118232+perdedora@users.noreply.github.com> Date: Wed, 14 Aug 2024 10:33:48 -0300 Subject: [PATCH 2/8] remove inline highlightReply --- inc/display.php | 34 +++++++++++++++--------- inc/functions.php | 42 +++++++++++++++++++++--------- js/show-backlinks.js | 2 +- templates/main.js | 53 +++++++++++++++++++++++++------------- templates/post_reply.html | 2 +- templates/post_thread.html | 2 +- 6 files changed, 90 insertions(+), 45 deletions(-) diff --git a/inc/display.php b/inc/display.php index 1d74424f2..d7ea01961 100644 --- a/inc/display.php +++ b/inc/display.php @@ -376,14 +376,19 @@ public function __construct($post, $root=null, $mod=false) { markup($this->body); } - if ($this->mod) + if ($this->mod) { // Fix internal links // Very complicated regex - $this->body = preg_replace( - '/body - ); + $this->body = preg_replace( + '/config['root'], '/') + . '(' + . sprintf(preg_quote($this->config['board_path'], '/'), $this->config['board_regex']) + . '([^"]+))"/u', + 'body + ); + } } public function link($pre = '', $page = false) { global $config, $board; @@ -431,14 +436,19 @@ public function __construct($post, $root = null, $mod = false, $hr = true) { markup($this->body); } - if ($this->mod) + if ($this->mod) { // Fix internal links // Very complicated regex - $this->body = preg_replace( - '/body - ); + $this->body = preg_replace( + '/config['root'], '/') + . '(' + . sprintf(preg_quote($this->config['board_path'], '/'), $this->config['board_regex']) + . '([^"]+))"/u', + 'body + ); + } } public function link($pre = '', $page = false) { global $config, $board; diff --git a/inc/functions.php b/inc/functions.php index 2f23ef090..ee93ce99c 100755 --- a/inc/functions.php +++ b/inc/functions.php @@ -2128,11 +2128,19 @@ function markup(&$body, $track_cites = false, $op = false) { } if (isset($cited_posts[$cite])) { - $replacement = '' . - '>>' . $cite . - ''; + $classAttribute = 'class="highlight-link"'; + $dataCiteAttribute = 'data-cite="' . htmlspecialchars($cite, ENT_QUOTES, 'UTF-8') . '"'; + $hrefValue = $config['root'] . $board['dir'] . $config['dir']['res'] + . link_for(['id' => $cite, 'thread' => $cited_posts[$cite]]) + . '#' . $cite; + $linkText = '>>' . htmlspecialchars($cite, ENT_QUOTES, 'UTF-8'); + + $replacement = $matches[1][0] . '' + . $linkText + . ''; $body = mb_substr_replace($body, $matches[1][0] . $replacement . $matches[3][0], $matches[0][1] + $skip_chars, mb_strlen($matches[0][0])); $skip_chars += mb_strlen($matches[1][0] . $replacement . $matches[3][0]) - mb_strlen($matches[0][0]); @@ -2224,13 +2232,23 @@ function markup(&$body, $track_cites = false, $op = false) { if ($cite) { if (isset($cited_posts[$_board][$cite])) { $link = $cited_posts[$_board][$cite]; - - $replacement = '' . - '>>>/' . $_board . '/' . $cite . - ''; + $classAttribute = ''; + if ($_board == $board['uri']) { + $classAttribute = 'class="highlight-link" data-cite="' . htmlspecialchars($cite, ENT_QUOTES, 'UTF-8') . '"'; + } + + $hrefValue = htmlspecialchars($link, ENT_QUOTES, 'UTF-8'); + + $linkText = '>>>/' + . htmlspecialchars($_board, ENT_QUOTES, 'UTF-8') + . '/' . htmlspecialchars($cite, ENT_QUOTES, 'UTF-8'); + + $replacement = $matches[1][0] + . '' + . $linkText + . ''; $body = mb_substr_replace($body, $matches[1][0] . $replacement . $matches[4][0], $matches[0][1] + $skip_chars, mb_strlen($matches[0][0])); $skip_chars += mb_strlen($matches[1][0] . $replacement . $matches[4][0]) - mb_strlen($matches[0][0]); diff --git a/js/show-backlinks.js b/js/show-backlinks.js index fc3125db4..93c7d47a4 100644 --- a/js/show-backlinks.js +++ b/js/show-backlinks.js @@ -39,7 +39,7 @@ onready(function(){ if ($mentioned.find('a.mentioned-' + reply_id).length != 0) return; - var $link = $('>>' + + var $link = $('>>' + reply_id + ''); $link.appendTo($mentioned) diff --git a/templates/main.js b/templates/main.js index 3b32f916c..f3a7b2c66 100644 --- a/templates/main.js +++ b/templates/main.js @@ -220,24 +220,23 @@ function get_cookie(cookie_name) { return null; } -function highlightReply(id) { - if (typeof window.event != "undefined" && event.which == 2) { - // don't highlight on middle click - return true; - } - - var divs = document.getElementsByTagName('div'); - for (var i = 0; i < divs.length; i++) - { - if (divs[i].className.indexOf('post') != -1) - divs[i].className = divs[i].className.replace(/highlighted/, ''); - } - if (id) { - var post = document.getElementById('reply_'+id); - if (post) - post.className += ' highlighted'; - window.location.hash = id; - } +function highlightReply(id, evt) { + if (evt && evt.button === 1) { + return true; + } + + document.querySelectorAll('div.post').forEach(div => { + div.classList.remove('highlighted'); + }); + + if (id) { + const post = document.getElementById(`reply_${id}`); + if (post) { + post.classList.add('highlighted'); + window.location.hash = id; + } + } + return true; } @@ -386,6 +385,24 @@ function ready() { } } +function addLinkListenersCite(selector, callback) { + document.querySelector('body').addEventListener('click', (event) => { + if (event.target.matches(selector)) { + event.preventDefault(); + + var cite = event.target.getAttribute('data-cite'); + + if (callback(cite, event)) { + window.location.href = event.target.href; + } + } + }); +} + +document.addEventListener('DOMContentLoaded', () => { + addLinkListenersCite('.highlight-link', highlightReply); +}); + {% endverbatim %} var post_date = "{{ config.post_date }}"; diff --git a/templates/post_reply.html b/templates/post_reply.html index e6f5fa09f..639ee880b 100644 --- a/templates/post_reply.html +++ b/templates/post_reply.html @@ -14,7 +14,7 @@ {% apply spaceless %} {% include 'post/poster_id.html' %} - No. + No. {{ post.id }}
{% endapply %} diff --git a/templates/post_thread.html b/templates/post_thread.html index e9c5cc128..6458a733a 100644 --- a/templates/post_thread.html +++ b/templates/post_thread.html @@ -18,7 +18,7 @@ {% apply spaceless %} {% include 'post/poster_id.html' %} - No. + No. {{ post.id }} {% if post.sticky %} {% if config.font_awesome %} From 36de809c9046493f73472590788dad1ae3420ecf Mon Sep 17 00:00:00 2001 From: fowr <89118232+perdedora@users.noreply.github.com> Date: Wed, 14 Aug 2024 10:41:59 -0300 Subject: [PATCH 3/8] remove citeReply inline --- templates/main.js | 40 +++++++++++++++------------- templates/post_reply.html | 2 +- templates/post_thread.html | 2 +- templates/post_thread_fileboard.html | 2 +- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/templates/main.js b/templates/main.js index f3a7b2c66..5dc5ac793 100644 --- a/templates/main.js +++ b/templates/main.js @@ -268,26 +268,27 @@ function dopost(form) { } function citeReply(id, with_link) { - var textarea = document.getElementById('body'); + var textarea = document.getElementById('body'); + + if (!textarea) return false; + + var insertionText = '>>' + id + '\n'; + + if (document.selection) { + // IE + textarea.focus(); + var sel = document.selection.createRange(); + sel.text = insertionText; + } else if (textarea.selectionStart !== undefined) { + var start = textarea.selectionStart; + var end = textarea.selectionEnd; + textarea.value = textarea.value.substring(0, start) + insertionText + textarea.value.substring(end); + + textarea.selectionStart = textarea.selectionEnd = start + insertionText.length; + } else { + textarea.value += insertionText; + } - if (!textarea) return false; - - if (document.selection) { - // IE - textarea.focus(); - var sel = document.selection.createRange(); - sel.text = '>>' + id + '\n'; - } else if (textarea.selectionStart || textarea.selectionStart == '0') { - var start = textarea.selectionStart; - var end = textarea.selectionEnd; - textarea.value = textarea.value.substring(0, start) + '>>' + id + '\n' + textarea.value.substring(end, textarea.value.length); - - textarea.selectionStart += ('>>' + id).length + 1; - textarea.selectionEnd = textarea.selectionStart; - } else { - // ??? - textarea.value += '>>' + id + '\n'; - } if (typeof $ != 'undefined') { var select = document.getSelection().toString(); if (select) { @@ -401,6 +402,7 @@ function addLinkListenersCite(selector, callback) { document.addEventListener('DOMContentLoaded', () => { addLinkListenersCite('.highlight-link', highlightReply); + addLinkListenersCite('.cite-link', citeReply); }); {% endverbatim %} diff --git a/templates/post_reply.html b/templates/post_reply.html index 639ee880b..a9006d090 100644 --- a/templates/post_reply.html +++ b/templates/post_reply.html @@ -15,7 +15,7 @@ {% apply spaceless %} {% include 'post/poster_id.html' %} No. - {{ post.id }} + {{ post.id }} {% endapply %} {% include 'post/fileinfo.html' %} diff --git a/templates/post_thread.html b/templates/post_thread.html index 6458a733a..75bfdcafb 100644 --- a/templates/post_thread.html +++ b/templates/post_thread.html @@ -19,7 +19,7 @@ {% apply spaceless %} {% include 'post/poster_id.html' %} No. - {{ post.id }} + {{ post.id }} {% if post.sticky %} {% if config.font_awesome %} diff --git a/templates/post_thread_fileboard.html b/templates/post_thread_fileboard.html index 1b71766a3..9ddb9924d 100644 --- a/templates/post_thread_fileboard.html +++ b/templates/post_thread_fileboard.html @@ -5,7 +5,7 @@