From 72beacc1da12d3851330e229ff43c8ec6f2ce352 Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Wed, 21 Aug 2013 20:54:46 +1000 Subject: allow moving threads with non-image uploads --- inc/mod/pages.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/mod/pages.php b/inc/mod/pages.php index 63e7266e..7df8f316 100644 --- a/inc/mod/pages.php +++ b/inc/mod/pages.php @@ -1048,7 +1048,7 @@ function mod_move($originBoard, $postID) { if ($post['has_file']) { // copy image $clone($file_src, sprintf($config['board_path'], $board['uri']) . $config['dir']['img'] . $post['file']); - if (!in_array($post['thumb'], array('spoiler', 'deleted'))) + if (!in_array($post['thumb'], array('spoiler', 'deleted', 'file'))) $clone($file_thumb, sprintf($config['board_path'], $board['uri']) . $config['dir']['thumb'] . $post['thumb']); } -- cgit v1.3 From 54a8c721212e279f47d786168b1c38bd9c28e8ed Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Wed, 21 Aug 2013 21:34:18 +1000 Subject: Huge bug with deleting boards: $tmp_board unused; sometimes it would delete the wrong board's directory --- inc/mod/pages.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/inc/mod/pages.php b/inc/mod/pages.php index 7df8f316..706513a3 100644 --- a/inc/mod/pages.php +++ b/inc/mod/pages.php @@ -379,7 +379,7 @@ function mod_edit_board($boardName) { $query->bindValue(':uri', $board['uri'], PDO::PARAM_INT); $query->execute() or error(db_error($query)); - $query = prepare("SELECT `board`, `post` FROM ``cites`` WHERE `target_board` = :board"); + $query = prepare("SELECT `board`, `post` FROM ``cites`` WHERE `target_board` = :board ORDER BY `board`"); $query->bindValue(':board', $board['uri']); $query->execute() or error(db_error($query)); while ($cite = $query->fetch(PDO::FETCH_ASSOC)) { @@ -391,6 +391,9 @@ function mod_edit_board($boardName) { } } + if (isset($tmp_board)) + $board = $tmp_board; + $query = prepare('DELETE FROM ``cites`` WHERE `board` = :board OR `target_board` = :board'); $query->bindValue(':board', $board['uri']); $query->execute() or error(db_error($query)); -- cgit v1.3 From 0cb54b15dc097cc27d6ba6dd2645e856bfda6df5 Mon Sep 17 00:00:00 2001 From: K Date: Tue, 2 Jul 2013 19:52:29 +0200 Subject: Add support for 4chan-compatible json API. Conflicts: inc/functions.php --- inc/api.php | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ inc/functions.php | 39 +++++++++++++++-- 2 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 inc/api.php diff --git a/inc/api.php b/inc/api.php new file mode 100644 index 00000000..5592d8af --- /dev/null +++ b/inc/api.php @@ -0,0 +1,123 @@ + 'no', + 'thread' => 'resto', + 'subject' => 'sub', + 'email' => 'email', + 'name' => 'name', + 'trip' => 'trip', + 'capcode' => 'capcode', + 'body' => 'com', + 'time' => 'time', + 'thumb' => 'thumb', // non-compatible field + 'thumbx' => 'tn_w', + 'thumby' => 'tn_h', + 'file' => 'file', // non-compatible field + 'filex' => 'w', + 'filey' => 'h', + 'filesize' => 'fsize', + //'filename' => 'filename', + 'omitted' => 'omitted_posts', + 'omitted_images' => 'omitted_images', + //'posts' => 'replies', + //'ip' => '', + 'sticky' => 'sticky', + 'locked' => 'locked', + //'bumplocked' => '', + //'embed' => '', + //'root' => '', + //'mod' => '', + //'hr' => '', + ); + + static $ints = array( + 'no' => 1, + 'resto' => 1, + 'time' => 1, + 'tn_w' => 1, + 'tn_h' => 1, + 'w' => 1, + 'h' => 1, + 'fsize' => 1, + 'omitted_posts' => 1, + 'omitted_images' => 1, + 'sticky' => 1, + 'locked' => 1, + ); + + private function translatePost($post) { + $apiPost = array(); + foreach (self::$postFields as $local => $translated) { + if (!isset($post->$local)) + continue; + + $toInt = isset(self::$ints[$translated]); + $val = $post->$local; + if ($val !== null && $val !== '') { + $apiPost[$translated] = $toInt ? (int) $val : $val; + } + } + + if (isset($post->filename)) { + $dotPos = strrpos($post->filename, '.'); + $apiPost['filename'] = substr($post->filename, 0, $dotPos); + $apiPost['ext'] = substr($post->filename, $dotPos); + } + + return $apiPost; + } + + function translateThread(Thread $thread) { + $apiPosts = array(); + $op = $this->translatePost($thread); + $op['resto'] = 0; + $apiPosts['posts'][] = $op; + + foreach ($thread->posts as $p) { + $apiPosts['posts'][] = $this->translatePost($p); + } + + return $apiPosts; + } + + function translatePage(array $threads) { + $apiPage = array(); + foreach ($threads as $thread) { + $apiPage['threads'][] = $this->translateThread($thread); + } + return $apiPage; + } + + function translateCatalogPage(array $threads) { + $apiPage = array(); + foreach ($threads as $thread) { + $ts = $this->translateThread($thread); + $apiPage['threads'][] = current($ts['posts']); + } + return $apiPage; + } + + function translateCatalog($catalog) { + $apiCatalog = array(); + foreach ($catalog as $page => $threads) { + $apiPage = $this->translateCatalogPage($threads); + $apiPage['page'] = $page; + $apiCatalog[] = $apiPage; + } + + return $apiCatalog; + } +} diff --git a/inc/functions.php b/inc/functions.php index d5348f0d..cedf5534 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -13,6 +13,7 @@ require_once 'inc/display.php'; require_once 'inc/template.php'; require_once 'inc/database.php'; require_once 'inc/events.php'; +require_once 'inc/api.php'; require_once 'inc/lib/gettext/gettext.inc'; // the user is not currently logged in as a moderator @@ -1047,6 +1048,9 @@ function index($page, $mod=false) { if ($query->rowCount() < 1 && $page > 1) return false; + + $threads = array(); + while ($th = $query->fetch(PDO::FETCH_ASSOC)) { $thread = new Thread($th, $mod ? '?/' : $config['root'], $mod); @@ -1087,7 +1091,8 @@ function index($page, $mod=false) { $thread->omitted = $omitted['post_count'] - ($th['sticky'] ? $config['threads_preview_sticky'] : $config['threads_preview']); $thread->omitted_images = $omitted['image_count'] - $num_images; } - + + $threads[] = $thread; $body .= $thread->build(true); } @@ -1096,7 +1101,8 @@ function index($page, $mod=false) { 'body' => $body, 'post_url' => $config['post_url'], 'config' => $config, - 'boardlist' => createBoardlist($mod) + 'boardlist' => createBoardlist($mod), + 'threads' => $threads ); } @@ -1289,10 +1295,14 @@ function buildIndex() { if (!$config['try_smarter']) $antibot = create_antibot($board['uri']); + $api = new Api(); + $catalog = array(); + for ($page = 1; $page <= $config['max_pages']; $page++) { $filename = $board['dir'] . ($page == 1 ? $config['file_index'] : sprintf($config['file_page'], $page)); - if ($config['try_smarter'] && isset($build_pages) && count($build_pages) && !in_array($page, $build_pages) && is_file($filename)) + if ($config['try_smarter'] && isset($build_pages) && count($build_pages) + && !in_array($page, $build_pages) && is_file($filename)) continue; $content = index($page); if (!$content) @@ -1309,13 +1319,30 @@ function buildIndex() { $content['antibot'] = $antibot; file_write($filename, Element('index.html', $content)); + + // json api + $threads = $content['threads']; + $json = json_encode($api->translatePage($threads)); + $jsonFilename = $board['dir'] . ($page-1) . ".json"; // pages should start from 0 + file_write($jsonFilename, $json); + + $catalog[$page-1] = $threads; } + if ($page < $config['max_pages']) { for (;$page<=$config['max_pages'];$page++) { $filename = $board['dir'] . ($page==1 ? $config['file_index'] : sprintf($config['file_page'], $page)); file_unlink($filename); + + $jsonFilename = $board['dir'] . ($page-1) . ".json"; + file_unlink($jsonFilename); } } + + // json api catalog + $json = json_encode($api->translateCatalog($catalog)); + $jsonFilename = $board['dir'] . "catalog.json"; + file_write($jsonFilename, $json); } function buildJavascript() { @@ -1735,6 +1762,12 @@ function buildThread($id, $return = false, $mod = false) { return $body; file_write($board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $id), $body); + + // json api + $api = new Api(); + $json = json_encode($api->translateThread($thread)); + $jsonFilename = $board['dir'] . $config['dir']['res'] . $id . ".json"; + file_write($jsonFilename, $json); } function rrmdir($dir) { -- cgit v1.3 From 01e906b1d37858168d4e8b2b7faa114fd4b9f63e Mon Sep 17 00:00:00 2001 From: ctrlcctrlv Date: Tue, 20 Aug 2013 16:53:05 +0000 Subject: Make it possible to disable API, disable it by default Conflicts: inc/functions.php --- inc/config.php | 9 ++++ inc/functions.php | 129 +++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 123 insertions(+), 15 deletions(-) diff --git a/inc/config.php b/inc/config.php index ae45a746..886d7183 100644 --- a/inc/config.php +++ b/inc/config.php @@ -1285,6 +1285,15 @@ // return 'Sorry, you cannot post that!'; // }); +/* + * ============= + * API settings + * ============= + */ + + // Whether or not to use the API, disabled by default. + $config['api']['enabled'] = false; + /* * ==================== * Other/uncategorized diff --git a/inc/functions.php b/inc/functions.php index cedf5534..98cf9d77 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -1295,9 +1295,11 @@ function buildIndex() { if (!$config['try_smarter']) $antibot = create_antibot($board['uri']); - $api = new Api(); - $catalog = array(); - + if ($config['api']['enabled']) { + $api = new Api(); + $catalog = array(); + } + for ($page = 1; $page <= $config['max_pages']; $page++) { $filename = $board['dir'] . ($page == 1 ? $config['file_index'] : sprintf($config['file_page'], $page)); @@ -1321,12 +1323,14 @@ function buildIndex() { file_write($filename, Element('index.html', $content)); // json api - $threads = $content['threads']; - $json = json_encode($api->translatePage($threads)); - $jsonFilename = $board['dir'] . ($page-1) . ".json"; // pages should start from 0 - file_write($jsonFilename, $json); + if ($config['api']['enabled']) { + $threads = $content['threads']; + $json = json_encode($api->translatePage($threads)); + $jsonFilename = $board['dir'] . ($page-1) . ".json"; // pages should start from 0 + file_write($jsonFilename, $json); - $catalog[$page-1] = $threads; + $catalog[$page-1] = $threads; + } } if ($page < $config['max_pages']) { @@ -1340,9 +1344,11 @@ function buildIndex() { } // json api catalog - $json = json_encode($api->translateCatalog($catalog)); - $jsonFilename = $board['dir'] . "catalog.json"; - file_write($jsonFilename, $json); + if ($config['api']['enabled']) { + $json = json_encode($api->translateCatalog($catalog)); + $jsonFilename = $board['dir'] . "catalog.json"; + file_write($jsonFilename, $json); + } } function buildJavascript() { @@ -1764,10 +1770,103 @@ function buildThread($id, $return = false, $mod = false) { file_write($board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $id), $body); // json api - $api = new Api(); - $json = json_encode($api->translateThread($thread)); - $jsonFilename = $board['dir'] . $config['dir']['res'] . $id . ".json"; - file_write($jsonFilename, $json); + if ($config['api']['enabled']) { + $api = new Api(); + $json = json_encode($api->translateThread($thread)); + $jsonFilename = $board['dir'] . $config['dir']['res'] . $id . ".json"; + file_write($jsonFilename, $json); + } + + if ($return) { + return $body; + } else { + $noko50fn = $board['dir'] . $config['dir']['res'] . sprintf($config['file_page50'], $id); + if ($hasnoko50 || file_exists($noko50fn)) { + buildThread50($id, $return, $mod, $thread); + } + + file_write($board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $id), $body); + } +} + +function buildThread50($id, $return = false, $mod = false, $thread = null) { + global $board, $config, $build_pages; + $id = round($id); + + if (event('build-thread', $id)) + return; + + if (!$thread) { + $query = prepare(sprintf("SELECT * FROM ``posts_%s`` WHERE (`thread` IS NULL AND `id` = :id) OR `thread` = :id ORDER BY `thread`,`id` DESC LIMIT :limit", $board['uri'])); + $query->bindValue(':id', $id, PDO::PARAM_INT); + $query->bindValue(':limit', $config['noko50_count']+1, PDO::PARAM_INT); + $query->execute() or error(db_error($query)); + + $num_images = 0; + while ($post = $query->fetch(PDO::FETCH_ASSOC)) { + if (!isset($thread)) { + $thread = new Thread($post, $mod ? '?/' : $config['root'], $mod); + } else { + if ($post['file']) + $num_images++; + + $thread->add(new Post($post, $mod ? '?/' : $config['root'], $mod)); + } + } + + // Check if any posts were found + if (!isset($thread)) + error($config['error']['nonexistant']); + + + if ($query->rowCount() == $config['noko50_count']+1) { + $count = prepare(sprintf("SELECT COUNT(`id`) as `num` FROM ``posts_%s`` WHERE `thread` = :thread UNION ALL SELECT COUNT(`id`) FROM ``posts_%s`` WHERE `file` IS NOT NULL AND `thread` = :thread", $board['uri'], $board['uri'])); + $count->bindValue(':thread', $id, PDO::PARAM_INT); + $count->execute() or error(db_error($count)); + + $c = $count->fetch(); + $thread->omitted = $c['num'] - $config['noko50_count']; + + $c = $count->fetch(); + $thread->omitted_images = $c['num'] - $num_images; + } + + $thread->posts = array_reverse($thread->posts); + } else { + $allPosts = $thread->posts; + + $thread->posts = array_slice($allPosts, -$config['noko50_count']); + $thread->omitted += count($allPosts) - count($thread->posts); + foreach ($allPosts as $index => $post) { + if ($index == count($allPosts)-count($thread->posts)) + break; + if ($post->file) + $thread->omitted_images++; + } + } + + $hasnoko50 = $thread->postCount() >= $config['noko50_min']; + + $body = Element('thread.html', array( + 'board' => $board, + 'thread' => $thread, + 'body' => $thread->build(false, true), + 'config' => $config, + 'id' => $id, + 'mod' => $mod, + 'hasnoko50' => $hasnoko50, + 'isnoko50' => true, + 'antibot' => $mod ? false : create_antibot($board['uri'], $id), + 'boardlist' => createBoardlist($mod), + 'return' => ($mod ? '?' . $board['url'] . $config['file_index'] : $config['root'] . $board['dir'] . $config['file_index']) + )); + + if ($return) { + return $body; + } else { + file_write($board['dir'] . $config['dir']['res'] . sprintf($config['file_page50'], $id), $body); + } +>>>>>>> a29a932... Make it possible to disable API, disable it by default } function rrmdir($dir) { -- cgit v1.3 From ecda099dfb73f9e967a33ce96e45dc7ba1217bf6 Mon Sep 17 00:00:00 2001 From: ctrlcctrlv Date: Tue, 20 Aug 2013 18:17:05 +0000 Subject: Custom fields in API, read config.php for info. Non-4chan compatible fields removed. --- inc/api.php | 67 +++++++++++++++++++++++++------------------------------ inc/config.php | 6 +++++ inc/functions.php | 4 ++-- 3 files changed, 39 insertions(+), 38 deletions(-) diff --git a/inc/api.php b/inc/api.php index 5592d8af..2bf6b7b8 100644 --- a/inc/api.php +++ b/inc/api.php @@ -1,5 +1,4 @@ postFields = array( + 'id' => 'no', + 'thread' => 'resto', + 'subject' => 'sub', + 'body' => 'com', + 'email' => 'email', + 'name' => 'name', + 'trip' => 'trip', + 'capcode' => 'capcode', + 'time' => 'time', + 'thumbx' => 'tn_w', + 'thumby' => 'tn_h', + 'filex' => 'w', + 'filey' => 'h', + 'filesize' => 'fsize', + 'filename' => 'filename', + 'omitted' => 'omitted_posts', + 'omitted_images' => 'omitted_images', + 'sticky' => 'sticky', + 'locked' => 'locked', + ); - /** - * Translation from local fields to fields in 4chan-style API - */ - public static $postFields = array( - 'id' => 'no', - 'thread' => 'resto', - 'subject' => 'sub', - 'email' => 'email', - 'name' => 'name', - 'trip' => 'trip', - 'capcode' => 'capcode', - 'body' => 'com', - 'time' => 'time', - 'thumb' => 'thumb', // non-compatible field - 'thumbx' => 'tn_w', - 'thumby' => 'tn_h', - 'file' => 'file', // non-compatible field - 'filex' => 'w', - 'filey' => 'h', - 'filesize' => 'fsize', - //'filename' => 'filename', - 'omitted' => 'omitted_posts', - 'omitted_images' => 'omitted_images', - //'posts' => 'replies', - //'ip' => '', - 'sticky' => 'sticky', - 'locked' => 'locked', - //'bumplocked' => '', - //'embed' => '', - //'root' => '', - //'mod' => '', - //'hr' => '', - ); + if (isset($config['api']['extra_fields']) && gettype($config['api']['extra_fields']) == 'array'){ + $this->postFields = array_merge($this->postFields, $config['api']['extra_fields']); + } + } - static $ints = array( + private static $ints = array( 'no' => 1, 'resto' => 1, 'time' => 1, @@ -60,7 +55,7 @@ class Api { private function translatePost($post) { $apiPost = array(); - foreach (self::$postFields as $local => $translated) { + foreach ($this->postFields as $local => $translated) { if (!isset($post->$local)) continue; diff --git a/inc/config.php b/inc/config.php index 886d7183..750782bc 100644 --- a/inc/config.php +++ b/inc/config.php @@ -1294,6 +1294,12 @@ // Whether or not to use the API, disabled by default. $config['api']['enabled'] = false; + // Extra fields in to be shown in the array that are not 4chan API compatible. + // You canget these by taking a look at the schema for posts_ tables. The array should be formatted as $db_name => $translated_name. + // For example: + + // $config['api']['extra_fields'] = array('body_nomarkup'=>'com_nomarkup'); + /* * ==================== * Other/uncategorized diff --git a/inc/functions.php b/inc/functions.php index 98cf9d77..aa92d0ef 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -1296,7 +1296,7 @@ function buildIndex() { $antibot = create_antibot($board['uri']); if ($config['api']['enabled']) { - $api = new Api(); + $api = new Api($config); $catalog = array(); } @@ -1771,7 +1771,7 @@ function buildThread($id, $return = false, $mod = false) { // json api if ($config['api']['enabled']) { - $api = new Api(); + $api = new Api($config); $json = json_encode($api->translateThread($thread)); $jsonFilename = $board['dir'] . $config['dir']['res'] . $id . ".json"; file_write($jsonFilename, $json); -- cgit v1.3 From 618d979ec419bddb5606837a9e1496369331f9bd Mon Sep 17 00:00:00 2001 From: ctrlcctrlv Date: Tue, 20 Aug 2013 18:52:12 +0000 Subject: Country flags in API if they are enabled --- inc/api.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/inc/api.php b/inc/api.php index 2bf6b7b8..69a58a0c 100644 --- a/inc/api.php +++ b/inc/api.php @@ -3,6 +3,7 @@ * Copyright (c) 2010-2013 Tinyboard Development Group */ + /** * Class for generating json API compatible with 4chan API */ @@ -11,6 +12,8 @@ class Api { /** * Translation from local fields to fields in 4chan-style API */ + $this->config = $config; + $this->postFields = array( 'id' => 'no', 'thread' => 'resto', @@ -64,6 +67,7 @@ class Api { if ($val !== null && $val !== '') { $apiPost[$translated] = $toInt ? (int) $val : $val; } + } if (isset($post->filename)) { @@ -72,6 +76,18 @@ class Api { $apiPost['ext'] = substr($post->filename, $dotPos); } + // Handle country field + if (isset($post->body_nomarkup) && $this->config['country_flags']) { + $modifiers = extract_modifiers($post->body_nomarkup); + if (isset($modifiers['flag']) && isset($modifiers['flag alt'])) { + $country = mb_convert_case($modifiers['flag'], MB_CASE_UPPER); + if ($country) { + $apiPost['country'] = $country; + $apiPost['country_name'] = $modifiers['flag alt']; + } + } + } + return $apiPost; } -- cgit v1.3 From ddd34347f8f6bf1b47e06c621419e03dca3eb00c Mon Sep 17 00:00:00 2001 From: ctrlcctrlv Date: Tue, 20 Aug 2013 21:31:46 +0000 Subject: Make file/thumb dimensons actually work (thanks sti) --- inc/api.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/inc/api.php b/inc/api.php index 69a58a0c..5e4cc88a 100644 --- a/inc/api.php +++ b/inc/api.php @@ -24,10 +24,10 @@ class Api { 'trip' => 'trip', 'capcode' => 'capcode', 'time' => 'time', - 'thumbx' => 'tn_w', - 'thumby' => 'tn_h', - 'filex' => 'w', - 'filey' => 'h', + 'thumbheight' => 'tn_w', + 'thumbwidth' => 'tn_h', + 'fileheight' => 'w', + 'filewidth' => 'h', 'filesize' => 'fsize', 'filename' => 'filename', 'omitted' => 'omitted_posts', -- cgit v1.3 From ed142a5e5d47b4e41ebb35ec51d50eba98a3d44b Mon Sep 17 00:00:00 2001 From: ctrlcctrlv Date: Tue, 20 Aug 2013 21:35:16 +0000 Subject: ;_; --- inc/api.php | 3 ++- inc/functions.php | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/inc/api.php b/inc/api.php index 5e4cc88a..9cad8ba0 100644 --- a/inc/api.php +++ b/inc/api.php @@ -8,7 +8,8 @@ * Class for generating json API compatible with 4chan API */ class Api { - function __construct($config){ + function __construct(){ + global $config; /** * Translation from local fields to fields in 4chan-style API */ diff --git a/inc/functions.php b/inc/functions.php index aa92d0ef..98cf9d77 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -1296,7 +1296,7 @@ function buildIndex() { $antibot = create_antibot($board['uri']); if ($config['api']['enabled']) { - $api = new Api($config); + $api = new Api(); $catalog = array(); } @@ -1771,7 +1771,7 @@ function buildThread($id, $return = false, $mod = false) { // json api if ($config['api']['enabled']) { - $api = new Api($config); + $api = new Api(); $json = json_encode($api->translateThread($thread)); $jsonFilename = $board['dir'] . $config['dir']['res'] . $id . ".json"; file_write($jsonFilename, $json); -- cgit v1.3 From 9d77a4cc4c3a633f163d1e11a4e2ef775dbe95cc Mon Sep 17 00:00:00 2001 From: ctrlcctrlv Date: Tue, 20 Aug 2013 22:11:32 +0000 Subject: Only add country to JSON if flag fits country code regex --- inc/api.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/api.php b/inc/api.php index 9cad8ba0..a8331590 100644 --- a/inc/api.php +++ b/inc/api.php @@ -80,8 +80,8 @@ class Api { // Handle country field if (isset($post->body_nomarkup) && $this->config['country_flags']) { $modifiers = extract_modifiers($post->body_nomarkup); - if (isset($modifiers['flag']) && isset($modifiers['flag alt'])) { - $country = mb_convert_case($modifiers['flag'], MB_CASE_UPPER); + if (isset($modifiers['flag']) && isset($modifiers['flag alt']) && preg_match('/^[a-z]{2}$/', $modifiers['flag'])) { + $country = strtoupper($modifiers['flag']); if ($country) { $apiPost['country'] = $country; $apiPost['country_name'] = $modifiers['flag alt']; -- cgit v1.3 From cbfafeea3636e222feb73cf42c24fec16bff71bd Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Wed, 21 Aug 2013 22:36:48 +1000 Subject: merge fail --- inc/functions.php | 1 - 1 file changed, 1 deletion(-) diff --git a/inc/functions.php b/inc/functions.php index 98cf9d77..76865882 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -1866,7 +1866,6 @@ function buildThread50($id, $return = false, $mod = false, $thread = null) { } else { file_write($board['dir'] . $config['dir']['res'] . sprintf($config['file_page50'], $id), $body); } ->>>>>>> a29a932... Make it possible to disable API, disable it by default } function rrmdir($dir) { -- cgit v1.3 From b01a402d23a1e7dd94ef2b9980a055c07d332f9d Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Wed, 21 Aug 2013 22:41:42 +1000 Subject: 4chan-compatible api: better config.php comments --- inc/config.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/inc/config.php b/inc/config.php index 750782bc..b6c510a7 100644 --- a/inc/config.php +++ b/inc/config.php @@ -1291,14 +1291,14 @@ * ============= */ - // Whether or not to use the API, disabled by default. + // Whether or not to enable the 4chan-compatible API, disabled by default. See + // https://github.com/4chan/4chan-API for API specification. $config['api']['enabled'] = false; - // Extra fields in to be shown in the array that are not 4chan API compatible. - // You canget these by taking a look at the schema for posts_ tables. The array should be formatted as $db_name => $translated_name. - // For example: - - // $config['api']['extra_fields'] = array('body_nomarkup'=>'com_nomarkup'); + // Extra fields in to be shown in the array that are not in the 4chan-API. You can get these by taking a + // look at the schema for posts_ tables. The array should be formatted as $db_column => $translated_name. + // Example: Adding the pre-markup post body to the API as "com_nomarkup". + // $config['api']['extra_fields'] = array('body_nomarkup' => 'com_nomarkup'); /* * ==================== -- cgit v1.3 From a83715dcb0c6f9bdb82f037b385f09870638963c Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Wed, 21 Aug 2013 22:43:35 +1000 Subject: single quotation marks please --- inc/functions.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/inc/functions.php b/inc/functions.php index 76865882..c34adbcc 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -1326,7 +1326,7 @@ function buildIndex() { if ($config['api']['enabled']) { $threads = $content['threads']; $json = json_encode($api->translatePage($threads)); - $jsonFilename = $board['dir'] . ($page-1) . ".json"; // pages should start from 0 + $jsonFilename = $board['dir'] . ($page - 1) . '.json'; // pages should start from 0 file_write($jsonFilename, $json); $catalog[$page-1] = $threads; @@ -1338,7 +1338,7 @@ function buildIndex() { $filename = $board['dir'] . ($page==1 ? $config['file_index'] : sprintf($config['file_page'], $page)); file_unlink($filename); - $jsonFilename = $board['dir'] . ($page-1) . ".json"; + $jsonFilename = $board['dir'] . ($page - 1) . '.json'; file_unlink($jsonFilename); } } @@ -1346,7 +1346,7 @@ function buildIndex() { // json api catalog if ($config['api']['enabled']) { $json = json_encode($api->translateCatalog($catalog)); - $jsonFilename = $board['dir'] . "catalog.json"; + $jsonFilename = $board['dir'] . 'catalog.json'; file_write($jsonFilename, $json); } } @@ -1773,7 +1773,7 @@ function buildThread($id, $return = false, $mod = false) { if ($config['api']['enabled']) { $api = new Api(); $json = json_encode($api->translateThread($thread)); - $jsonFilename = $board['dir'] . $config['dir']['res'] . $id . ".json"; + $jsonFilename = $board['dir'] . $config['dir']['res'] . $id . '.json'; file_write($jsonFilename, $json); } -- cgit v1.3 From 11fa73e4d11777ce6cc808c278d5c8ca2175b392 Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Wed, 21 Aug 2013 22:44:23 +1000 Subject: automatically initialize $config['api'] --- inc/functions.php | 1 + 1 file changed, 1 insertion(+) diff --git a/inc/functions.php b/inc/functions.php index c34adbcc..9ea6aa9a 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -35,6 +35,7 @@ function loadConfig() { $arrays = array( 'db', + 'api', 'cache', 'cookies', 'error', -- cgit v1.3 From c04e8056a09a5c10d65d737dd978e32964ee230b Mon Sep 17 00:00:00 2001 From: Czterooki Date: Mon, 19 Aug 2013 10:22:41 -0400 Subject: fix background on dark_roach after a bad merge Conflicts: stylesheets/dark_roach.css --- stylesheets/dark_roach.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stylesheets/dark_roach.css b/stylesheets/dark_roach.css index cff616b6..a0e2be44 100644 --- a/stylesheets/dark_roach.css +++ b/stylesheets/dark_roach.css @@ -5,7 +5,7 @@ src: local('Ubuntu Light'), local('Ubuntu-Light'), url(http://themes.googleusercontent.com/static/fonts/ubuntu/v4/_aijTyevf54tkVDLy-dlnD8E0i7KZn-EPnyo3HZu7kw.woff) format('woff'); } body { - background: #000000; + background: #000112; background-image: url(data:image/png;base64,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), url(data:image/png;base64,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); background-repeat: repeat-x, no-repeat; background-attachment: fixed, fixed; -- cgit v1.3 From d92b13876216064317ed28efa60a5a525a40a646 Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Wed, 21 Aug 2013 22:53:48 +1000 Subject: Accidentally merged noko50 stuff --- inc/functions.php | 86 +------------------------------------------------------ 1 file changed, 1 insertion(+), 85 deletions(-) diff --git a/inc/functions.php b/inc/functions.php index 9ea6aa9a..afebd5d8 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -1781,95 +1781,11 @@ function buildThread($id, $return = false, $mod = false) { if ($return) { return $body; } else { - $noko50fn = $board['dir'] . $config['dir']['res'] . sprintf($config['file_page50'], $id); - if ($hasnoko50 || file_exists($noko50fn)) { - buildThread50($id, $return, $mod, $thread); - } - file_write($board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $id), $body); } } -function buildThread50($id, $return = false, $mod = false, $thread = null) { - global $board, $config, $build_pages; - $id = round($id); - - if (event('build-thread', $id)) - return; - - if (!$thread) { - $query = prepare(sprintf("SELECT * FROM ``posts_%s`` WHERE (`thread` IS NULL AND `id` = :id) OR `thread` = :id ORDER BY `thread`,`id` DESC LIMIT :limit", $board['uri'])); - $query->bindValue(':id', $id, PDO::PARAM_INT); - $query->bindValue(':limit', $config['noko50_count']+1, PDO::PARAM_INT); - $query->execute() or error(db_error($query)); - - $num_images = 0; - while ($post = $query->fetch(PDO::FETCH_ASSOC)) { - if (!isset($thread)) { - $thread = new Thread($post, $mod ? '?/' : $config['root'], $mod); - } else { - if ($post['file']) - $num_images++; - - $thread->add(new Post($post, $mod ? '?/' : $config['root'], $mod)); - } - } - - // Check if any posts were found - if (!isset($thread)) - error($config['error']['nonexistant']); - - - if ($query->rowCount() == $config['noko50_count']+1) { - $count = prepare(sprintf("SELECT COUNT(`id`) as `num` FROM ``posts_%s`` WHERE `thread` = :thread UNION ALL SELECT COUNT(`id`) FROM ``posts_%s`` WHERE `file` IS NOT NULL AND `thread` = :thread", $board['uri'], $board['uri'])); - $count->bindValue(':thread', $id, PDO::PARAM_INT); - $count->execute() or error(db_error($count)); - - $c = $count->fetch(); - $thread->omitted = $c['num'] - $config['noko50_count']; - - $c = $count->fetch(); - $thread->omitted_images = $c['num'] - $num_images; - } - - $thread->posts = array_reverse($thread->posts); - } else { - $allPosts = $thread->posts; - - $thread->posts = array_slice($allPosts, -$config['noko50_count']); - $thread->omitted += count($allPosts) - count($thread->posts); - foreach ($allPosts as $index => $post) { - if ($index == count($allPosts)-count($thread->posts)) - break; - if ($post->file) - $thread->omitted_images++; - } - } - - $hasnoko50 = $thread->postCount() >= $config['noko50_min']; - - $body = Element('thread.html', array( - 'board' => $board, - 'thread' => $thread, - 'body' => $thread->build(false, true), - 'config' => $config, - 'id' => $id, - 'mod' => $mod, - 'hasnoko50' => $hasnoko50, - 'isnoko50' => true, - 'antibot' => $mod ? false : create_antibot($board['uri'], $id), - 'boardlist' => createBoardlist($mod), - 'return' => ($mod ? '?' . $board['url'] . $config['file_index'] : $config['root'] . $board['dir'] . $config['file_index']) - )); - - if ($return) { - return $body; - } else { - file_write($board['dir'] . $config['dir']['res'] . sprintf($config['file_page50'], $id), $body); - } -} - - function rrmdir($dir) { +function rrmdir($dir) { if (is_dir($dir)) { $objects = scandir($dir); foreach ($objects as $object) { -- cgit v1.3 From ec3eecd2e5032bcef7748704fa4b8b521133c1f0 Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Wed, 21 Aug 2013 22:58:15 +1000 Subject: dark_roach.css: move images to stylesheets/img --- stylesheets/dark_roach.css | 2 +- stylesheets/img/dark_roach_bg.png | Bin 0 -> 13292 bytes stylesheets/img/dark_roach_top.png | Bin 0 -> 2886 bytes 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 stylesheets/img/dark_roach_bg.png create mode 100644 stylesheets/img/dark_roach_top.png diff --git a/stylesheets/dark_roach.css b/stylesheets/dark_roach.css index a0e2be44..6de59553 100644 --- a/stylesheets/dark_roach.css +++ b/stylesheets/dark_roach.css @@ -6,7 +6,7 @@ } body { background: #000112; - background-image: url(data:image/png;base64,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), url(data:image/png;base64,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); + background-image: url('img/dark_roach_top.png'), url('img/dark_roach_bg.png'); background-repeat: repeat-x, no-repeat; background-attachment: fixed, fixed; background-position: top, right bottom; diff --git a/stylesheets/img/dark_roach_bg.png b/stylesheets/img/dark_roach_bg.png new file mode 100644 index 00000000..5cc59dff Binary files /dev/null and b/stylesheets/img/dark_roach_bg.png differ diff --git a/stylesheets/img/dark_roach_top.png b/stylesheets/img/dark_roach_top.png new file mode 100644 index 00000000..bdfc1ff9 Binary files /dev/null and b/stylesheets/img/dark_roach_top.png differ -- cgit v1.3 From a65c4f2c1fa81073f380ad42b8073720de02fee2 Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Wed, 21 Aug 2013 23:03:38 +1000 Subject: permissions fix --- stylesheets/img/rect820.png | Bin stylesheets/img/rect821.png | Bin 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 stylesheets/img/rect820.png mode change 100755 => 100644 stylesheets/img/rect821.png diff --git a/stylesheets/img/rect820.png b/stylesheets/img/rect820.png old mode 100755 new mode 100644 diff --git a/stylesheets/img/rect821.png b/stylesheets/img/rect821.png old mode 100755 new mode 100644 -- cgit v1.3 From 5cc7bd860fe653db831b20c7937a80ef35221f56 Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Thu, 22 Aug 2013 03:35:57 +1000 Subject: Add cache and gm to pre-installation test. Don't die when we can't write to templates/cache. --- inc/template.php | 3 ++- install.php | 24 +++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/inc/template.php b/inc/template.php index 09e27c26..ef688944 100644 --- a/inc/template.php +++ b/inc/template.php @@ -26,7 +26,8 @@ function load_twig() { $loader->setPaths($config['dir']['template']); $twig = new Twig_Environment($loader, array( 'autoescape' => false, - 'cache' => "{$config['dir']['template']}/cache", + 'cache' => is_writable('templates') && (!is_dir('templates/cache') || is_writable('templates/cache')) ? + "{$config['dir']['template']}/cache" : false, 'debug' => $config['debug'] )); $twig->addExtension(new Twig_Extensions_Extension_Tinyboard()); diff --git a/install.php b/install.php index a6937028..8725df6d 100644 --- a/install.php +++ b/install.php @@ -512,6 +512,13 @@ if ($step == 0) { 'required' => false, 'message' => '(Optional) `identify` was not found or executable; command-line ImageMagick image processing cannot be enabled.', ), + array( + 'category' => 'Image processing', + 'name' => '`gm` (command-line GraphicsMagick)', + 'result' => $can_exec && shell_exec('which gm'), + 'required' => false, + 'message' => '(Optional) `gm` was not found or executable; command-line GraphicsMagick (faster than ImageMagick) cannot be enabled.', + ), array( 'category' => 'Image processing', 'name' => '`gifsicle` (command-line animted GIF thumbnailing)', @@ -526,12 +533,27 @@ if ($step == 0) { 'required' => true, 'message' => 'Tinyboard does not have permission to create directories (boards) here. You will need to chmod (or operating system equivalent) appropriately.' ), + array( + 'category' => 'File permissions', + 'name' => getcwd() . '/templates/cache', + 'result' => is_writable('templates') && (!is_dir('templates/cache') || is_writable('templates/cache')), + 'required' => true, + 'message' => 'You must give Tinyboard permission to create (and write to) the templates/cache directory or performance will be drastically reduced.' + ), array( 'category' => 'File permissions', 'name' => getcwd() . '/inc/instance-config.php', 'result' => is_writable('inc/instance-config.php'), 'required' => false, - 'message' => 'Tinyboard does not have permission to make changes to inc/instance-config.php. To complete the installation, you will be asked to manually copy and paste code into the file instead.' + 'message' => 'Tinyboard does not have permission to make changes to inc/instance-config.php. To complete the installation, you will be asked to manually copy and paste code into the file instead.' + ), + array( + 'category' => 'Misc', + 'name' => 'Caching available (APC, XCache, Memcached or Redis)', + 'result' => extension_loaded('apc') || extension_loaded('xcache') + || extension_loaded('memcached') || extension_loaded('redis'), + 'required' => false, + 'message' => 'You will not be able to enable the additional caching system, designed to minimize SQL queries and significantly improve performance. APC is the recommended method of caching, but XCache, Memcached and Redis are also supported.' ), array( 'category' => 'Misc', -- cgit v1.3 From cdeccbb9ba041b47aec0b6e6cc7acea268cf32ad Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Mon, 26 Aug 2013 12:13:40 +1000 Subject: Uploading files via URL: fix for URL parameters (eg. image.png?id=343543) --- post.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/post.php b/post.php index df7fe435..7ab1eb59 100644 --- a/post.php +++ b/post.php @@ -273,8 +273,12 @@ if (isset($_POST['delete'])) { if (!preg_match($config['url_regex'], $post['file_url'])) error($config['error']['invalidimg']); - - $post['extension'] = strtolower(mb_substr($post['file_url'], mb_strrpos($post['file_url'], '.') + 1)); + if (mb_strpos($post['file_url'], '?') !== false) + $url_without_params = mb_substr($post['file_url'], 0, mb_strpos($post['file_url'], '?')); + else + $url_without_params = $post['file_url']; + + $post['extension'] = strtolower(mb_substr($url_without_params, mb_strrpos($url_without_params, '.') + 1)); if (!in_array($post['extension'], $config['allowed_ext']) && !in_array($post['extension'], $config['allowed_ext_files'])) error($config['error']['unknownext']); @@ -305,7 +309,7 @@ if (isset($_POST['delete'])) { fclose($fp); $_FILES['file'] = array( - 'name' => basename($post['file_url']), + 'name' => basename($url_without_params), 'tmp_name' => $post['file_tmp'], 'error' => 0, 'size' => filesize($post['file_tmp']) -- cgit v1.3 From 09388f6588843d8042fc2542d049deb47c57ce07 Mon Sep 17 00:00:00 2001 From: Dan Saunders Date: Sun, 25 Aug 2013 23:23:02 -0400 Subject: Added a post-delete action for themes This would be really useful for themes that focus on posts --- post.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/post.php b/post.php index 7ab1eb59..2450bf06 100644 --- a/post.php +++ b/post.php @@ -75,6 +75,9 @@ if (isset($_POST['delete'])) { } buildIndex(); + + + rebuildThemes('post-delete', $board['uri']); $is_mod = isset($_POST['mod']) && $_POST['mod']; $root = $is_mod ? $config['root'] . $config['file_mod'] . '?/' : $config['root']; -- cgit v1.3 From bb06593ef5f21b4bc4432530e5ca634f09764773 Mon Sep 17 00:00:00 2001 From: Dan Saunders Date: Sun, 25 Aug 2013 23:26:41 -0400 Subject: Added post-delete handling on themes that should use it. --- templates/themes/catalog/theme.php | 2 +- templates/themes/recent/theme.php | 2 +- templates/themes/sitemap/theme.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/themes/catalog/theme.php b/templates/themes/catalog/theme.php index 96550683..424a813b 100644 --- a/templates/themes/catalog/theme.php +++ b/templates/themes/catalog/theme.php @@ -20,7 +20,7 @@ $b = new Catalog(); $b->build($settings, $board); } - } elseif ($action == 'post-thread' || ($settings['update_on_posts'] && $action == 'post') && in_array($board, $boards)) { + } elseif ($action == 'post-thread' || ($settings['update_on_posts'] && $action == 'post') || ($settings['update_on_posts'] && $action == 'post-delete') && in_array($board, $boards)) { $b = new Catalog(); $b->build($settings, $board); } diff --git a/templates/themes/recent/theme.php b/templates/themes/recent/theme.php index 08d910f8..4bbf1469 100644 --- a/templates/themes/recent/theme.php +++ b/templates/themes/recent/theme.php @@ -24,7 +24,7 @@ $this->excluded = explode(' ', $settings['exclude']); - if ($action == 'all' || $action == 'post' || $action == 'post-thread') + if ($action == 'all' || $action == 'post' || $action == 'post-thread' || $action == 'post-delete') file_write($config['dir']['home'] . $settings['html'], $this->homepage($settings)); } diff --git a/templates/themes/sitemap/theme.php b/templates/themes/sitemap/theme.php index 226f8357..7e5b1984 100644 --- a/templates/themes/sitemap/theme.php +++ b/templates/themes/sitemap/theme.php @@ -11,7 +11,7 @@ // - post (a post has been made) // - thread (a thread has been made) - if ($action != 'post' && $action != 'post-thread') + if ($action != 'post' && $action != 'post-thread' && $action != 'post-delete') return; $boards = explode(' ', $settings['boards']); -- cgit v1.3 From 08bb2894bc358600eeaa03014080c3c2dd910cef Mon Sep 17 00:00:00 2001 From: Dan Saunders Date: Sun, 25 Aug 2013 23:50:29 -0400 Subject: Rebuild themes when a post or file is deleted... Rebuild themes when a post or file is deleted in the moderation panel. --- inc/mod/pages.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/inc/mod/pages.php b/inc/mod/pages.php index 706513a3..5ee8221b 100644 --- a/inc/mod/pages.php +++ b/inc/mod/pages.php @@ -1241,6 +1241,8 @@ function mod_ban_post($board, $delete, $post, $token = false) { modLog("Deleted post #{$post}"); // Rebuild board buildIndex(); + // Rebuild themes + rebuildThemes('post-delete', $board['uri']); } header('Location: ?/' . sprintf($config['board_path'], $board) . $config['file_index'], true, $config['redirect_http']); @@ -1333,7 +1335,8 @@ function mod_delete($board, $post) { modLog("Deleted post #{$post}"); // Rebuild board buildIndex(); - + // Rebuild themes + rebuildThemes('post-delete', $board['uri']); // Redirect header('Location: ?/' . sprintf($config['board_path'], $board) . $config['file_index'], true, $config['redirect_http']); } @@ -1354,6 +1357,8 @@ function mod_deletefile($board, $post) { // Rebuild board buildIndex(); + // Rebuild themes + rebuildThemes('post-delete', $board['uri']); // Redirect header('Location: ?/' . sprintf($config['board_path'], $board) . $config['file_index'], true, $config['redirect_http']); @@ -1392,6 +1397,9 @@ function mod_spoiler_image($board, $post) { // Rebuild board buildIndex(); + + // Rebuild themes + rebuildThemes('post-delete', $board['uri']); // Redirect header('Location: ?/' . sprintf($config['board_path'], $board) . $config['file_index'], true, $config['redirect_http']); @@ -1442,6 +1450,8 @@ function mod_deletebyip($boardName, $post, $global = false) { deletePost($post['id'], false, false); + rebuildThemes('post-delete', $board['uri']); + if ($post['thread']) $threads_to_rebuild[$post['board']][$post['thread']] = true; else -- cgit v1.3 From 00a1841cbc6fb76cd96c51142a3a1b86a073d58a Mon Sep 17 00:00:00 2001 From: Dan Saunders Date: Mon, 26 Aug 2013 00:36:41 -0400 Subject: Regenerate themes after editing a post --- inc/mod/pages.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/inc/mod/pages.php b/inc/mod/pages.php index 5ee8221b..3305e0c2 100644 --- a/inc/mod/pages.php +++ b/inc/mod/pages.php @@ -1306,6 +1306,8 @@ function mod_edit_post($board, $edit_raw_html, $postID) { } buildIndex(); + + rebuildThemes('post', $board['uri']); header('Location: ?/' . sprintf($config['board_path'], $board) . $config['dir']['res'] . sprintf($config['file_page'], $post['thread'] ? $post['thread'] : $postID) . '#' . $postID, true, $config['redirect_http']); } else { -- cgit v1.3 From 319cd2520ff18120570e56eba04ceb1206007375 Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Tue, 27 Aug 2013 08:13:23 +1000 Subject: Upload by URL: still use fatal_error_handler() on shutdown --- post.php | 1 + 1 file changed, 1 insertion(+) diff --git a/post.php b/post.php index 2450bf06..6de3edfa 100644 --- a/post.php +++ b/post.php @@ -288,6 +288,7 @@ if (isset($_POST['delete'])) { $post['file_tmp'] = tempnam($config['tmp'], 'url'); function unlink_tmp_file($file) { @unlink($file); + fatal_error_handler(); } register_shutdown_function('unlink_tmp_file', $post['file_tmp']); -- cgit v1.3 From 5003a692b4505eccdb57447fbf77e4333c8014c0 Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Tue, 27 Aug 2013 08:55:03 +1000 Subject: exiftool: Use -overwrite_original. Important bugfix; old images were never being deleted when using exiftool (instead kept as *_original in /tmp) --- post.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/post.php b/post.php index 6de3edfa..21d294cd 100644 --- a/post.php +++ b/post.php @@ -526,7 +526,8 @@ if (isset($_POST['delete'])) { escapeshellarg($upload)); if ($config['use_exiftool'] && !$config['strip_exif']) { if ($exiftool_error = shell_exec_error( - 'exiftool -q -orientation=1 -n ' . escapeshellarg($upload))) + 'exiftool -overwrite_original -q -q -orientation=1 -n ' . + escapeshellarg($upload))) error('exiftool failed!', null, $exiftool_error); } else { // TODO: Find another way to remove the Orientation tag from the EXIF profile @@ -589,7 +590,8 @@ if (isset($_POST['delete'])) { if ($config['redraw_image'] || (!@$post['exif_stripped'] && $config['strip_exif'] && ($post['extension'] == 'jpg' || $post['extension'] == 'jpeg'))) { if (!$config['redraw_image'] && $config['use_exiftool']) { - if($error = shell_exec_error('exiftool -ignoreMinorErrors -q -q -all= ' . escapeshellarg($upload))) + if($error = shell_exec_error('exiftool -overwrite_original -ignoreMinorErrors -q -q -all= ' . + escapeshellarg($upload))) error('Could not strip EXIF metadata!', null, $error); } else { $image->to($post['file']); -- cgit v1.3 From b96314ef23121f0ad030e75755ea85a0c25bbe49 Mon Sep 17 00:00:00 2001 From: gtx Date: Tue, 27 Aug 2013 12:50:32 +1000 Subject: notsuba.css from tagechan --- stylesheets/notsuba.css | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 stylesheets/notsuba.css diff --git a/stylesheets/notsuba.css b/stylesheets/notsuba.css new file mode 100644 index 00000000..ef9e1057 --- /dev/null +++ b/stylesheets/notsuba.css @@ -0,0 +1,88 @@ +/** +* notsuba.css +* Tagechan is the best +* you are forbidden by law from making any unauthorized edits to this file. I-I'll sue! ;_; +*/ +body { +background: #f2edd0 +} + +a:link, a:visited { +text-decoration: none; +color: #608673; +} + +a:link:hover, a:visited:hover { +color: #DD0000; +} + +a.post_no { +color: #000033; +} + +p.intro a.email span.name { +color: #608673; +} + +p.intro a.email:hover span.name { +color: #DD0000; +} + +h2, div.title, h1 { +color: #800000; +} + +form table tr th { +background: #ded8b7; +} + +div.banner { +background-color: #E04000; +} + +div.post.op hr { +border-color: #608673; +} + +p.intro span.subject { +color: #8a2e2e; +font-weight: 800; +} + +p.intro span.name { +color: #117743; +font-weight: 800; +} + +div.post.reply.highlighted { +background: #dcae9b; +} + +div.post.reply { +background: #e9d1be; +border-color: #dcae9b; +} + +div.ban { +border: 1px solid #B0C2B9; +} + +div.ban h2 { +background: #e9d1be; +color: #608673; +} + +div.pages { +color: #8899AA; +background: #e9d1be; +border-right: 1px solid #8FCCCD; +border-bottom: 1px solid #8FCCCD; +} + +hr { +border-color: #B0C2B9; +} + +div.boardlist { +color: #608673; +} \ No newline at end of file -- cgit v1.3 From 6ce78cb1a454e8556580eaf6b253e1111f848ac0 Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Tue, 27 Aug 2013 17:27:17 +1000 Subject: Bugfix: post editing: should be $board here, not $board['uri'] --- inc/mod/pages.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/mod/pages.php b/inc/mod/pages.php index 3305e0c2..105061e9 100644 --- a/inc/mod/pages.php +++ b/inc/mod/pages.php @@ -1307,7 +1307,7 @@ function mod_edit_post($board, $edit_raw_html, $postID) { buildIndex(); - rebuildThemes('post', $board['uri']); + rebuildThemes('post', $board); header('Location: ?/' . sprintf($config['board_path'], $board) . $config['dir']['res'] . sprintf($config['file_page'], $post['thread'] ? $post['thread'] : $postID) . '#' . $postID, true, $config['redirect_http']); } else { -- cgit v1.3 From a7ac3339def8d07d825d64f33e8ca69c21dd2743 Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Wed, 28 Aug 2013 17:00:41 +1000 Subject: DNS(): Cache NXDOMAIN --- inc/functions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/functions.php b/inc/functions.php index afebd5d8..6ce0b29e 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -1940,7 +1940,7 @@ function DNS($host) { global $config; if ($config['cache']['enabled'] && ($ip_addr = cache::get('dns_' . $host))) { - return $ip_addr; + return $ip_addr != '?' ? $ip_addr : false; } if (!$config['dns_system']) { @@ -1956,7 +1956,7 @@ function DNS($host) { } if ($config['cache']['enabled']) - cache::set('dns_' . $host, $ip_addr, 3600); + cache::set('dns_' . $host, $ip_addr !== false ? $ip_addr : '?', 3600); return $ip_addr; } -- cgit v1.3 From dc8b1948ddb75ac9a620f1146ce2b19627de4222 Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Wed, 28 Aug 2013 17:08:56 +1000 Subject: Performance: Only purge old antispam hashes once per request (at most) --- inc/anti-bot.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/inc/anti-bot.php b/inc/anti-bot.php index fde97096..41e0a1d6 100644 --- a/inc/anti-bot.php +++ b/inc/anti-bot.php @@ -178,11 +178,14 @@ class AntiBot { } function _create_antibot($board, $thread) { - global $config; + global $config, $purged_old_antispam; $antibot = new AntiBot(array($board, $thread)); - query('DELETE FROM ``antispam`` WHERE `expires` < UNIX_TIMESTAMP()') or error(db_error()); + if (!isset($purged_old_antispam)) { + $purged_old_antispam = true; + query('DELETE FROM ``antispam`` WHERE `expires` < UNIX_TIMESTAMP()') or error(db_error()); + } if ($thread) $query = prepare('UPDATE ``antispam`` SET `expires` = UNIX_TIMESTAMP() + :expires WHERE `board` = :board AND `thread` = :thread AND `expires` IS NULL'); -- cgit v1.3 From fcb88b16cdf79f7f543f923b3d5fa39bbdbfb239 Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Wed, 28 Aug 2013 17:20:29 +1000 Subject: Bugfix: Corrupt images were not getting removed from /tmp (convert, gm, and gifsicle) --- inc/image.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/inc/image.php b/inc/image.php index 8088999d..d3692a39 100644 --- a/inc/image.php +++ b/inc/image.php @@ -314,16 +314,18 @@ class ImageConvert extends ImageBase { $this->destroy(); } - $this->temp = tempnam($config['tmp'], 'imagick'); + $this->temp = tempnam($config['tmp'], 'convert'); $config['thumb_keep_animation_frames'] = (int)$config['thumb_keep_animation_frames']; if ($this->format == 'gif' && ($config['thumb_ext'] == 'gif' || $config['thumb_ext'] == '') && $config['thumb_keep_animation_frames'] > 1) { if ($this->gifsicle) { if (($error = shell_exec("gifsicle -w --unoptimize -O2 --resize {$this->width}x{$this->height} < " . - escapeshellarg($this->src . '') . " \"#0-{$config['thumb_keep_animation_frames']}\" -o " . - escapeshellarg($this->temp))) || !file_exists($this->temp)) + escapeshellarg($this->src . '') . " \"#0-{$config['thumb_keep_animation_frames']}\" -o " . + escapeshellarg($this->temp))) || !file_exists($this->temp)) { + $this->destroy(); error('Failed to resize image!', null, $error); + } } else { if ($config['convert_manual_orient'] && ($this->format == 'jpg' || $this->format == 'jpeg')) $convert_args = str_replace('-auto-orient', ImageConvert::jpeg_exif_orientation($this->src), $config['convert_args']); @@ -338,8 +340,10 @@ class ImageConvert extends ImageBase { escapeshellarg($this->src), $this->width, $this->height, - escapeshellarg($this->temp)))) || !file_exists($this->temp)) + escapeshellarg($this->temp)))) || !file_exists($this->temp)) { + $this->destroy(); error('Failed to resize image!', null, $error); + } if ($size = $this->get_size($this->temp)) { $this->width = $size[0]; $this->height = $size[1]; @@ -359,8 +363,10 @@ class ImageConvert extends ImageBase { escapeshellarg($this->src . '[0]'), $this->width, $this->height, - escapeshellarg($this->temp)))) || !file_exists($this->temp)) + escapeshellarg($this->temp)))) || !file_exists($this->temp)) { + $this->destroy(); error('Failed to resize image!', null, $error); + } if ($size = $this->get_size($this->temp)) { $this->width = $size[0]; $this->height = $size[1]; -- cgit v1.3 From 5aaa6887f647a2d16b5db995c434cea4ce98538d Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Wed, 28 Aug 2013 18:02:28 +1000 Subject: Add `ip` index to post tables for faster ?/IP/ (and flood detection, etc.) --- install.php | 6 +++++- templates/posts.sql | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/install.php b/install.php index 8725df6d..3054bf10 100644 --- a/install.php +++ b/install.php @@ -1,7 +1,7 @@ Date: Wed, 28 Aug 2013 18:30:01 +1000 Subject: Sitemap theme: Minimum time between generating, and only generate on post-thread and post-delete --- templates/themes/sitemap/info.php | 9 +++++++++ templates/themes/sitemap/theme.php | 9 ++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/templates/themes/sitemap/info.php b/templates/themes/sitemap/info.php index 43b529fa..0ea2ba9d 100644 --- a/templates/themes/sitemap/info.php +++ b/templates/themes/sitemap/info.php @@ -35,6 +35,15 @@ 'default' => 'hourly', 'size' => '20' ); + + $theme['config'][] = Array( + 'title' => 'Minimum time between regenerating', + 'name' => 'regen_time', + 'type' => 'text', + 'comment' => '(in seconds)', + 'default' => '0', + 'size' => '8' + ); $__boards = listBoards(); $__default_boards = Array(); diff --git a/templates/themes/sitemap/theme.php b/templates/themes/sitemap/theme.php index 7e5b1984..1e36422d 100644 --- a/templates/themes/sitemap/theme.php +++ b/templates/themes/sitemap/theme.php @@ -11,9 +11,16 @@ // - post (a post has been made) // - thread (a thread has been made) - if ($action != 'post' && $action != 'post-thread' && $action != 'post-delete') + if ($action != 'post-thread' && $action != 'post-delete') return; + if ($settings['regen_time'] > 0) { + if ($last_gen = @filemtime($settings['path'])) { + if (time() - $last_gen < (int)$settings['regen_time']) + return; // Too soon + } + } + $boards = explode(' ', $settings['boards']); $threads = array(); -- cgit v1.3 From 10d59e949aece5d4dd5c1b54d9b26300f792a3db Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Wed, 28 Aug 2013 18:39:45 +1000 Subject: Performance: Add `expires` index to antispm table to make purging old hashes a little quicker --- install.php | 4 +++- install.sql | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/install.php b/install.php index 3054bf10..35c1ecb7 100644 --- a/install.php +++ b/install.php @@ -1,7 +1,7 @@ Date: Wed, 28 Aug 2013 20:09:30 +1000 Subject: Allow Unix sockets for database connection --- inc/config.php | 8 +++++--- inc/database.php | 12 ++++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/inc/config.php b/inc/config.php index b6c510a7..5d572010 100644 --- a/inc/config.php +++ b/inc/config.php @@ -77,16 +77,18 @@ // Database driver (http://www.php.net/manual/en/pdo.drivers.php) // Only MySQL is supported by Tinyboard at the moment, sorry. $config['db']['type'] = 'mysql'; - // Hostname or IP address + // Hostname, IP address or Unix socket (prefixed with ":") $config['db']['server'] = 'localhost'; + // Example: Unix socket + // $config['db']['server'] = ':/tmp/mysql.sock'; // Login $config['db']['user'] = ''; $config['db']['password'] = ''; // Tinyboard database $config['db']['database'] = ''; - // Table prefix + // Table prefix (optional) $config['db']['prefix'] = ''; - // Use a persistent connection (experimental) + // Use a persistent connection (experimental; benefits unknown) $config['db']['persistent'] = false; // Anything more to add to the DSN string (eg. port=xxx;foo=bar) $config['db']['dsn'] = ''; diff --git a/inc/database.php b/inc/database.php index 24959d0c..8daa20b4 100644 --- a/inc/database.php +++ b/inc/database.php @@ -43,9 +43,17 @@ class PreparedQueryDebug { function sql_open() { global $pdo, $config; - if ($pdo) return true; + if ($pdo) + return true; - $dsn = $config['db']['type'] . ':host=' . $config['db']['server'] . ';dbname=' . $config['db']['database']; + if (isset($config['db']['server'][0]) && $config['db']['server'][0] == ':') + $unix_socket = substr($config['db']['server'], 1); + else + $unix_socket = false; + + $dsn = $config['db']['type'] . ':' . + ($unix_socket ? 'unix_socket=' . $unix_socket : 'host=' . $config['db']['server']) . + ';dbname=' . $config['db']['database']; if (!empty($config['db']['dsn'])) $dsn .= ';' . $config['db']['dsn']; try { -- cgit v1.3 From 7a4e481333c3ab39ea63c2d961a7c05016b12460 Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Wed, 28 Aug 2013 22:30:56 +1000 Subject: Huge bugfix: Old tracked cites where not being purged correctly. Recommend query: "TRUNCATE TABLE `cites`;" to start over --- inc/functions.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/inc/functions.php b/inc/functions.php index 6ce0b29e..e2289ef1 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -997,9 +997,8 @@ function deletePost($id, $error_if_doesnt_exist=true, $rebuild_after=true) { if (isset($tmp_board)) openBoard($tmp_board); - $query = prepare("DELETE FROM ``cites`` WHERE (`target_board` = :board AND `target` = :id) OR (`board` = :board AND `post` = :id)"); + $query = prepare("DELETE FROM ``cites`` WHERE (`target_board` = :board AND `target` = (" . implode(' OR `target` = ', $ids) . ")) OR (`board` = :board AND (`post` = " . implode(' OR `post` = ', $ids) . "))"); $query->bindValue(':board', $board['uri']); - $query->bindValue(':id', $id, PDO::PARAM_INT); $query->execute() or error(db_error($query)); if (isset($rebuild) && $rebuild_after) { -- cgit v1.3