From d6841c02aaf2c14169904ff6d1b60d7aaae927a2 Mon Sep 17 00:00:00 2001 From: Georg Eitler Date: Tue, 11 Aug 2020 22:04:09 +0200 Subject: [PATCH] add JSON support --- LICENSE | 2 +- imgboard.php | 31 ++++++++++++++-- inc/database_flatfile.php | 11 ++++++ inc/database_mysql.php | 11 ++++++ inc/database_mysqli.php | 11 ++++++ inc/database_pdo.php | 11 ++++++ inc/database_sqlite.php | 11 ++++++ inc/database_sqlite3.php | 11 ++++++ inc/defines.php | 3 ++ inc/html.php | 9 +++++ inc/json.php | 76 +++++++++++++++++++++++++++++++++++++++ settings.default.php | 1 + 12 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 inc/json.php diff --git a/LICENSE b/LICENSE index ccdcdde..7c20f89 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Trevor Slocum +Copyright (c) 2020 Trevor Slocum Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/imgboard.php b/imgboard.php index e9c17a2..6d74b45 100644 --- a/imgboard.php +++ b/imgboard.php @@ -1,7 +1,29 @@ + +MIT License + +Copyright (c) 2020 Trevor Slocum + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ error_reporting(E_ALL); ini_set("display_errors", 1); @@ -57,6 +79,9 @@ foreach ($writedirs as $dir) { } $includes = array("inc/defines.php", "inc/functions.php", "inc/html.php"); +if (TINYIB_JSON) { + $includes[] = 'inc/json.php'; +} if (in_array(TINYIB_DBMODE, array('flatfile', 'mysql', 'mysqli', 'sqlite', 'sqlite3', 'pdo'))) { $includes[] = 'inc/database_' . TINYIB_DBMODE . '.php'; } else { diff --git a/inc/database_flatfile.php b/inc/database_flatfile.php index c15e5b4..7fd2fa1 100644 --- a/inc/database_flatfile.php +++ b/inc/database_flatfile.php @@ -184,6 +184,17 @@ function postsInThreadByID($id, $moderated_only = true) { return convertPostsToSQLStyle($rows); } +function imagesInThreadByID($id, $moderated_only = true) { + $images = 0; + $posts = postsInThreadByID($id, false); + foreach ($posts as $post) { + if ($post['file'] != '') { + $images++; + } + } + return $images; +} + function postsByHex($hex) { $rows = $GLOBALS['db']->selectWhere(POSTS_FILE, new SimpleWhereClause(POST_FILE_HEX, '=', $hex, STRING_COMPARISON), 1); return convertPostsToSQLStyle($rows); diff --git a/inc/database_mysql.php b/inc/database_mysql.php index 6908e98..86e08b4 100644 --- a/inc/database_mysql.php +++ b/inc/database_mysql.php @@ -105,6 +105,17 @@ function postsInThreadByID($id, $moderated_only = true) { return $posts; } +function imagesInThreadByID($id, $moderated_only = true) { + $images = 0; + $posts = postsInThreadByID($id, false); + foreach ($posts as $post) { + if ($post['file'] != '') { + $images++; + } + } + return $images; +} + function postsByHex($hex) { $posts = array(); $result = mysql_query("SELECT `id`, `parent` FROM `" . TINYIB_DBPOSTS . "` WHERE `file_hex` = '" . mysql_real_escape_string($hex) . "' AND `moderated` = 1 LIMIT 1"); diff --git a/inc/database_mysqli.php b/inc/database_mysqli.php index 7e5974b..c7852db 100644 --- a/inc/database_mysqli.php +++ b/inc/database_mysqli.php @@ -117,6 +117,17 @@ function postsInThreadByID($id, $moderated_only = true) { return $posts; } +function imagesInThreadByID($id, $moderated_only = true) { + $images = 0; + $posts = postsInThreadByID($id, false); + foreach ($posts as $post) { + if ($post['file'] != '') { + $images++; + } + } + return $images; +} + function postsByHex($hex) { global $link; $posts = array(); diff --git a/inc/database_pdo.php b/inc/database_pdo.php index ba6d826..d7f1c69 100644 --- a/inc/database_pdo.php +++ b/inc/database_pdo.php @@ -167,6 +167,17 @@ function postsInThreadByID($id, $moderated_only = true) { return $posts; } +function imagesInThreadByID($id, $moderated_only = true) { + $images = 0; + $posts = postsInThreadByID($id, false); + foreach ($posts as $post) { + if ($post['file'] != '') { + $images++; + } + } + return $images; +} + function postsByHex($hex) { $posts = array(); $results = pdoQuery("SELECT * FROM " . TINYIB_DBPOSTS . " WHERE file_hex = ? AND moderated = 1 LIMIT 1", array($hex)); diff --git a/inc/database_sqlite.php b/inc/database_sqlite.php index a972ae4..8bcb3a8 100644 --- a/inc/database_sqlite.php +++ b/inc/database_sqlite.php @@ -118,6 +118,17 @@ function postsInThreadByID($id, $moderated_only = true) { return $posts; } +function imagesInThreadByID($id, $moderated_only = true) { + $images = 0; + $posts = postsInThreadByID($id, false); + foreach ($posts as $post) { + if ($post['file'] != '') { + $images++; + } + } + return $images; +} + function postsByHex($hex) { $posts = array(); $result = sqlite_fetch_all(sqlite_query($GLOBALS["db"], "SELECT id, parent FROM " . TINYIB_DBPOSTS . " WHERE file_hex = '" . sqlite_escape_string($hex) . "' LIMIT 1"), SQLITE_ASSOC); diff --git a/inc/database_sqlite3.php b/inc/database_sqlite3.php index 4ab0b02..f2111d8 100644 --- a/inc/database_sqlite3.php +++ b/inc/database_sqlite3.php @@ -130,6 +130,17 @@ function postsInThreadByID($id, $moderated_only = true) { return $posts; } +function imagesInThreadByID($id, $moderated_only = true) { + $images = 0; + $posts = postsInThreadByID($id, false); + foreach ($posts as $post) { + if ($post['file'] != '') { + $images++; + } + } + return $images; +} + function postsByHex($hex) { global $db; $posts = array(); diff --git a/inc/defines.php b/inc/defines.php index 8a4bc74..085720c 100644 --- a/inc/defines.php +++ b/inc/defines.php @@ -46,6 +46,9 @@ if (!defined('TINYIB_TIMEZONE')) { if (!defined('TINYIB_CATALOG')) { define('TINYIB_CATALOG', true); } +if (!defined('TINYIB_JSON')) { + define('TINYIB_JSON', true); +} if (!defined('TINYIB_DBMIGRATE')) { define('TINYIB_DBMIGRATE', false); } diff --git a/inc/html.php b/inc/html.php index 4a60513..543f07d 100644 --- a/inc/html.php +++ b/inc/html.php @@ -623,6 +623,10 @@ function rebuildIndexes() { $i = 0; $htmlposts = ''; } + + if (TINYIB_JSON) { + writePage("res/" . $thread['id'] . '.json', buildThreadNoJSON($thread['id'])); + } } if ($page == 0 || $htmlposts != '') { @@ -633,6 +637,11 @@ function rebuildIndexes() { if (TINYIB_CATALOG) { rebuildCatalog(); } + + if (TINYIB_JSON) { + writePage('threads.json', buildThreadsJSON()); + writePage('catalog.json', buildCatalogJSON()); + } } function rebuildThread($id) { diff --git a/inc/json.php b/inc/json.php new file mode 100644 index 0000000..2ce210e --- /dev/null +++ b/inc/json.php @@ -0,0 +1,76 @@ + $thread['id'], 'subject' => $thread['subject'], 'bumped' => $thread['bumped'])); + } + + $threads_json[] = $output; + if (version_compare(phpversion(), '5.4.0', '>')) { + return json_encode($threads_json, JSON_PRETTY_PRINT); + } else { + return json_encode($threads_json); + } +} + +function buildCatalogJSON() { + $output['threads'] = array(); + + $threads = allThreads(); + + foreach ($threads as $thread) { + $replies = postsInThreadByID($thread['id']); + $images = imagesInThreadByID($thread['id']); + + if($thread['name'] == '') { + array_push($output['threads'], array('id' => $thread['id'], 'parent' => $thread['parent'], 'timestamp' => $thread['timestamp'], 'bumped' => $thread['bumped'], 'name' => 'Anonymous', 'tripcode' => $thread['tripcode'], 'subject' => $thread['subject'], 'message' => $thread['message'], 'file' => $thread['file'], 'file_hex' => $thread['file_hex'], 'file_original' => $thread['file_original'], 'file_size' => $thread['file_size'], 'file_size_formated' => $thread['file_size_formatted'], 'image_width' => $thread['image_width'], 'image_height' => $thread['image_height'], 'thumb' => $thread['thumb'], 'thumb_width' => $thread['thumb_width'], 'thumb_height' => $thread['thumb_height'], 'stickied' => $thread['stickied'], 'moderated' => $thread['moderated'], 'locked' => $thread['locked'], 'replies' => count($replies) - 1, 'images' => $images)); + } else { + array_push($output['threads'], array('id' => $thread['id'], 'parent' => $thread['parent'], 'timestamp' => $thread['timestamp'], 'bumped' => $thread['bumped'], 'name' => $thread['name'], 'tripcode' => $thread['tripcode'], 'subject' => $thread['subject'], 'message' => $thread['message'], 'file' => $thread['file'], 'file_hex' => $thread['file_hex'], 'file_original' => $thread['file_original'], 'file_size' => $thread['file_size'], 'file_size_formated' => $thread['file_size_formatted'], 'image_width' => $thread['image_width'], 'image_height' => $thread['image_height'], 'thumb' => $thread['thumb'], 'thumb_width' => $thread['thumb_width'], 'thumb_height' => $thread['thumb_height'], 'stickied' => $thread['stickied'], 'moderated' => $thread['moderated'], 'locked' => $thread['locked'], 'replies' => count($replies) - 1, 'images' => $images)); + } + } + + $threads_json[] = $output; + if (version_compare(phpversion(), '5.4.0', '>')) { + return json_encode($threads_json, JSON_PRETTY_PRINT); + } else { + return json_encode($threads_json); + } +} + +function buildThreadNoJSON($id) { + $output = array(); + + $threads = allThreads(); + + foreach ($threads as $thread) { + $replies = postsInThreadByID($id); + if($thread['parent'] == 0 && $thread['id'] == $id) { + if($thread['name'] == '') { + $output = array('posts' => [array('id' => $thread['id'], 'parent' => $thread['parent'], 'timestamp' => $thread['timestamp'], 'bumped' => $thread['bumped'], 'name' => 'Anonymous', 'tripcode' => $thread['tripcode'], 'subject' => $thread['subject'], 'message' => $thread['message'], 'file' => $thread['file'], 'file_hex' => $thread['file_hex'], 'file_original' => $thread['file_original'], 'file_size' => $thread['file_size'], 'file_size_formated' => $thread['file_size_formatted'], 'image_width' => $thread['image_width'], 'image_height' => $thread['image_height'], 'thumb' => $thread['thumb'], 'thumb_width' => $thread['thumb_width'], 'thumb_height' => $thread['thumb_height'], 'stickied' => $thread['stickied'], 'moderated' => $thread['moderated'], 'locked' => $thread['locked'])]); + } else { + $output = array('posts' => [array('id' => $thread['id'], 'parent' => $thread['parent'], 'timestamp' => $thread['timestamp'], 'bumped' => $thread['bumped'], 'name' => $thread['name'], 'tripcode' => $thread['tripcode'], 'subject' => $thread['subject'], 'message' => $thread['message'], 'file' => $thread['file'], 'file_hex' => $thread['file_hex'], 'file_original' => $thread['file_original'], 'file_size' => $thread['file_size'], 'file_size_formated' => $thread['file_size_formatted'], 'image_width' => $thread['image_width'], 'image_height' => $thread['image_height'], 'thumb' => $thread['thumb'], 'thumb_width' => $thread['thumb_width'], 'thumb_height' => $thread['thumb_height'], 'stickied' => $thread['stickied'], 'moderated' => $thread['moderated'], 'locked' => $thread['locked'])]); + } + } + } + foreach ($replies as $reply) { + if($reply['parent'] == $id) { + if($thread['name'] == '') { + array_push($output['posts'], array('id' => $reply['id'], 'parent' => $reply['parent'], 'timestamp' => $reply['timestamp'], 'bumped' => $reply['bumped'], 'name' => 'Anonymous', 'tripcode' => $reply['tripcode'], 'subject' => $reply['subject'], 'message' => $reply['message'], 'file' => $reply['file'], 'file_hex' => $reply['file_hex'], 'file_original' => $reply['file_original'], 'file_size' => $reply['file_size'], 'file_size_formated' => $reply['file_size_formatted'], 'image_width' => $reply['image_width'], 'image_height' => $reply['image_height'], 'thumb' => $reply['thumb'], 'thumb_width' => $reply['thumb_width'], 'thumb_height' => $reply['thumb_height'], 'moderated' => $reply['moderated'])); + } else { + array_push($output['posts'], array('id' => $reply['id'], 'parent' => $reply['parent'], 'timestamp' => $reply['timestamp'], 'bumped' => $reply['bumped'], 'name' => $reply['name'], 'tripcode' => $reply['tripcode'], 'subject' => $reply['subject'], 'message' => $reply['message'], 'file' => $reply['file'], 'file_hex' => $reply['file_hex'], 'file_original' => $reply['file_original'], 'file_size' => $reply['file_size'], 'file_size_formated' => $reply['file_size_formatted'], 'image_width' => $reply['image_width'], 'image_height' => $reply['image_height'], 'thumb' => $reply['thumb'], 'thumb_width' => $reply['thumb_width'], 'thumb_height' => $reply['thumb_height'], 'moderated' => $reply['moderated'])); + } + } + } + + if (version_compare(phpversion(), '5.4.0', '>')) { + return json_encode($output, JSON_PRETTY_PRINT); + } else { + return json_encode($output); + } +} \ No newline at end of file diff --git a/settings.default.php b/settings.default.php index 9071dcd..3e0821b 100644 --- a/settings.default.php +++ b/settings.default.php @@ -28,6 +28,7 @@ define('TINYIB_TRUNCATE', 15); // Messages are truncated to this many lin define('TINYIB_WORDBREAK', 80); // Words longer than this many characters will be broken apart [0 to disable] define('TINYIB_TIMEZONE', 'UTC'); // See https://secure.php.net/manual/en/timezones.php - e.g. America/Los_Angeles define('TINYIB_CATALOG', true); // Generate catalog page +define('TINYIB_JSON', true); // Write JSON files (threads.json, catalog.json, etc.) $tinyib_hidefieldsop = array(); // Fields to hide when creating a new thread - e.g. array('name', 'email', 'subject', 'message', 'file', 'embed', 'password') $tinyib_hidefields = array(); // Fields to hide when replying