From 29b45e7a11370583dcae93344c58e7783d1a0eb2 Mon Sep 17 00:00:00 2001 From: towards-a-new-leftypol Date: Tue, 5 Sep 2023 14:26:46 -0400 Subject: [PATCH] Add delete_token column to post_* tables - stores the delete_token uuid for telling spamnoticer that the post has been deleted - passes the token to spamnoticer --- composer.json | 3 +- composer.lock | 238 +++++++++++++++++++++++++++++++++++++++- inc/functions.php | 27 +++-- inc/instance-config.php | 1 + inc/spamnoticer.php | 6 +- post.php | 14 ++- templates/posts.sql | 1 + 7 files changed, 275 insertions(+), 15 deletions(-) diff --git a/composer.json b/composer.json index 8f2ee752..fbff8e12 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,7 @@ "twig/twig": "^3.0", "phpmyadmin/twig-i18n-extension": "^4.0", "php81_bc/strftime": "^0.5.0", - "mrclay/jsmin-php": "^2.4" + "mrclay/jsmin-php": "^2.4", + "ramsey/uuid": "^4.7" } } diff --git a/composer.lock b/composer.lock index 9c888ffe..e21d7310 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,63 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d1e010ca547a56f876745bea6e18306c", + "content-hash": "705ac21640fe827036d68ead42d068ae", "packages": [ + { + "name": "brick/math", + "version": "0.11.0", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478", + "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^9.0", + "vimeo/psalm": "5.0.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "brick", + "math" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.11.0" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2023-01-15T23:15:59+00:00" + }, { "name": "guzzlehttp/guzzle", "version": "7.7.0", @@ -1386,6 +1441,187 @@ }, "time": "2019-03-08T08:55:37+00:00" }, + { + "name": "ramsey/collection", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.28.3", + "fakerphp/faker": "^1.21", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^1.0", + "mockery/mockery": "^1.5", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpcsstandards/phpcsutils": "^1.0.0-rc1", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.18.4", + "ramsey/coding-standard": "^2.0.3", + "ramsey/conventional-commits": "^1.3", + "vimeo/psalm": "^5.4" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", + "type": "tidelift" + } + ], + "time": "2022-12-31T21:50:55+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.7.4", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "60a4c63ab724854332900504274f6150ff26d286" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/60a4c63ab724854332900504274f6150ff26d286", + "reference": "60a4c63ab724854332900504274f6150ff26d286", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11", + "ext-json": "*", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.10", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.8", + "ergebnis/composer-normalize": "^2.15", + "mockery/mockery": "^1.3", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^8.5 || ^9", + "ramsey/composer-repl": "^1.4", + "slevomat/coding-standard": "^8.4", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.9" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.7.4" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", + "type": "tidelift" + } + ], + "time": "2023-04-15T23:01:58+00:00" + }, { "name": "sebastian/cli-parser", "version": "2.0.0", diff --git a/inc/functions.php b/inc/functions.php index 078721c9..b824a226 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -995,7 +995,7 @@ function insertFloodPost(array $post) { function post(array $post) { global $pdo, $board,$config; - $query = prepare(sprintf("INSERT INTO ``posts_%s`` VALUES ( NULL, :thread, :subject, :email, :name, :trip, :capcode, :body, :body_nomarkup, :time, :time, :files, :num_files, :filehash, :password, :ip, :sticky, :locked, :cycle, 0, :embed, :slug)", $board['uri'])); + $query = prepare(sprintf("INSERT INTO ``posts_%s`` VALUES ( NULL, :thread, :subject, :email, :name, :trip, :capcode, :body, :body_nomarkup, :time, :time, :files, :num_files, :filehash, :password, :ip, :sticky, :locked, :cycle, 0, :embed, :slug, :delete_token)", $board['uri'])); // Basic stuff if (!empty($post['subject'])) { @@ -1082,6 +1082,12 @@ function post(array $post) { $query->bindValue(':slug', NULL); } + if ($config['spam_noticer']['enabled']) { + $query->bindValue(':delete_token', $post['delete_token']); + } else { + $query->bindValue(':delete_token', NULL); + } + if (!$query->execute()) { undoImage($post); error(db_error($query)); @@ -1107,7 +1113,7 @@ function bumpThread($id) { } // Remove file from post -function deleteFile($id, $remove_entirely_if_already=true, $file=null) { +function deleteFile($id, $remove_entirely_if_already=true, $file=null, $alert_spamnoticer=false) { global $board, $config; $query = prepare(sprintf("SELECT `thread`, `files`, `num_files` FROM ``posts_%s`` WHERE `id` = :id LIMIT 1", $board['uri'])); @@ -1162,8 +1168,9 @@ function rebuildPost($id) { $query->bindValue(':id', $id, PDO::PARAM_INT); $query->execute() or error(db_error($query)); - if ((!$post = $query->fetch(PDO::FETCH_ASSOC)) || !$post['body_nomarkup']) + if ((!$post = $query->fetch(PDO::FETCH_ASSOC)) || !$post['body_nomarkup']) { return false; + } markup($post['body'] = &$post['body_nomarkup']); $post = (object)$post; @@ -1181,7 +1188,7 @@ function rebuildPost($id) { } // Delete a post (reply or thread) -function deletePost($id, $error_if_doesnt_exist=true, $rebuild_after=true) { +function deletePost($id, $error_if_doesnt_exist=true, $rebuild_after=true, $alert_spamnoticer=false) { global $board, $config; // Select post and replies (if thread) in one query @@ -1190,18 +1197,22 @@ function deletePost($id, $error_if_doesnt_exist=true, $rebuild_after=true) { $query->execute() or error(db_error($query)); if ($query->rowCount() < 1) { - if ($error_if_doesnt_exist) + + if ($error_if_doesnt_exist) { error($config['error']['invalidpost']); - else return false; + } else { + return false; + } } $ids = array(); // Delete posts and maybe replies while ($post = $query->fetch(PDO::FETCH_ASSOC)) { + event('delete', $post); - $thread_id = $post['thread']; + if (!$post['thread']) { // Delete thread HTML page file_unlink($board['dir'] . $config['dir']['res'] . link_for($post) ); @@ -1216,6 +1227,7 @@ function deletePost($id, $error_if_doesnt_exist=true, $rebuild_after=true) { // Rebuild thread $rebuild = &$post['thread']; } + if ($post['files']) { // Delete file foreach (json_decode($post['files']) as $i => $f) { @@ -1237,6 +1249,7 @@ function deletePost($id, $error_if_doesnt_exist=true, $rebuild_after=true) { $query = prepare("SELECT `board`, `post` FROM ``cites`` WHERE `target_board` = :board AND (`target` = " . implode(' OR `target` = ', $ids) . ") ORDER BY `board`"); $query->bindValue(':board', $board['uri']); $query->execute() or error(db_error($query)); + while ($cite = $query->fetch(PDO::FETCH_ASSOC)) { if ($board['uri'] != $cite['board']) { if (!isset($tmp_board)) diff --git a/inc/instance-config.php b/inc/instance-config.php index 617c4806..39b4532f 100644 --- a/inc/instance-config.php +++ b/inc/instance-config.php @@ -106,6 +106,7 @@ $config['thread_subject_in_title'] = true; $config['spam']['enabled'] = false; $config['spam_noticer']['enabled'] = true; $config['spam_noticer']['base_url'] = 'http://192.168.4.6:8888'; +$config['spam_noticer']['website_name'] = "leftychan_dev"; /* * Basic captcha. See also: captchaconfig.php diff --git a/inc/spamnoticer.php b/inc/spamnoticer.php index 102ae2c9..0256730f 100644 --- a/inc/spamnoticer.php +++ b/inc/spamnoticer.php @@ -163,7 +163,8 @@ function checkWithSpamNoticer($config, $post, $boardname) { 'time_stamp' => time(), 'website_name' => $config['spam_noticer']['website_name'], 'board_name' => $boardname, - 'thread_id' => array_key_exists('thread', $post) ? $post['thread'] : NULL + 'thread_id' => array_key_exists('thread', $post) ? $post['thread'] : NULL, + 'delete_token' => $post['delete_token'], ]; $result = new SpamNoticerResult(); @@ -201,9 +202,6 @@ function checkWithSpamNoticer($config, $post, $boardname) { $result->reason = (string) $response->getBody(); } - print_err("strbody:\n" . $result->reason); - print_err("status_code: " . $response->getStatusCode()); - $result->client = $client; return $result; diff --git a/post.php b/post.php index 50479354..4d6cfad3 100644 --- a/post.php +++ b/post.php @@ -7,6 +7,8 @@ require_once 'inc/functions.php'; require_once 'inc/anti-bot.php'; require_once 'inc/bans.php'; +use Ramsey\Uuid\Uuid; + $dropped_post = false; function handle_nntpchan() { @@ -249,11 +251,11 @@ function handle_delete(){ if (isset($_POST['file'])) { // Delete just the file - deleteFile($id); + deleteFile($id, true, null, true); modLog("User deleted file from his own post #$id"); } else { // Delete entire post - deletePost($id); + deletePost($id, true, true, true); modLog("User deleted his own post #$id"); } @@ -972,11 +974,19 @@ function handle_post(){ if ($config['spam_noticer']['enabled']) { require_once 'inc/spamnoticer.php'; + + $delete_token_uuid = Uuid::uuid4(); // Generate a version 4 (random) UUID + $delete_token = $delete_token_uuid->toString(); + $post['delete_token'] = $delete_token; + $spam_noticer_result = checkWithSpamNoticer($config, $post, $board['uri']); + if ($spam_noticer_result->succeeded) { if ($spam_noticer_result->noticed) { error($config['error']['spam_noticer'] . $spam_noticer_result->reason); } + } else { + print_err($spam_noticer_result->reason); } } else { print_err("spam_noticer off!"); diff --git a/templates/posts.sql b/templates/posts.sql index 070e687b..972c6fea 100644 --- a/templates/posts.sql +++ b/templates/posts.sql @@ -21,6 +21,7 @@ CREATE TABLE IF NOT EXISTS ``posts_{{ board }}`` ( `sage` int(1) NOT NULL, `embed` text, `slug` varchar(256) DEFAULT NULL, + `delete_token` char(36) DEFAULT NULL, UNIQUE KEY `id` (`id`), KEY `thread_id` (`thread`,`id`), KEY `filehash` (`filehash`(40)),