From 4be8f91f3bd8a3ab46ca358116fb27baaff00bd6 Mon Sep 17 00:00:00 2001 From: Daniel Saunders Date: Thu, 22 Nov 2018 23:40:42 -0500 Subject: [PATCH] Removed a lot of unnecessary code. --- inc/captcha/captcha.php | 357 -------------------- inc/captcha/config.php | 16 - inc/captcha/dbschema.sql | 9 - inc/captcha/entrypoint.php | 85 ----- inc/captcha/readme.md | 10 - inc/config.php | 146 +------- inc/controller.php | 108 ------ inc/functions.php | 266 +++++---------- inc/lock.php | 39 --- inc/nntpchan/nntpchan.php | 152 --------- inc/nntpchan/tests.php | 30 -- inc/polyfill.php | 28 -- inc/queue.php | 49 --- inc/route.php | 65 ---- install.php | 81 ++--- install.sql | 33 -- js/captcha.js | 43 --- post.php | 486 +++++++-------------------- smart_build.php | 86 ----- templates/post_form.html | 21 -- templates/themes/awsumchan/theme.php | 14 +- templates/themes/catalog/theme.php | 20 +- templates/themes/recent/theme.php | 12 +- templates/themes/sitemap/theme.php | 35 +- templates/themes/ukko/theme.php | 9 +- tmp/locks/.gitkeep | 0 tmp/queue/generate/.gitkeep | 0 tools/worker.php | 31 -- 28 files changed, 259 insertions(+), 1972 deletions(-) delete mode 100644 inc/captcha/captcha.php delete mode 100644 inc/captcha/config.php delete mode 100644 inc/captcha/dbschema.sql delete mode 100644 inc/captcha/entrypoint.php delete mode 100644 inc/captcha/readme.md delete mode 100644 inc/controller.php delete mode 100644 inc/lock.php delete mode 100644 inc/nntpchan/nntpchan.php delete mode 100644 inc/nntpchan/tests.php delete mode 100644 inc/polyfill.php delete mode 100644 inc/queue.php delete mode 100644 inc/route.php delete mode 100644 js/captcha.js delete mode 100644 smart_build.php delete mode 100644 tmp/locks/.gitkeep delete mode 100644 tmp/queue/generate/.gitkeep delete mode 100755 tools/worker.php diff --git a/inc/captcha/captcha.php b/inc/captcha/captcha.php deleted file mode 100644 index 7c54fa3c..00000000 --- a/inc/captcha/captcha.php +++ /dev/null @@ -1,357 +0,0 @@ -width = $left; - $this->height = $top; - - $this->charset = preg_split('//u', $charset); - - $this->style = ""; - - for ($i = 0; $i < $len; $i++) { - $this->content[] = array(mb_substr($text, $i, 1, 'utf-8'), "top" => $top / 2 - $top / 4, - "left" => $left/10 + 9*$left*$i/10/$len, - "position" => "absolute"); - } - - $this->color = "hsla(".rand(1,360).", 76%, 78%, 1)"; - - $this->add_junk(); - $this->mutate_sizes(); - $this->mutate_positions(); - $this->mutate_transform(); - $this->mutate_anchors(); - $this->randomize(); - $this->mutate_containers(); - $this->mutate_margins(); - $this->mutate_styles(); - $this->randomize(); - } - - function mutate_sizes() { - foreach ($this->content as &$v) { - if (!isset ($v['font-size'])) - $v['font-size'] = rand($this->height/3 - 4, $this->height/3 + 8); - } - } - function mutate_positions() { - foreach ($this->content as &$v) { - $v['top'] += rand(-10,10); - $v['left'] += rand(-10,10); - } - } - function mutate_transform() { - $fromto = array('6'=>'9', '9'=>'6', '8'=>'8', '0'=>'0', - 'z'=>'z', 's'=>'s', 'n'=>'u', 'u'=>'n', - 'a'=>'ɐ', 'e'=>'ə', 'p'=>'d', 'd'=>'p', - 'A'=>'∀', 'E'=>'∃', 'H'=>'H', 'o'=>'o', - 'O'=>'O'); - - foreach ($this->content as &$v) { - $basefrom = -20; - $baseto = 20; - - if (isset($fromto[$v[0]]) && rand(0,1)) { - $v[0] = $fromto[$v[0]]; - $basefrom = 160; - $baseto = 200; - } - - $v['transform'] = 'rotate('.rand($basefrom,$baseto).'deg)'; - $v['-ms-transform'] = 'rotate('.rand($basefrom,$baseto).'deg)'; - $v['-webkit-transform'] = 'rotate('.rand($basefrom,$baseto).'deg)'; - } - } - function randomize(&$a = false) { - if ($a === false) { - $a = &$this->content; - } - - shuffle($a); - - foreach ($a as &$v) { - $this->shuffle_assoc($v); - - if (is_array ($v[0])) { - $this->randomize($v[0]); - } - } - } - - function add_junk() { - $count = rand(200, 300); - - while ($count--) { - $elem = array(); - - $elem['top'] = rand(0, $this->height); - $elem['left'] = rand(0, $this->width); - - $elem['position'] = 'absolute'; - - $elem[0] = $this->charset[rand(0, count($this->charset)-1)]; - - switch($t = rand (0,9)) { - case 0: - $elem['display'] = 'none'; break; - case 1: - $elem['top'] = rand(-60, -90); break; - case 2: - $elem['left'] = rand(-40, -70); break; - case 3: - $elem['top'] = $this->height + rand(10, 60); break; - case 4: - $elem['left'] = $this->width + rand(10, 60); break; - case 5: - $elem['color'] = $this->color; break; - case 6: - $elem['visibility'] = 'hidden'; break; - case 7: - $elem['height'] = rand(0,2); - $elem['overflow'] = 'hidden'; break; - case 8: - $elem['width'] = rand(0,1); - $elem['overflow'] = 'hidden'; break; - case 9: - $elem['font-size'] = rand(2, 6); break; - } - - $this->content[] = $elem; - } - } - - function mutate_anchors() { - foreach ($this->content as &$elem) { - if (rand(0,1)) { - $elem['right'] = $this->width - $elem['left'] - (int)(0.5*$elem['font-size']); - unset($elem['left']); - } - if (rand(0,1)) { - $elem['bottom'] = $this->height - $elem['top'] - (int)(1.5*$elem['font-size']); - unset($elem['top']); - } - } - } - - function mutate_containers() { - for ($i = 0; $i <= 80; $i++) { - $new = []; - $new['width'] = rand(0, $this->width*2); - $new['height'] = rand(0, $this->height*2); - $new['top'] = rand(-$this->height * 2, $this->height * 2); - $new['bottom'] = $this->height - ($new['top'] + $new['height']); - $new['left'] = rand(-$this->width * 2, $this->width * 2); - $new['right'] = $this->width - ($new['left'] + $new['width']); - - $new['position'] = 'absolute'; - - $new[0] = []; - - $cnt = rand(0,10); - for ($j = 0; $j < $cnt; $j++) { - $elem = array_pop($this->content); - if (!$elem) break; - - if (isset($elem['top'])) $elem['top'] -= $new['top']; - if (isset($elem['bottom'])) $elem['bottom'] -= $new['bottom']; - if (isset($elem['left'])) $elem['left'] -= $new['left']; - if (isset($elem['right'])) $elem['right'] -= $new['right']; - - $new[0][] = $elem; - } - - if (rand (0,1)) unset($new['top']); - else unset($new['bottom']); - if (rand (0,1)) unset($new['left']); - else unset($new['right']); - - $this->content[] = $new; - - shuffle($this->content); - } - } - - function mutate_margins(&$a = false) { - if ($a === false) { - $a = &$this->content; - } - - foreach ($a as &$v) { - $ary = ['top', 'left', 'bottom', 'right']; - shuffle($ary); - $cnt = rand(0,4); - $ary = array_slice($ary, 0, $cnt); - - foreach ($ary as $prop) { - $margin = rand(-1000, 1000); - - $v['margin-'.$prop] = $margin; - - if (isset($v[$prop])) { - $v[$prop] -= $margin; - } - } - - if (is_array($v[0])) { - $this->mutate_margins($v[0]); - } - } - } - - function mutate_styles(&$a = false) { - if ($a === false) { - $a = &$this->content; - } - - foreach ($a as &$v) { - $content = $v[0]; - unset($v[0]); - $styles = array_splice($v, 0, rand(0, 6)); - $v[0] = $content; - - $id_or_class = rand(0,1); - $param = $id_or_class ? "id" : "class"; - $prefix = $id_or_class ? "#" : "."; - $genname = "zz-".base_convert(rand(1,999999999), 10, 36); - - if ($styles || rand(0,1)) { - $this->style .= $prefix.$genname."{"; - $this->style .= $this->rand_whitespace(); - - foreach ($styles as $k => $val) { - if (is_int($val)) { - $val = "".$val."px"; - } - - $this->style .= "$k:"; - $this->style .= $this->rand_whitespace(); - $this->style .= "$val;"; - $this->style .= $this->rand_whitespace(); - } - $this->style .= "}"; - $this->style .= $this->rand_whitespace(); - } - - $v[$param] = $genname; - - if (is_array($v[0])) { - $this->mutate_styles($v[0]); - } - } - } - - function to_html(&$a = false) { - $inside = true; - - if ($a === false) { - if ($this->style) { - echo ""; - } - - echo "
"; - $a = &$this->content; - $inside = false; - } - - foreach ($a as &$v) { - $letter = $v[0]; - - unset ($v[0]); - - echo "rand_whitespace(1); - - if (isset ($v['id'])) { - echo "id='$v[id]'"; - echo $this->rand_whitespace(1); - - unset ($v['id']); - } - if (isset ($v['class'])) { - echo "class='$v[class]'"; - echo $this->rand_whitespace(1); - - unset ($v['class']); - } - - echo "style='"; - - foreach ($v as $k => $val) { - if (is_int($val)) { - $val = "".$val."px"; - } - - echo "$k:"; - echo $this->rand_whitespace(); - echo "$val;"; - echo $this->rand_whitespace(); - - } - - echo "'>"; - echo $this->rand_whitespace(); - - if (is_array ($letter)) { - $this->to_html($letter); - } - else { - echo $letter; - } - - echo "
"; - } - - if (!$inside) { - echo ""; - } - - } - - function rand_whitespace($r = 0) { - switch (rand($r,4)) { - case 0: - return ""; - case 1: - return "\n"; - case 2: - return "\t"; - case 3: - return " "; - case 4: - return " "; - } - } - - - - function shuffle_assoc(&$array) { - $keys = array_keys($array); - - shuffle($keys); - - foreach($keys as $key) { - $new[$key] = $array[$key]; - } - - $array = $new; - - return true; - } -} - -//$charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789卐"; - -//(new CzaksCaptcha("hotwheels", 300, 80, $charset))->to_html(); -?> diff --git a/inc/captcha/config.php b/inc/captcha/config.php deleted file mode 100644 index 568c06c5..00000000 --- a/inc/captcha/config.php +++ /dev/null @@ -1,16 +0,0 @@ - 'SET NAMES utf8')); - - -// Captcha expiration: -$expires_in = 120; // 120 seconds - -// Captcha dimensions: -$width = 250; -$height = 80; - -// Captcha length: -$length = 6; diff --git a/inc/captcha/dbschema.sql b/inc/captcha/dbschema.sql deleted file mode 100644 index 504ea10c..00000000 --- a/inc/captcha/dbschema.sql +++ /dev/null @@ -1,9 +0,0 @@ -SET NAMES utf8; - -CREATE TABLE `captchas` ( - `cookie` VARCHAR(50), - `extra` VARCHAR(200), - `text` VARCHAR(255), - `created_at` INT(11), - PRIMARY KEY (cookie, extra) -) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; diff --git a/inc/captcha/entrypoint.php b/inc/captcha/entrypoint.php deleted file mode 100644 index 3b468a2a..00000000 --- a/inc/captcha/entrypoint.php +++ /dev/null @@ -1,85 +0,0 @@ -prepare("DELETE FROM `captchas` WHERE `created_at` < ?")->execute([time() - $expires_in]); -} - -switch ($mode) { -// Request: GET entrypoint.php?mode=get&extra=1234567890 -// Response: JSON: cookie => "generatedcookie", captchahtml => "captchahtml", expires_in => 120 -case "get": - if (!isset ($_GET['extra'])) { - die(); - } - - header("Content-type: application/json"); - - $extra = $_GET['extra']; - - require_once("config.php"); - - $text = rand_string($length, $extra); - - $captcha = new CzaksCaptcha($text, $width, $height, $extra); - - $cookie = rand_string(20, "abcdefghijklmnopqrstuvwxyz"); - - ob_start(); - $captcha->to_html(); - $html = ob_get_contents(); - ob_end_clean(); - - $query = $pdo->prepare("INSERT INTO `captchas` (`cookie`, `extra`, `text`, `created_at`) VALUES (?, ?, ?, ?)"); - $query->execute( [$cookie, $extra, $text, time()]); - - echo json_encode(["cookie" => $cookie, "captchahtml" => $html, "expires_in" => $expires_in]); - - break; - -// Request: GET entrypoint.php?mode=check&cookie=generatedcookie&extra=1234567890&text=captcha -// Response: 0 OR 1 -case "check": - if (!isset ($_GET['mode']) - || !isset ($_GET['cookie']) - || !isset ($_GET['extra']) - || !isset ($_GET['text'])) { - die(); - } - - require_once("config.php"); - - cleanup($pdo, $expires_in); - - $query = $pdo->prepare("SELECT * FROM `captchas` WHERE `cookie` = ? AND `extra` = ?"); - $query->execute([$_GET['cookie'], $_GET['extra']]); - - $ary = $query->fetchAll(); - - if (!$ary) { - echo "0"; - } - else { - $query = $pdo->prepare("DELETE FROM `captchas` WHERE `cookie` = ? AND `extra` = ?"); - $query->execute([$_GET['cookie'], $_GET['extra']]); - - if ($ary[0]['text'] !== $_GET['text']) { - echo "0"; - } - else { - echo "1"; - } - } - - break; -} diff --git a/inc/captcha/readme.md b/inc/captcha/readme.md deleted file mode 100644 index 8b1f538a..00000000 --- a/inc/captcha/readme.md +++ /dev/null @@ -1,10 +0,0 @@ -I integrated this from: https://github.com/ctrlcctrlv/infinity/commit/62a6dac022cb338f7b719d0c35a64ab3efc64658 - -First import the captcha/dbschema.sql in your database it is no longer required. - -In inc/captcha/config.php change the database_name database_user database_password to your own settings. - -Add js/captcha.js in your instance-config.php or config.php - -Go to Line 305 in the /inc/config file and copy the settings in instance config, while changing the url to your website. -Go to the line beneath it if you only want to enable it when posting a new thread. diff --git a/inc/config.php b/inc/config.php index 22704b81..c7fd4f8c 100644 --- a/inc/config.php +++ b/inc/config.php @@ -103,7 +103,7 @@ /* * ==================== - * Cache, lock and queue settings + * Cache settings * ==================== */ @@ -137,12 +137,6 @@ // (this file will be explicitly loaded during cache hit, but not during cache miss). $config['cache_config'] = false; - // Define a lock driver. - $config['lock']['enabled'] = 'fs'; - - // Define a queue driver. - $config['queue']['enabled'] = 'fs'; // xD - /* * ==================== * Cookie settings @@ -281,8 +275,6 @@ 'raw', 'embed', 'g-recaptcha-response', - 'captcha_cookie', - 'captcha_text', 'spoiler', 'page', 'file_url', @@ -298,26 +290,6 @@ // Public and private key pair from https://www.google.com/recaptcha/admin/create $config['recaptcha_public'] = '6LcXTcUSAAAAAKBxyFWIt2SO8jwx4W7wcSMRoN3f'; $config['recaptcha_private'] = '6LcXTcUSAAAAAOGVbVdhmEM1_SyRF4xTKe8jbzf_'; - - // Enable Custom Captcha you need to change a couple of settings - //Read more at: /captcha/instructions.md - $config['captcha'] = array(); - - // Enable custom captcha provider - $config['captcha']['enabled'] = false; - - //New thread captcha - //Require solving a captcha to post a thread. - //Default off. - $config['new_thread_capt'] = false; - - // Custom captcha get provider path (if not working get the absolute path aka your url.) - $config['captcha']['provider_get'] = '../inc/captcha/entrypoint.php'; - // Custom captcha check provider path - $config['captcha']['provider_check'] = '../inc/captcha/entrypoint.php'; - - // Custom captcha extra field (eg. charset) - $config['captcha']['extra'] = 'abcdefghijklmnopqrstuvwxyz'; // Ability to lock a board for normal users and still allow mods to post. Could also be useful for making an archive board $config['board_locked'] = false; @@ -1025,7 +997,6 @@ // $config['additional_javascript'][] = 'js/auto-reload.js'; // $config['additional_javascript'][] = 'js/post-hover.js'; // $config['additional_javascript'][] = 'js/style-select.js'; - // $config['additional_javascript'][] = 'js/captcha.js'; // Where these script files are located on the web. Defaults to $config['root']. // $config['additional_javascript_url'] = 'http://static.example.org/tinyboard-javascript-stuff/'; @@ -1133,7 +1104,7 @@ $config['error']['delete_too_soon'] = _('You\'ll have to wait another %s before deleting that.'); $config['error']['mime_exploit'] = _('MIME type detection XSS exploit (IE) detected; post discarded.'); $config['error']['invalid_embed'] = _('Couldn\'t make sense of the URL of the video you tried to embed.'); - $config['error']['captcha'] = _('You seem to have mistyped the verification.'); + $config['error']['captcha'] = _('You seem to have failed the verification.'); // Moderator errors @@ -1236,76 +1207,7 @@ // Try not to build pages when we shouldn't have to. $config['try_smarter'] = true; - -/* - * ==================== - * Advanced build - * ==================== - */ - - // Strategies for file generation. Also known as an "advanced build". If you don't have performance - // issues, you can safely ignore that part, because it's hard to configure and won't even work on - // your free webhosting. - // - // A strategy is a function, that given the PHP environment and ($fun, $array) variable pair, returns - // an $action array or false. - // - // $fun - a controller function name, see inc/controller.php. This is named after functions, so that - // we can generate the files in daemon. - // - // $array - arguments to be passed - // - // $action - action to be taken. It's an array, and the first element of it is one of the following: - // * "immediate" - generate the page immediately - // * "defer" - defer page generation to a moment a worker daemon gets to build it (serving a stale - // page in the meantime). The remaining arguments are daemon-specific. Daemon isn't - // implemented yet :DDDD inb4 while(true) { generate(Queue::Get()) }; (which is probably it). - // * "build_on_load" - defer page generation to a moment, when the user actually accesses the page. - // This is a smart_build behaviour. You shouldn't use this one too much, if you - // use it for active boards, the server may choke due to a possible race condition. - // See my blog post: https://engine.vichan.net/blog/res/2.html - // - // So, let's assume we want to build a thread 1324 on board /b/, because a new post appeared there. - // We try the first strategy, giving it arguments: 'sb_thread', array('b', 1324). The strategy will - // now return a value $action, denoting an action to do. If $action is false, we try another strategy. - // - // As I said, configuration isn't easy. - // - // 1. chmod 0777 directories: tmp/locks/ and tmp/queue/. - // 2. serve 403 and 404 requests to go thru smart_build.php - // for nginx, this blog post contains config snippets: https://engine.vichan.net/blog/res/2.html - // 3. disable indexes in your webserver - // 4. launch any number of daemons (eg. twice your number of threads?) using the command: - // $ tools/worker.php - // You don't need to do that step if you are not going to use the "defer" option. - // 5. enable smart_build_helper (see below) - // 6. edit the strategies (see inc/functions.php for the builtin ones). You can use lambdas. I will test - // various ones and include one that works best for me. - $config['generation_strategies'] = array(); - // Add a sane strategy. It forces to immediately generate a page user is about to land on. Otherwise, - // it has no opinion, so it needs a fallback strategy. - $config['generation_strategies'][] = 'strategy_sane'; - // Add an immediate catch-all strategy. This is the default function of imageboards: generate all pages - // on post time. - $config['generation_strategies'][] = 'strategy_immediate'; - // NOT RECOMMENDED: Instead of an all-"immediate" strategy, you can use an all-"build_on_load" one (used - // to be initialized using $config['smart_build']; ) for all pages instead of those to be build - // immediately. A rebuild done in this mode should remove all your static files - // $config['generation_strategies'][1] = 'strategy_smart_build'; - - // Deprecated. Leave it false. See above. - $config['smart_build'] = false; - - // Use smart_build.php for dispatching missing requests. It may be useful without smart_build or advanced - // build, for example it will regenerate the missing files. - $config['smart_build_helper'] = true; - - // smart_build.php: when a file doesn't exist, where should we redirect? - $config['page_404'] = '/404.html'; - - // Extra controller entrypoints. Controller is used only by smart_build and advanced build. - $config['controller_entrypoints'] = array(); - + /* * ==================== * Mod settings @@ -1706,45 +1608,6 @@ // Example: Adding the pre-markup post body to the API as "com_nomarkup". // $config['api']['extra_fields'] = array('body_nomarkup' => 'com_nomarkup'); -/* - * ================== - * NNTPChan settings - * ================== - */ - -/* - * Please keep in mind that NNTPChan support in vichan isn't finished yet / is in an experimental - * state. Please join #nntpchan on Rizon in order to peer with someone. - */ - - $config['nntpchan'] = array(); - - // Enable NNTPChan integration - $config['nntpchan']['enabled'] = false; - - // NNTP server - $config['nntpchan']['server'] = "localhost:1119"; - - // Global dispatch array. Add your boards to it to enable them. Please make - // sure that this setting is set in a global context. - $config['nntpchan']['dispatch'] = array(); // 'overchan.test' => 'test' - - // Trusted peer - an IP address of your NNTPChan instance. This peer will have - // increased capabilities, eg.: will evade spamfilter. - $config['nntpchan']['trusted_peer'] = '127.0.0.1'; - - // Salt for message ID generation. Keep it long and secure. - $config['nntpchan']['salt'] = 'change_me+please'; - - // A local message ID domain. Make sure to change it. - $config['nntpchan']['domain'] = 'example.vichan.net'; - - // An NNTPChan group name. - // Please set this setting in your board/config.php, not globally. - $config['nntpchan']['group'] = false; // eg. 'overchan.test' - - - /* * ==================== * Other/uncategorized @@ -1842,8 +1705,5 @@ // You can set it to a higher value, to further migrate to other password hashing function. $config['password_crypt_version'] = 1; - // Use CAPTCHA for reports? - $config['report_captcha'] = false; - // Allowed HTML tags in ?/edit_pages. $config['allowed_html'] = 'a[href|title],p,br,li,ol,ul,strong,em,u,h2,b,i,tt,div,img[src|alt|title],hr'; diff --git a/inc/controller.php b/inc/controller.php deleted file mode 100644 index 02e33443..00000000 --- a/inc/controller.php +++ /dev/null @@ -1,108 +0,0 @@ - $config['max_pages']) return false; - $config['try_smarter'] = true; - $build_pages = array($page); - buildIndex("skip"); - return true; -} - -function sb_api_board($b, $page = 0) { $page = (int)$page; - return sb_board($b, $page + 1); -} - -function sb_thread($b, $thread, $slugcheck = false) { global $config; $thread = (int)$thread; - if ($thread < 1) return false; - - if (!preg_match('/^'.$config['board_regex'].'$/u', $b)) return false; - - if (Cache::get("thread_exists_".$b."_".$thread) == "no") return false; - - $query = prepare(sprintf("SELECT MAX(`id`) AS `max` FROM ``posts_%s``", $b)); - if (!$query->execute()) return false; - - $s = $query->fetch(PDO::FETCH_ASSOC); - $max = $s['max']; - - if ($thread > $max) return false; - - $query = prepare(sprintf("SELECT `id` FROM ``posts_%s`` WHERE `id` = :id AND `thread` IS NULL", $b)); - $query->bindValue(':id', $thread); - - if (!$query->execute() || !$query->fetch(PDO::FETCH_ASSOC) ) { - Cache::set("thread_exists_".$b."_".$thread, "no", 3600); - return false; - } - - if ($slugcheck && $config['slugify']) { - global $request; - - $link = link_for(array("id" => $thread), $slugcheck === 50, array("uri" => $b)); - $link = "/".$b."/".$config['dir']['res'].$link; - - if ($link != $request) { - header("Location: $link", true, 301); - die(); - } - } - - if ($slugcheck == 50) { // Should we really generate +50 page? Maybe there are not enough posts anyway - global $request; - $r = str_replace("+50", "", $request); - $r = substr($r, 1); // Cut the slash - - if (file_exists($r)) return false; - } - - if (!openBoard($b)) return false; - buildThread($thread); - return true; -} - -function sb_thread_slugcheck($b, $thread) { - return sb_thread($b, $thread, true); -} -function sb_thread_slugcheck50($b, $thread) { - return sb_thread($b, $thread, 50); -} - -function sb_api($b) { global $config, $build_pages; - if (!openBoard($b)) return false; - $config['try_smarter'] = true; - $build_pages = array(-1); - buildIndex(); - return true; -} - -function sb_ukko() { - rebuildTheme("ukko", "post-thread"); - return true; -} - -function sb_catalog($b) { - if (!openBoard($b)) return false; - - rebuildTheme("catalog", "post-thread", $b); - return true; -} - -function sb_recent() { - rebuildTheme("recent", "post-thread"); - return true; -} - -function sb_sitemap() { - rebuildTheme("sitemap", "all"); - return true; -} - diff --git a/inc/functions.php b/inc/functions.php index 3d620db6..cb8d603b 100755 --- a/inc/functions.php +++ b/inc/functions.php @@ -21,9 +21,6 @@ require_once 'inc/database.php'; require_once 'inc/events.php'; require_once 'inc/api.php'; require_once 'inc/mod/auth.php'; -require_once 'inc/lock.php'; -require_once 'inc/queue.php'; -require_once 'inc/polyfill.php'; // the user is not currently logged in as a moderator $mod = false; @@ -92,8 +89,6 @@ function loadConfig() { 'db', 'api', 'cache', - 'lock', - 'queue', 'cookies', 'error', 'dir', @@ -564,10 +559,6 @@ function openBoard($uri) { if ($b) { setupBoard($b); - if (function_exists('after_open_board')) { - after_open_board(); - } - return true; } return false; @@ -1343,7 +1334,7 @@ function thread_find_page($thread) { } // $brief means that we won't need to generate anything yet -function index($page, $mod=false, $brief = false) { +function index($page, $mod=false) { global $board, $config, $debug; $body = ''; @@ -1414,10 +1405,7 @@ function index($page, $mod=false, $brief = false) { } $threads[] = $thread; - - if (!$brief) { - $body .= $thread->build(true); - } + $body .= $thread->build(true); } if ($config['file_board']) { @@ -1639,10 +1627,9 @@ function checkMute() { function buildIndex($global_api = "yes") { global $board, $config, $build_pages; - $catalog_api_action = generation_strategy('sb_api', array($board['uri'])); - - $pages = null; - $antibot = null; + $pages = getPages(); + if ($config['try_smarter']) + $antibot = create_antibot($board['uri']); if ($config['api']['enabled']) { $api = new Api(); @@ -1653,54 +1640,43 @@ function buildIndex($global_api = "yes") { $filename = $board['dir'] . ($page == 1 ? $config['file_index'] : sprintf($config['file_page'], $page)); $jsonFilename = $board['dir'] . ($page - 1) . '.json'; // pages should start from 0 - $wont_build_this_page = $config['try_smarter'] && isset($build_pages) && !empty($build_pages) && !in_array($page, $build_pages); - - if ((!$config['api']['enabled'] || $global_api == "skip") && $wont_build_this_page) + if ((!$config['api']['enabled'] || $global_api == "skip") && $config['try_smarter'] && isset($build_pages) + && !empty($build_pages) && !in_array($page, $build_pages)) continue; - $action = generation_strategy('sb_board', array($board['uri'], $page)); - if ($action == 'rebuild' || $catalog_api_action == 'rebuild') { - $content = index($page, false, $wont_build_this_page); - if (!$content) - break; + $content = index($page); + if (!$content) + break; - // json api - if ($config['api']['enabled']) { - $threads = $content['threads']; - $json = json_encode($api->translatePage($threads)); - file_write($jsonFilename, $json); + // json api + if ($config['api']['enabled']) { + $threads = $content['threads']; + $json = json_encode($api->translatePage($threads)); + file_write($jsonFilename, $json); - $catalog[$page-1] = $threads; - - if ($wont_build_this_page) continue; - } - - if ($config['try_smarter']) { - $antibot = create_antibot($board['uri'], 0 - $page); - $content['current_page'] = $page; - } - elseif (!$antibot) { - $antibot = create_antibot($board['uri']); - } - $antibot->reset(); - if (!$pages) { - $pages = getPages(); - } - $content['pages'] = $pages; - $content['pages'][$page-1]['selected'] = true; - $content['btn'] = getPageButtons($content['pages']); - $content['antibot'] = $antibot; - - file_write($filename, Element('index.html', $content)); + $catalog[$page-1] = $threads; } - elseif ($action == 'delete' || $catalog_api_action == 'delete') { - file_unlink($filename); - file_unlink($jsonFilename); + + if ((!$config['api']['enabled'] || $global_api == "skip") && $config['try_smarter'] && isset($build_pages) + && !empty($build_pages) && !in_array($page, $build_pages)) + continue; + + if ($config['try_smarter']) { + $antibot = create_antibot($board['uri'], 0 - $page); + $content['current_page'] = $page; } + + $antibot->reset(); + $content['pages'] = $pages; + $content['pages'][$page-1]['selected'] = true; + $content['btn'] = getPageButtons($content['pages']); + $content['antibot'] = $antibot; + + file_write($filename, Element('index.html', $content)); } // $action is an action for our last page - if (($catalog_api_action == 'rebuild' || $action == 'rebuild' || $action == 'delete') && $page < $config['max_pages']) { + 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); @@ -1714,21 +1690,13 @@ function buildIndex($global_api = "yes") { // json api catalog if ($config['api']['enabled'] && $global_api != "skip") { - if ($catalog_api_action == 'delete') { - $jsonFilename = $board['dir'] . 'catalog.json'; - file_unlink($jsonFilename); - $jsonFilename = $board['dir'] . 'threads.json'; - file_unlink($jsonFilename); - } - elseif ($catalog_api_action == 'rebuild') { - $json = json_encode($api->translateCatalog($catalog)); - $jsonFilename = $board['dir'] . 'catalog.json'; - file_write($jsonFilename, $json); + $json = json_encode($api->translateCatalog($catalog)); + $jsonFilename = $board['dir'] . 'catalog.json'; + file_write($jsonFilename, $json); - $json = json_encode($api->translateCatalog($catalog, true)); - $jsonFilename = $board['dir'] . 'threads.json'; - file_write($jsonFilename, $json); - } + $json = json_encode($api->translateCatalog($catalog, true)); + $jsonFilename = $board['dir'] . 'threads.json'; + file_write($jsonFilename, $json); } if ($config['try_smarter']) @@ -2237,71 +2205,57 @@ function buildThread($id, $return = false, $mod = false) { cache::delete("thread_{$board['uri']}_{$id}"); } + $query = prepare(sprintf("SELECT * FROM ``posts_%s`` WHERE (`thread` IS NULL AND `id` = :id) OR `thread` = :id ORDER BY `thread`,`id`", $board['uri'])); + $query->bindValue(':id', $id, PDO::PARAM_INT); + $query->execute() or error(db_error($query)); + + while ($post = $query->fetch(PDO::FETCH_ASSOC)) { + if (!isset($thread)) + $thread = new Thread($post, $mod ? '?/' : $config['root'], $mod); + else + $thread->add(new Post($post, $mod ? '?/' : $config['root'], $mod)); + } + + // Check if any posts were found + if (!isset($thread)) + error($config['error']['nonexistant']); + + $hasnoko50 = $thread->postCount() >= $config['noko50_min']; + $antibot = $mod || $return ? false : create_antibot($board['uri'], $id); + + $body = Element('thread.html', array( + 'board' => $board, + 'thread' => $thread, + 'body' => $thread->build(), + 'config' => $config, + 'id' => $id, + 'mod' => $mod, + 'hasnoko50' => $hasnoko50, + 'isnoko50' => false, + 'antibot' => $antibot, + 'menu' => createMenu(), + 'return' => ($mod ? '?' . $board['url'] . $config['file_index'] : $config['root'] . $board['dir'] . $config['file_index']) + )); + + if ($config['try_smarter'] && !$mod) $build_pages[] = thread_find_page($id); - $action = generation_strategy('sb_thread', array($board['uri'], $id)); - - if ($action == 'rebuild' || $return || $mod) { - $query = prepare(sprintf("SELECT * FROM ``posts_%s`` WHERE (`thread` IS NULL AND `id` = :id) OR `thread` = :id ORDER BY `thread`,`id`", $board['uri'])); - $query->bindValue(':id', $id, PDO::PARAM_INT); - $query->execute() or error(db_error($query)); - - while ($post = $query->fetch(PDO::FETCH_ASSOC)) { - if (!isset($thread)) { - $thread = new Thread($post, $mod ? '?/' : $config['root'], $mod); - } else { - $thread->add(new Post($post, $mod ? '?/' : $config['root'], $mod)); - } - } - - // Check if any posts were found - if (!isset($thread)) - error($config['error']['nonexistant']); - - $hasnoko50 = $thread->postCount() >= $config['noko50_min']; - $antibot = $mod || $return ? false : create_antibot($board['uri'], $id); - - $body = Element('thread.html', array( - 'board' => $board, - 'thread' => $thread, - 'body' => $thread->build(), - 'config' => $config, - 'id' => $id, - 'mod' => $mod, - 'hasnoko50' => $hasnoko50, - 'isnoko50' => false, - 'antibot' => $antibot, - 'menu' => createMenu(), - 'return' => ($mod ? '?' . $board['url'] . $config['file_index'] : $config['root'] . $board['dir'] . $config['file_index']) - )); - - // json api - if ($config['api']['enabled'] && !$mod) { - $api = new Api(); - $json = json_encode($api->translateThread($thread)); - $jsonFilename = $board['dir'] . $config['dir']['res'] . $id . '.json'; - file_write($jsonFilename, $json); - } - } - elseif($action == 'delete') { + // json api + if ($config['api']['enabled'] && !$mod) { + $api = new Api(); + $json = json_encode($api->translateThread($thread)); $jsonFilename = $board['dir'] . $config['dir']['res'] . $id . '.json'; - file_unlink($jsonFilename); + file_write($jsonFilename, $json); } - if ($action == 'delete' && !$return && !$mod) { - $noko50fn = $board['dir'] . $config['dir']['res'] . link_for(array('id' => $id), true); - file_unlink($noko50fn); - - file_unlink($board['dir'] . $config['dir']['res'] . link_for(array('id' => $id))); - } elseif ($return) { + if ($return) { return $body; - } elseif ($action == 'rebuild') { + } else { $noko50fn = $board['dir'] . $config['dir']['res'] . link_for($thread, true); - if ($hasnoko50 || file_exists($noko50fn)) { + if ($hasnoko50 || file_exists($noko50fn)) buildThread50($id, $return, $mod, $thread, $antibot); - } - + file_write($board['dir'] . $config['dir']['res'] . link_for($thread), $body); } } @@ -2779,61 +2733,3 @@ function markdown($s) { return $pd->text($s); } - -function generation_strategy($fun, $array=array()) { global $config; - $action = false; - - foreach ($config['generation_strategies'] as $s) { - if ($action = $s($fun, $array)) { - break; - } - } - - switch ($action[0]) { - case 'immediate': - return 'rebuild'; - case 'defer': - // Ok, it gets interesting here :) - get_queue('generate')->push(serialize(array('build', $fun, $array, $action))); - return 'ignore'; - case 'build_on_load': - return 'delete'; - } -} - -function strategy_immediate($fun, $array) { - return array('immediate'); -} - -function strategy_smart_build($fun, $array) { - return array('build_on_load'); -} - -function strategy_sane($fun, $array) { global $config; - if (php_sapi_name() == 'cli') return false; - else if (isset($_POST['mod'])) return false; - // Thread needs to be done instantly. Same with a board page, but only if posting a new thread. - else if ($fun == 'sb_thread' || ($fun == 'sb_board' && $array[1] == 1 && isset ($_POST['page']))) return array('immediate'); - else return false; -} - -// My first, test strategy. -function strategy_first($fun, $array) { - switch ($fun) { - case 'sb_thread': - return array('defer'); - case 'sb_board': - if ($array[1] > 8) return array('build_on_load'); - else return array('defer'); - case 'sb_api': - return array('defer'); - case 'sb_catalog': - return array('defer'); - case 'sb_recent': - return array('build_on_load'); - case 'sb_sitemap': - return array('build_on_load'); - case 'sb_ukko': - return array('defer'); - } -} diff --git a/inc/lock.php b/inc/lock.php deleted file mode 100644 index 4fb2f5df..00000000 --- a/inc/lock.php +++ /dev/null @@ -1,39 +0,0 @@ -f = fopen("tmp/locks/$key", "w"); - } - } - - // Get a shared lock - function get($nonblock = false) { global $config; - if ($config['lock']['enabled'] == 'fs') { - $wouldblock = false; - flock($this->f, LOCK_SH | ($nonblock ? LOCK_NB : 0), $wouldblock); - if ($nonblock && $wouldblock) return false; - } - return $this; - } - - // Get an exclusive lock - function get_ex($nonblock = false) { global $config; - if ($config['lock']['enabled'] == 'fs') { - $wouldblock = false; - flock($this->f, LOCK_EX | ($nonblock ? LOCK_NB : 0), $wouldblock); - if ($nonblock && $wouldblock) return false; - } - return $this; - } - - // Free a lock - function free() { global $config; - if ($config['lock']['enabled'] == 'fs') { - flock($this->f, LOCK_UN); - } - return $this; - } -} diff --git a/inc/nntpchan/nntpchan.php b/inc/nntpchan/nntpchan.php deleted file mode 100644 index de67a193..00000000 --- a/inc/nntpchan/nntpchan.php +++ /dev/null @@ -1,152 +0,0 @@ -"; -} - - -function gen_nntp($headers, $files) { - if (count($files) == 0) { - } - else if (count($files) == 1 && $files[0]['type'] == 'text/plain') { - $content = $files[0]['text'] . "\r\n"; - $headers['Content-Type'] = "text/plain; charset=UTF-8"; - } - else { - $boundary = sha1($headers['Message-Id']); - $content = ""; - $headers['Content-Type'] = "multipart/mixed; boundary=$boundary"; - foreach ($files as $file) { - $content .= "--$boundary\r\n"; - if (isset($file['name'])) { - $file['name'] = preg_replace('/[\r\n\0"]/', '', $file['name']); - $content .= "Content-Disposition: form-data; filename=\"$file[name]\"; name=\"attachment\"\r\n"; - } - $type = explode('/', $file['type'])[0]; - if ($type == 'text') { - $file['type'] .= '; charset=UTF-8'; - } - $content .= "Content-Type: $file[type]\r\n"; - if ($type != 'text' && $type != 'message') { - $file['text'] = base64_encode($file['text']); - $content .= "Content-Transfer-Encoding: base64\r\n"; - } - $content .= "\r\n"; - $content .= $file['text']; - $content .= "\r\n"; - } - $content .= "--$boundary--\r\n"; - - $headers['Mime-Version'] = '1.0'; - } - //$headers['Content-Length'] = strlen($content); - $headers['Date'] = date('r', $headers['Date']); - $out = ""; - foreach ($headers as $id => $val) { - $val = str_replace("\n", "\n\t", $val); - $out .= "$id: $val\r\n"; - } - $out .= "\r\n"; - $out .= $content; - return $out; -} - -function nntp_publish($msg, $id) { - global $config; - $server = $config["nntpchan"]["server"]; - $s = fsockopen("tcp://$server"); - fgets($s); - fputs($s, "MODE STREAM\r\n"); - fgets($s); - fputs($s, "TAKETHIS $id\r\n"); - fputs($s, $msg); - fputs($s, "\r\n.\r\n"); - fgets($s); - fputs($s, "QUIT\r\n"); - fclose($s); -} - -function post2nntp($post, $msgid) { - global $config; - - $headers = array(); - $files = array(); - - $headers['Message-Id'] = $msgid; - $headers['Newsgroups'] = $config['nntpchan']['group']; - $headers['Date'] = time(); - $headers['Subject'] = $post['subject'] ? $post['subject'] : "None"; - $headers['From'] = $post['name'] . " "; - - if ($post['email'] == 'sage') { - $headers['X-Sage'] = true; - } - - if (!$post['op']) { - // Get muh parent - $query = prepare("SELECT `message_id` FROM ``nntp_references`` WHERE `board` = :board AND `id` = :id"); - $query->bindValue(':board', $post['board']); - $query->bindValue(':id', $post['thread']); - $query->execute() or error(db_error($query)); - - if ($result = $query->fetch(PDO::FETCH_ASSOC)) { - $headers['References'] = $result['message_id']; - } - else { - return false; // We don't have OP. Discarding. - } - } - - // Let's parse the body a bit. - $body = trim($post['body_nomarkup']); - $body = preg_replace('/\r?\n/', "\r\n", $body); - $body = preg_replace_callback('@>>(>/([a-zA-Z0-9_+-]+)/)?([0-9]+)@', function($o) use ($post) { - if ($o[1]) { - $board = $o[2]; - } - else { - $board = $post['board']; - } - $id = $o[3]; - - $query = prepare("SELECT `message_id_digest` FROM ``nntp_references`` WHERE `board` = :board AND `id` = :id"); - $query->bindValue(':board', $board); - $query->bindValue(':id', $id); - $query->execute() or error(db_error($query)); - - if ($result = $query->fetch(PDO::FETCH_ASSOC)) { - return ">>".substr($result['message_id_digest'], 0, 18); - } - else { - return $o[0]; // Should send URL imo - } - }, $body); - $body = preg_replace('/>>>>([0-9a-fA-F])+/', '>>\1', $body); - - - $files[] = array('type' => 'text/plain', 'text' => $body); - - foreach ($post['files'] as $id => $file) { - $fc = array(); - - $fc['type'] = $file['type']; - $fc['text'] = file_get_contents($file['file_path']); - $fc['name'] = $file['name']; - - $files[] = $fc; - } - - return array($headers, $files); -} diff --git a/inc/nntpchan/tests.php b/inc/nntpchan/tests.php deleted file mode 100644 index a63789d7..00000000 --- a/inc/nntpchan/tests.php +++ /dev/null @@ -1,30 +0,0 @@ - "czaks ", "Message-Id" => "<1234.0000.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None"], -[['type' => 'text/plain', 'text' => "THIS IS A NEW TEST THREAD"]]); -echo "\n@@@@ Single msg:\n"; -echo $m1 = gennntp(["From" => "czaks ", "Message-Id" => "<1234.1234.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None", "References" => "<1234.0000.".$time."@example.vichan.net>"], -[['type' => 'text/plain', 'text' => "hello world, with no image :("]]); -echo "\n@@@@ Single msg and pseudoimage:\n"; -echo $m2 = gennntp(["From" => "czaks ", "Message-Id" => "<1234.2137.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None", "References" => "<1234.0000.".$time."@example.vichan.net>"], -[['type' => 'text/plain', 'text' => "hello world, now with an image!"], - ['type' => 'image/gif', 'text' => base64_decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), 'name' => "urgif.gif"]]); -echo "\n@@@@ Single msg and two pseudoimages:\n"; -echo $m3 = gennntp(["From" => "czaks ", "Message-Id" => "<1234.1488.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None", "References" => "<1234.0000.".$time."@example.vichan.net>"], -[['type' => 'text/plain', 'text' => "hello world, now WITH TWO IMAGES!!!"], - ['type' => 'image/gif', 'text' => base64_decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), 'name' => "urgif.gif"], - ['type' => 'image/gif', 'text' => base64_decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), 'name' => "urgif2.gif"]]); -shoveitup($m0, "<1234.0000.".$time."@example.vichan.net>"); -sleep(1); -shoveitup($m1, "<1234.1234.".$time."@example.vichan.net>"); -sleep(1); -shoveitup($m2, "<1234.2137.".$time."@example.vichan.net>"); -shoveitup($m3, "<1234.1488.".$time."@example.vichan.net>"); - diff --git a/inc/polyfill.php b/inc/polyfill.php deleted file mode 100644 index ac40a00a..00000000 --- a/inc/polyfill.php +++ /dev/null @@ -1,28 +0,0 @@ - $i ? $i : 0]) ^ ord($theirs[$i]); - } - - return $answer === 0 && $olen === $tlen; - } -} diff --git a/inc/queue.php b/inc/queue.php deleted file mode 100644 index 66305b3b..00000000 --- a/inc/queue.php +++ /dev/null @@ -1,49 +0,0 @@ -lock = new Lock($key); - $key = str_replace('/', '::', $key); - $key = str_replace("\0", '', $key); - $this->key = "tmp/queue/$key/"; - } - } - - function push($str) { global $config; - if ($config['queue']['enabled'] == 'fs') { - $this->lock->get_ex(); - file_put_contents($this->key.microtime(true), $str); - $this->lock->free(); - } - return $this; - } - - function pop($n = 1) { global $config; - if ($config['queue']['enabled'] == 'fs') { - $this->lock->get_ex(); - $dir = opendir($this->key); - $paths = array(); - while ($n > 0) { - $path = readdir($dir); - if ($path === FALSE) break; - elseif ($path == '.' || $path == '..') continue; - else { $paths[] = $path; $n--; } - } - $out = array(); - foreach ($paths as $v) { - $out []= file_get_contents($this->key.$v); - unlink($this->key.$v); - } - $this->lock->free(); - return $out; - } - } -} - -// Don't use the constructor. Use the get_queue function. -$queues = array(); - -function get_queue($name) { global $queues; - return $queues[$name] = isset ($queues[$name]) ? $queues[$name] : new Queue($name); -} diff --git a/inc/route.php b/inc/route.php deleted file mode 100644 index 2a5c1732..00000000 --- a/inc/route.php +++ /dev/null @@ -1,65 +0,0 @@ - $fun) { - $id = '@^' . preg_quote($id, '@') . '$@u'; - - $id = str_replace('%b', '('.$config['board_regex'].')', $id); - $id = str_replace('%d', '([0-9]+)', $id); - $id = str_replace('%s', '[a-zA-Z0-9-]+', $id); - - $matches = null; - - if (preg_match ($id, $request, $matches)) { - array_shift($matches); - - $reached = array($fun, $matches); - - break; - } - } - - return $reached; -} - diff --git a/install.php b/install.php index 899954b8..bc31cebc 100644 --- a/install.php +++ b/install.php @@ -1,7 +1,7 @@ salt_length; ++$i) { - $s = pack("c", mt_rand(0,255)); - $ret = $ret . $s; - } - - return base64_encode($ret); - } - // Best function of the lot. Works with any PHP version as long as OpenSSL extension is on private function generate_install_salt_openssl() { $ret = openssl_random_pseudo_bytes($this->salt_length, $strong); - if (!$strong) { + if (!$strong) error(_("Misconfigured system: OpenSSL returning weak salts. Cannot continue.")); - } return base64_encode($ret); } @@ -37,13 +23,10 @@ class SaltGen { // TODO: Perhaps add mcrypt as an option? Maybe overkill. public function generate() { - if (extension_loaded('openssl')) { + if (extension_loaded('openssl')) return "OSSL." . $this->generate_install_salt_openssl(); - } else if (defined('PHP_MAJOR_VERSION') && PHP_MAJOR_VERSION >= 7) { + else return "PHP7." . $this->generate_install_salt_php7(); - } else { - return "INSECURE." . $this->generate_install_salt(); - } } } @@ -561,7 +544,8 @@ if (file_exists($config['has_installed'])) { break; } case '4.4.98-pre': - if (!$twig) load_twig(); + if (!$twig) + load_twig(); $twig->clearCacheFiles(); case '4.4.98': case '4.5.0': @@ -590,12 +574,11 @@ if (file_exists($config['has_installed'])) { case '4.9.90': case '4.9.91': case '4.9.92': - foreach ($boards as &$board) { - query(sprintf('ALTER TABLE ``posts_%s`` ADD `slug` VARCHAR(255) DEFAULT NULL AFTER `embed`;', $board['uri'])) or error(db_error()); - } - case '4.9.93': - query('ALTER TABLE ``mods`` CHANGE `password` `password` VARCHAR(255) NOT NULL;') or error(db_error()); - query('ALTER TABLE ``mods`` CHANGE `salt` `salt` VARCHAR(64) NOT NULL;') or error(db_error()); + foreach ($boards as &$board) + query(sprintf('ALTER TABLE ``posts_%s`` ADD `slug` VARCHAR(255) DEFAULT NULL AFTER `embed`;', $board['uri'])) or error(db_error()); + case '4.9.93': + query('ALTER TABLE ``mods`` CHANGE `password` `password` VARCHAR(255) NOT NULL;') or error(db_error()); + query('ALTER TABLE ``mods`` CHANGE `salt` `salt` VARCHAR(64) NOT NULL;') or error(db_error()); case '5.0.0': query('ALTER TABLE ``mods`` CHANGE `salt` `version` VARCHAR(64) NOT NULL;') or error(db_error()); case '5.0.1': @@ -611,9 +594,8 @@ if (file_exists($config['has_installed'])) { UNIQUE KEY `u_pages` (`name`,`board`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;') or error(db_error()); case '5.1.1': - foreach ($boards as &$board) { - query(sprintf("ALTER TABLE ``posts_%s`` ADD `cycle` int(1) NOT NULL AFTER `locked`", $board['uri'])) or error(db_error()); - } + foreach ($boards as &$board) + query(sprintf("ALTER TABLE ``posts_%s`` ADD `cycle` int(1) NOT NULL AFTER `locked`", $board['uri'])) or error(db_error()); case '5.1.2': query('CREATE TABLE IF NOT EXISTS ``nntp_references`` ( `board` varchar(60) NOT NULL, @@ -635,6 +617,9 @@ if (file_exists($config['has_installed'])) { `created_at` int(11), PRIMARY KEY (`cookie`,`extra`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;') or error(db_error()); + case '5.2.0-dev-1': + query('DROP TABLE IF EXISTS ``nntp_references``; + DROP TABLE IF EXISTS ``captchas``;') or error(db_error()); case false: // TODO: enhance Tinyboard -> vichan upgrade path. query("CREATE TABLE IF NOT EXISTS ``search_queries`` ( `ip` varchar(39) NOT NULL, `time` int(11) NOT NULL, `query` text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8;") or error(db_error()); @@ -647,11 +632,11 @@ if (file_exists($config['has_installed'])) { break; default: $page['title'] = 'Unknown version'; - $page['body'] = '

vichan was unable to determine what version is currently installed.

'; + $page['body'] = '

Tinyboard was unable to determine what version is currently installed.

'; break; case VERSION: $page['title'] = 'Already installed'; - $page['body'] = '

It appears that vichan is already installed (' . $version . ') and there is nothing to upgrade! Delete ' . $config['has_installed'] . ' to reinstall.

'; + $page['body'] = '

It appears that Tinyboard is already installed (' . $version . ') and there is nothing to upgrade! Delete ' . $config['has_installed'] . ' to reinstall.

'; break; } @@ -729,17 +714,17 @@ if ($step == 0) { $tests = array( array( 'category' => 'PHP', - 'name' => 'PHP ≥ 5.4', - 'result' => PHP_VERSION_ID >= 50400, + 'name' => 'PHP ≥ 7.0', + 'result' => PHP_VERSION_ID >= 70000, 'required' => true, - 'message' => 'vichan requires PHP 5.4 or better.', + 'message' => 'Tinyboard requires PHP 7.0 or better.', ), array( 'category' => 'PHP', - 'name' => 'PHP ≥ 5.6', - 'result' => PHP_VERSION_ID >= 50600, + 'name' => 'PHP ≥ 7.2', + 'result' => PHP_VERSION_ID >= 70200, 'required' => false, - 'message' => 'vichan works best on PHP 5.6 or better.', + 'message' => 'Tinyboard works best on PHP 7.2 or better.', ), array( 'category' => 'PHP', @@ -750,10 +735,10 @@ if ($step == 0) { ), array( 'category' => 'PHP', - 'name' => 'OpenSSL extension installed or PHP ≥ 7.0', - 'result' => (extension_loaded('openssl') || (defined('PHP_MAJOR_VERSION') && PHP_MAJOR_VERSION >= 7)), + 'name' => 'OpenSSL extension installed', + 'result' => extension_loaded('openssl'), 'required' => false, - 'message' => 'It is highly recommended that you install the PHP OpenSSL extension and/or use PHP version 7 or above. If you do not, it is possible that the IP addresses of users of your site could be compromised — see vichan issue #284. Installing the OpenSSL extension allows vichan to generate a secure salt automatically for you.', + 'message' => 'It is highly recommended that you install the PHP OpenSSL extension. Installing the OpenSSL extension allows Tinyboard to generate a secure salt automatically for you.', ), array( 'category' => 'Database', @@ -851,28 +836,28 @@ if ($step == 0) { 'name' => getcwd(), 'result' => is_writable('.'), 'required' => true, - 'message' => 'vichan does not have permission to create directories (boards) here. You will need to chmod (or operating system equivalent) appropriately.' + '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 vichan permission to create (and write to) the templates/cache directory or performance will be drastically reduced.' + '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() . '/tmp/cache', 'result' => is_dir('tmp/cache') && is_writable('tmp/cache'), 'required' => true, - 'message' => 'You must give vichan permission to write to the tmp/cache directory.' + 'message' => 'You must give Tinyboard permission to write to the tmp/cache directory.' ), array( 'category' => 'File permissions', 'name' => getcwd() . '/inc/instance-config.php', 'result' => is_writable('inc/instance-config.php'), 'required' => false, - 'message' => 'vichan 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', @@ -884,10 +869,10 @@ if ($step == 0) { ), array( 'category' => 'Misc', - 'name' => 'vichan installed using git', + 'name' => 'Tinyboard installed using git', 'result' => is_dir('.git'), 'required' => false, - 'message' => 'vichan is still beta software and it\'s not going to come out of beta any time soon. As there are often many months between releases yet changes and bug fixes are very frequent, it\'s recommended to use the git repository to maintain your vichan installation. Using git makes upgrading much easier.' + 'message' => 'Tinyboard is still beta software and it\'s not going to come out of beta any time soon. As there are often many months between releases yet changes and bug fixes are very frequent, it\'s recommended to use the git repository to maintain your Tinyboard installation. Using git makes upgrading much easier.' ) ); diff --git a/install.sql b/install.sql index ca60a58a..64ee259e 100644 --- a/install.sql +++ b/install.sql @@ -314,39 +314,6 @@ CREATE TABLE IF NOT EXISTS `pages` ( UNIQUE KEY `u_pages` (`name`,`board`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; --- -------------------------------------------------------- - --- --- Table structure for table `nntp_references` --- - -CREATE TABLE IF NOT EXISTS `nntp_references` ( - `board` varchar(30) NOT NULL, - `id` int(11) unsigned NOT NULL, - `message_id` varchar(255) CHARACTER SET ascii NOT NULL, - `message_id_digest` varchar(40) CHARACTER SET ascii NOT NULL, - `own` tinyint(1) NOT NULL, - `headers` text, - PRIMARY KEY (`message_id_digest`), - UNIQUE KEY `message_id` (`message_id`), - UNIQUE KEY `u_board_id` (`board`, `id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; - --- -------------------------------------------------------- - --- --- Table structure for table `captchas` --- - -CREATE TABLE IF NOT EXISTS `captchas` ( - `cookie` VARCHAR(50), - `extra` VARCHAR(200), - `text` VARCHAR(255), - `created_at` INT(11), - PRIMARY KEY (`cookie`,`extra`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; - - /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/js/captcha.js b/js/captcha.js deleted file mode 100644 index 018588b7..00000000 --- a/js/captcha.js +++ /dev/null @@ -1,43 +0,0 @@ -var tout; - -function redo_events(provider, extra) { - $('.captcha .captcha_text, textarea[id="body"]').off("focus").one("focus", function() { actually_load_captcha(provider, extra); }); -} - -function actually_load_captcha(provider, extra) { - $('.captcha .captcha_text, textarea[id="body"]').off("focus"); - - if (tout !== undefined) { - clearTimeout(tout); - } - - $.getJSON(provider, {mode: 'get', extra: extra}, function(json) { - $(".captcha .captcha_cookie").val(json.cookie); - $(".captcha .captcha_html").html(json.captchahtml); - - setTimeout(function() { - redo_events(provider, extra); - }, json.expires_in * 1000); - }); -} - -function load_captcha(provider, extra) { - $(function() { - $(".captcha>td").html(""+ - ""+ - "
"); - - $("#quick-reply .captcha .captcha_text").prop("placeholder", _("Verification")); - - $(".captcha .captcha_html").on("click", function() { actually_load_captcha(provider, extra); }); - $(document).on("ajax_after_post", function() { actually_load_captcha(provider, extra); }); - redo_events(provider, extra); - - $(window).on("quick-reply", function() { - redo_events(provider, extra); - $("#quick-reply .captcha .captcha_html").html($("form:not(#quick-reply) .captcha .captcha_html").html()); - $("#quick-reply .captcha .captcha_cookie").val($("form:not(#quick-reply) .captcha .captcha_cookie").html()); - $("#quick-reply .captcha .captcha_html").on("click", function() { actually_load_captcha(provider, extra); }); - }); - }); -} \ No newline at end of file diff --git a/post.php b/post.php index 3ca3bb23..fc56a28b 100644 --- a/post.php +++ b/post.php @@ -11,170 +11,6 @@ if ((!isset($_POST['mod']) || !$_POST['mod']) && $config['board_locked']) { error("Board is locked"); } -$dropped_post = false; - -// Is it a post coming from NNTP? Let's extract it and pretend it's a normal post. -if (isset($_GET['Newsgroups']) && $config['nntpchan']['enabled']) { - if ($_SERVER['REMOTE_ADDR'] != $config['nntpchan']['trusted_peer']) { - error("NNTPChan: Forbidden. $_SERVER[REMOTE_ADDR] is not a trusted peer"); - } - - $_POST = array(); - $_POST['json_response'] = true; - - $headers = json_encode($_GET); - - if (!isset ($_GET['Message-Id'])) { - if (!isset ($_GET['Message-ID'])) { - error("NNTPChan: No message ID"); - } - else $msgid = $_GET['Message-ID']; - } - else $msgid = $_GET['Message-Id']; - - $groups = preg_split("/,\s*/", $_GET['Newsgroups']); - if (count($groups) != 1) { - error("NNTPChan: Messages can go to only one newsgroup"); - } - $group = $groups[0]; - - if (!isset($config['nntpchan']['dispatch'][$group])) { - error("NNTPChan: We don't synchronize $group"); - } - $xboard = $config['nntpchan']['dispatch'][$group]; - - $ref = null; - if (isset ($_GET['References'])) { - $refs = preg_split("/,\s*/", $_GET['References']); - - if (count($refs) > 1) { - error("NNTPChan: We don't support multiple references"); - } - - $ref = $refs[0]; - - $query = prepare("SELECT `board`,`id` FROM ``nntp_references`` WHERE `message_id` = :ref"); - $query->bindValue(':ref', $ref); - $query->execute() or error(db_error($query)); - - $ary = $query->fetchAll(PDO::FETCH_ASSOC); - - if (count($ary) == 0) { - error("NNTPChan: We don't have $ref that $msgid references"); - } - - $p_id = $ary[0]['id']; - $p_board = $ary[0]['board']; - - if ($p_board != $xboard) { - error("NNTPChan: Cross board references not allowed. Tried to reference $p_board on $xboard"); - } - - $_POST['thread'] = $p_id; - } - - $date = isset($_GET['Date']) ? strtotime($_GET['Date']) : time(); - - list($ct) = explode('; ', $_GET['Content-Type']); - - $query = prepare("SELECT COUNT(*) AS `c` FROM ``nntp_references`` WHERE `message_id` = :msgid"); - $query->bindValue(":msgid", $msgid); - $query->execute() or error(db_error($query)); - - $a = $query->fetch(PDO::FETCH_ASSOC); - if ($a['c'] > 0) { - error("NNTPChan: We already have this post. Post discarded."); - } - - if ($ct == 'text/plain') { - $content = file_get_contents("php://input"); - } - elseif ($ct == 'multipart/mixed' || $ct == 'multipart/form-data') { - _syslog(LOG_INFO, "MM: Files: ".print_r($GLOBALS, true)); // Debug - - $content = ''; - - $newfiles = array(); - foreach ($_FILES['attachment']['error'] as $id => $error) { - if ($_FILES['attachment']['type'][$id] == 'text/plain') { - $content .= file_get_contents($_FILES['attachment']['tmp_name'][$id]); - } - elseif ($_FILES['attachment']['type'][$id] == 'message/rfc822') { // Signed message, ignore for now - } - else { // A real attachment :^) - $file = array(); - $file['name'] = $_FILES['attachment']['name'][$id]; - $file['type'] = $_FILES['attachment']['type'][$id]; - $file['size'] = $_FILES['attachment']['size'][$id]; - $file['tmp_name'] = $_FILES['attachment']['tmp_name'][$id]; - $file['error'] = $_FILES['attachment']['error'][$id]; - - $newfiles["file$id"] = $file; - } - } - - $_FILES = $newfiles; - } - else { - error("NNTPChan: Wrong mime type: $ct"); - } - - $_POST['subject'] = isset($_GET['Subject']) ? ($_GET['Subject'] == 'None' ? '' : $_GET['Subject']) : ''; - $_POST['board'] = $xboard; - - if (isset ($_GET['From'])) { - list($name, $mail) = explode(" <", $_GET['From'], 2); - $mail = preg_replace('/>\s+$/', '', $mail); - - $_POST['name'] = $name; - //$_POST['email'] = $mail; - $_POST['email'] = ''; - } - - if (isset ($_GET['X_Sage'])) { - $_POST['email'] = 'sage'; - } - - $content = preg_replace_callback('/>>([0-9a-fA-F]{6,})/', function($id) use ($xboard) { - $id = $id[1]; - - $query = prepare("SELECT `board`,`id` FROM ``nntp_references`` WHERE `message_id_digest` LIKE :rule"); - $idx = $id . "%"; - $query->bindValue(':rule', $idx); - $query->execute() or error(db_error($query)); - - $ary = $query->fetchAll(PDO::FETCH_ASSOC); - if (count($ary) == 0) { - return ">>>>$id"; - } - else { - $ret = array(); - foreach ($ary as $v) { - if ($v['board'] != $xboard) { - $ret[] = ">>>/".$v['board']."/".$v['id']; - } - else { - $ret[] = ">>".$v['id']; - } - } - return implode($ret, ", "); - } - }, $content); - - $_POST['body'] = $content; - - $dropped_post = array( - 'date' => $date, - 'board' => $xboard, - 'msgid' => $msgid, - 'headers' => $headers, - 'from_nntp' => true, - ); -} -elseif (isset($_GET['Newsgroups'])) { - error("NNTPChan: NNTPChan support is disabled"); -} - if (isset($_POST['delete'])) { // Delete @@ -291,21 +127,18 @@ if (isset($_POST['delete'])) { if (count($report) > $config['report_limit']) error($config['error']['toomanyreports']); - if ($config['report_captcha'] && !isset($_POST['captcha_text'], $_POST['captcha_cookie'])) { - error($config['error']['bot']); - } + if ($config['recaptcha']) { + if (!isset($_POST['g-recaptcha-response'])) + error($config['error']['bot']); - if ($config['report_captcha']) { - $resp = file_get_contents($config['captcha']['provider_check'] . "?" . http_build_query([ - 'mode' => 'check', - 'text' => $_POST['captcha_text'], - 'extra' => $config['captcha']['extra'], - 'cookie' => $_POST['captcha_cookie'] - ])); + // Check what reCAPTCHA has to say... + $resp = json_decode(file_get_contents(sprintf('https://www.google.com/recaptcha/api/siteverify?secret=%s&response=%s&remoteip=%s', + $config['recaptcha_private'], + urlencode($_POST['g-recaptcha-response']), + $_SERVER['REMOTE_ADDR'])), true); - if ($resp !== '1') { - error($config['error']['captcha']); - } + if (!$resp['success']) + error($config['error']['captcha']); } $reason = escape_markup_modifiers($_POST['reason']); @@ -318,11 +151,10 @@ if (isset($_POST['delete'])) { $post = $query->fetch(PDO::FETCH_ASSOC); - $error = event('report', array('ip' => $_SERVER['REMOTE_ADDR'], 'board' => $board['uri'], 'post' => $post, 'reason' => $reason, 'link' => link_for($post))); + $error = event('report', array('ip' => $_SERVER['REMOTE_ADDR'], 'board' => $board['uri'], 'post' => $post, 'reason' => $reason, 'link' => link_for($post))); - if ($error) { - error($error); - } + if ($error) + error($error); if ($config['syslog']) _syslog(LOG_INFO, 'Reported post: ' . @@ -348,8 +180,8 @@ if (isset($_POST['delete'])) { header('Content-Type: text/json'); echo json_encode(array('success' => true)); } -} elseif (isset($_POST['post']) || $dropped_post) { - if (!isset($_POST['body'], $_POST['board']) && !$dropped_post) +} elseif (isset($_POST['post'])) { + if (!isset($_POST['body'], $_POST['board'])) error($config['error']['bot']); $post = array('board' => $_POST['board'], 'files' => array()); @@ -376,85 +208,63 @@ if (isset($_POST['delete'])) { } else $post['op'] = true; + // Check if banned + checkBan($board['uri']); - if (!$dropped_post) { + // Check for CAPTCHA right after opening the board so the "return" link is in there + if ($config['recaptcha']) { + if (!isset($_POST['g-recaptcha-response'])) + error($config['error']['bot']); - // Check if banned - checkBan($board['uri']); + // Check what reCAPTCHA has to say... + $resp = json_decode(file_get_contents(sprintf('https://www.google.com/recaptcha/api/siteverify?secret=%s&response=%s&remoteip=%s', + $config['recaptcha_private'], + urlencode($_POST['g-recaptcha-response']), + $_SERVER['REMOTE_ADDR'])), true); - // Check for CAPTCHA right after opening the board so the "return" link is in there - if ($config['recaptcha']) { - if (!isset($_POST['g-recaptcha-response'])) - error($config['error']['bot']); - - // Check what reCAPTCHA has to say... - $resp = json_decode(file_get_contents(sprintf('https://www.google.com/recaptcha/api/siteverify?secret=%s&response=%s&remoteip=%s', - $config['recaptcha_private'], - urlencode($_POST['g-recaptcha-response']), - $_SERVER['REMOTE_ADDR'])), true); - - if (!$resp['success']) { - error($config['error']['captcha']); - } - // Same, but now with our custom captcha provider - if (($config['captcha']['enabled']) || (($post['op']) && ($config['new_thread_capt'])) ) { - $resp = file_get_contents($config['captcha']['provider_check'] . "?" . http_build_query([ - 'mode' => 'check', - 'text' => $_POST['captcha_text'], - 'extra' => $config['captcha']['extra'], - 'cookie' => $_POST['captcha_cookie'] - ])); - if ($resp !== '1') { - error($config['error']['captcha'] . - ''); - } + if (!$resp['success']) + error($config['error']['captcha']); } -} - if (!(($post['op'] && $_POST['post'] == $config['button_newtopic']) || - (!$post['op'] && $_POST['post'] == $config['button_reply']))) - error($config['error']['bot']); - - // Check the referrer - if ($config['referer_match'] !== false && - (!isset($_SERVER['HTTP_REFERER']) || !preg_match($config['referer_match'], rawurldecode($_SERVER['HTTP_REFERER'])))) - error($config['error']['referer']); - - checkDNSBL(); - + if (!(($post['op'] && $_POST['post'] == $config['button_newtopic']) || + (!$post['op'] && $_POST['post'] == $config['button_reply']))) + error($config['error']['bot']); - if ($post['mod'] = isset($_POST['mod']) && $_POST['mod']) { - check_login(false); - if (!$mod) { - // Liar. You're not a mod. - error($config['error']['notamod']); - } - - $post['sticky'] = $post['op'] && isset($_POST['sticky']); - $post['locked'] = $post['op'] && isset($_POST['lock']); - $post['raw'] = isset($_POST['raw']); - - if ($post['sticky'] && !hasPermission($config['mod']['sticky'], $board['uri'])) - error($config['error']['noaccess']); - if ($post['locked'] && !hasPermission($config['mod']['lock'], $board['uri'])) - error($config['error']['noaccess']); - if ($post['raw'] && !hasPermission($config['mod']['rawhtml'], $board['uri'])) - error($config['error']['noaccess']); - } - - if (!$post['mod']) { - $post['antispam_hash'] = checkSpam(array($board['uri'], isset($post['thread']) ? $post['thread'] : ($config['try_smarter'] && isset($_POST['page']) ? 0 - (int)$_POST['page'] : null))); - if ($post['antispam_hash'] === true) - error($config['error']['spam']); + // Check the referrer + if ($config['referer_match'] !== false && + (!isset($_SERVER['HTTP_REFERER']) || !preg_match($config['referer_match'], rawurldecode($_SERVER['HTTP_REFERER'])))) + error($config['error']['referer']); + + checkDNSBL(); + + + if ($post['mod'] = isset($_POST['mod']) && $_POST['mod']) { + check_login(false); + if (!$mod) { + // Liar. You're not a mod. + error($config['error']['notamod']); } - if ($config['robot_enable'] && $config['robot_mute']) { - checkMute(); - } + $post['sticky'] = $post['op'] && isset($_POST['sticky']); + $post['locked'] = $post['op'] && isset($_POST['lock']); + $post['raw'] = isset($_POST['raw']); + + if ($post['sticky'] && !hasPermission($config['mod']['sticky'], $board['uri'])) + error($config['error']['noaccess']); + if ($post['locked'] && !hasPermission($config['mod']['lock'], $board['uri'])) + error($config['error']['noaccess']); + if ($post['raw'] && !hasPermission($config['mod']['rawhtml'], $board['uri'])) + error($config['error']['noaccess']); } - else { - $mod = $post['mod'] = false; + + if (!$post['mod']) { + $post['antispam_hash'] = checkSpam(array($board['uri'], isset($post['thread']) ? $post['thread'] : ($config['try_smarter'] && isset($_POST['page']) ? 0 - (int)$_POST['page'] : null))); + if ($post['antispam_hash'] === true) + error($config['error']['spam']); } + + if ($config['robot_enable'] && $config['robot_mute']) + checkMute(); //Check if thread exists if (!$post['op']) { @@ -466,11 +276,8 @@ if (isset($_POST['delete'])) { // Non-existant error($config['error']['nonexistant']); } - } - else { + } else $thread = false; - } - // Check for an embed field if ($config['enable_embedding'] && isset($_POST['embed']) && !empty($_POST['embed'])) { @@ -485,9 +292,8 @@ if (isset($_POST['delete'])) { break; } } - if (!isset($post['embed'])) { + if (!isset($post['embed'])) error($config['error']['invalid_embed']); - } } if (!hasPermission($config['mod']['bypass_field_disable'], $board['uri'])) { @@ -565,53 +371,41 @@ if (isset($_POST['delete'])) { $post['body'] = $_POST['body']; $post['password'] = $_POST['password']; $post['has_file'] = (!isset($post['embed']) && (($post['op'] && !isset($post['no_longer_require_an_image_for_op']) && $config['force_image_op']) || count($_FILES) > 0)); - - if (!$dropped_post) { - if (!($post['has_file'] || isset($post['embed'])) || (($post['op'] && $config['force_body_op']) || (!$post['op'] && $config['force_body']))) { - $stripped_whitespace = preg_replace('/[\s]/u', '', $post['body']); - if ($stripped_whitespace == '') { - error($config['error']['tooshort_body']); - } - } - - if (!$post['op']) { - // Check if thread is locked - // but allow mods to post - if ($thread['locked'] && !hasPermission($config['mod']['postinlocked'], $board['uri'])) - error($config['error']['locked']); - - $numposts = numPosts($post['thread']); - - if ($config['reply_hard_limit'] != 0 && $config['reply_hard_limit'] <= $numposts['replies']) - error($config['error']['reply_hard_limit']); - - if ($post['has_file'] && $config['image_hard_limit'] != 0 && $config['image_hard_limit'] <= $numposts['images']) - error($config['error']['image_hard_limit']); - } + if (!($post['has_file'] || isset($post['embed'])) || (($post['op'] && $config['force_body_op']) || (!$post['op'] && $config['force_body']))) { + $stripped_whitespace = preg_replace('/[\s]/u', '', $post['body']); + if ($stripped_whitespace == '') + error($config['error']['tooshort_body']); } - else { - if (!$post['op']) { - $numposts = numPosts($post['thread']); - } + + if (!$post['op']) { + // Check if thread is locked + // but allow mods to post + if ($thread['locked'] && !hasPermission($config['mod']['postinlocked'], $board['uri'])) + error($config['error']['locked']); + + $numposts = numPosts($post['thread']); + + if ($config['reply_hard_limit'] != 0 && $config['reply_hard_limit'] <= $numposts['replies']) + error($config['error']['reply_hard_limit']); + + if ($post['has_file'] && $config['image_hard_limit'] != 0 && $config['image_hard_limit'] <= $numposts['images']) + error($config['error']['image_hard_limit']); } if ($post['has_file']) { // Determine size sanity $size = 0; if ($config['multiimage_method'] == 'split') { - foreach ($_FILES as $key => $file) { + foreach ($_FILES as $key => $file) $size += $file['size']; - } } elseif ($config['multiimage_method'] == 'each') { foreach ($_FILES as $key => $file) { - if ($file['size'] > $size) { + if ($file['size'] > $size) $size = $file['size']; - } } - } else { + } else error(_('Unrecognized file size determination method.')); - } if ($size > $config['max_filesize']) error(sprintf3($config['error']['filesize'], array( @@ -643,7 +437,7 @@ if (isset($_POST['delete'])) { $trip = generate_tripcode($post['name']); $post['name'] = $trip[0]; - $post['trip'] = isset($trip[1]) ? $trip[1] : ''; // XX: Dropped posts and tripcodes + $post['trip'] = isset($trip[1]) ? $trip[1] : ''; // XX: Tripcodes $noko = false; if (strtolower($post['email']) == 'noko') { @@ -652,7 +446,8 @@ if (isset($_POST['delete'])) { } elseif (strtolower($post['email']) == 'nonoko'){ $noko = false; $post['email'] = ''; - } else $noko = $config['always_noko']; + } else + $noko = $config['always_noko']; if ($post['has_file']) { $i = 0; @@ -683,20 +478,19 @@ if (isset($_POST['delete'])) { } } - if (empty($post['files'])) $post['has_file'] = false; + if (empty($post['files'])) + $post['has_file'] = false; - if (!$dropped_post) { - // Check for a file - if ($post['op'] && !isset($post['no_longer_require_an_image_for_op'])) { - if (!$post['has_file'] && $config['force_image_op']) - error($config['error']['noimage']); - } - - // Check for too many files - if (sizeof($post['files']) > $config['max_images']) - error($config['error']['toomanyimages']); + // Check for a file + if ($post['op'] && !isset($post['no_longer_require_an_image_for_op'])) { + if (!$post['has_file'] && $config['force_image_op']) + error($config['error']['noimage']); } + // Check for too many files + if (sizeof($post['files']) > $config['max_images']) + error($config['error']['toomanyimages']); + if ($config['strip_combining_chars']) { $post['name'] = strip_combining_chars($post['name']); $post['email'] = strip_combining_chars($post['email']); @@ -704,28 +498,25 @@ if (isset($_POST['delete'])) { $post['body'] = strip_combining_chars($post['body']); } - if (!$dropped_post) { - // Check string lengths - if (mb_strlen($post['name']) > 35) - error(sprintf($config['error']['toolong'], 'name')); - if (mb_strlen($post['email']) > 40) - error(sprintf($config['error']['toolong'], 'email')); - if (mb_strlen($post['subject']) > 100) - error(sprintf($config['error']['toolong'], 'subject')); - if (!$mod && mb_strlen($post['body']) > $config['max_body']) - error($config['error']['toolong_body']); - if (mb_strlen($post['password']) > 20) - error(sprintf($config['error']['toolong'], 'password')); - } + // Check string lengths + if (mb_strlen($post['name']) > 35) + error(sprintf($config['error']['toolong'], 'name')); + if (mb_strlen($post['email']) > 40) + error(sprintf($config['error']['toolong'], 'email')); + if (mb_strlen($post['subject']) > 100) + error(sprintf($config['error']['toolong'], 'subject')); + if (!$mod && mb_strlen($post['body']) > $config['max_body']) + error($config['error']['toolong_body']); + if (mb_strlen($post['password']) > 20) + error(sprintf($config['error']['toolong'], 'password')); + wordfilters($post['body']); $post['body'] = escape_markup_modifiers($post['body']); - if ($mod && isset($post['raw']) && $post['raw']) { + if ($mod && isset($post['raw']) && $post['raw']) $post['body'] .= "\n1"; - } - if (!$dropped_post) if (($config['country_flags'] && !$config['allow_no_country']) || ($config['country_flags'] && $config['allow_no_country'] && !isset($_POST['no_country']))) { $gi=geoip\geoip_open('inc/lib/geoip/GeoIPv6.dat', GEOIP_STANDARD); @@ -748,8 +539,7 @@ if (isset($_POST['delete'])) { } } - if ($config['user_flag'] && isset($_POST['user_flag'])) - if (!empty($_POST['user_flag']) ){ + if ($config['user_flag'] && isset($_POST['user_flag']) && !empty($_POST['user_flag']) ){ $user_flag = $_POST['user_flag']; @@ -766,8 +556,7 @@ if (isset($_POST['delete'])) { $post['body'] .= "\n" . $_POST['tag'] . ""; } - if (!$dropped_post) - if ($config['proxy_save'] && isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { + if ($config['proxy_save'] && isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $proxy = preg_replace("/[^0-9a-fA-F.,: ]/", '', $_SERVER['HTTP_X_FORWARDED_FOR']); $post['body'] .= "\n".$proxy.""; } @@ -839,7 +628,7 @@ if (isset($_POST['delete'])) { } } - if (!hasPermission($config['mod']['bypass_filters'], $board['uri']) && !$dropped_post) { + if (!hasPermission($config['mod']['bypass_filters'], $board['uri'])) { require_once 'inc/filters.php'; do_filters($post); @@ -1042,17 +831,16 @@ if (isset($_POST['delete'])) { } // Do filters again if OCRing - if ($config['tesseract_ocr'] && !hasPermission($config['mod']['bypass_filters'], $board['uri']) && !$dropped_post) { + if ($config['tesseract_ocr'] && !hasPermission($config['mod']['bypass_filters'], $board['uri'])) do_filters($post); - } - if (!hasPermission($config['mod']['postunoriginal'], $board['uri']) && $config['robot_enable'] && checkRobot($post['body_nomarkup']) && !$dropped_post) { + if (!hasPermission($config['mod']['postunoriginal'], $board['uri']) && $config['robot_enable'] && checkRobot($post['body_nomarkup'])) { undoImage($post); - if ($config['robot_mute']) { + + if ($config['robot_mute']) error(sprintf($config['error']['muted'], mute())); - } else { + else error($config['error']['unoriginal']); - } } // Remove board directories before inserting them into the database. @@ -1085,42 +873,6 @@ if (isset($_POST['delete'])) { $post['id'] = $id = post($post); $post['slug'] = slugify($post); - - if ($dropped_post && $dropped_post['from_nntp']) { - $query = prepare("INSERT INTO ``nntp_references`` (`board`, `id`, `message_id`, `message_id_digest`, `own`, `headers`) VALUES ". - "(:board , :id , :message_id , :message_id_digest , false, :headers)"); - - $query->bindValue(':board', $dropped_post['board']); - $query->bindValue(':id', $id); - $query->bindValue(':message_id', $dropped_post['msgid']); - $query->bindValue(':message_id_digest', sha1($dropped_post['msgid'])); - $query->bindValue(':headers', $dropped_post['headers']); - $query->execute() or error(db_error($query)); - } // ^^^^^ For inbound posts ^^^^^ - elseif ($config['nntpchan']['enabled'] && $config['nntpchan']['group']) { - // vvvvv For outbound posts vvvvv - - require_once('inc/nntpchan/nntpchan.php'); - $msgid = gen_msgid($post['board'], $post['id']); - - list($headers, $files) = post2nntp($post, $msgid); - - $message = gen_nntp($headers, $files); - - $query = prepare("INSERT INTO ``nntp_references`` (`board`, `id`, `message_id`, `message_id_digest`, `own`, `headers`) VALUES ". - "(:board , :id , :message_id , :message_id_digest , true , :headers)"); - - $query->bindValue(':board', $post['board']); - $query->bindValue(':id', $post['id']); - $query->bindValue(':message_id', $msgid); - $query->bindValue(':message_id_digest', sha1($msgid)); - $query->bindValue(':headers', json_encode($headers)); - $query->execute() or error(db_error($query)); - - // Let's broadcast it! - nntp_publish($message, $msgid); - } - insertFloodPost($post); // Handle cyclical threads diff --git a/smart_build.php b/smart_build.php deleted file mode 100644 index cfac446a..00000000 --- a/smart_build.php +++ /dev/null @@ -1,86 +0,0 @@ -404 Not Found

Page doesn't exist


vichan
"; - } - else { - header("Location: ".$config['page_404']); - } - header("X-Accel-Expires: 120"); - die(); -} - -if ($reached) { - if ($request[strlen($request)-1] == '/') { - $request .= 'index.html'; - } - $request = '.'.$request; - - if (!file_exists($request)) { - die_404(); - } - - header("HTTP/1.1 200 OK"); - header("Status: 200 OK"); - if (preg_match('/\.json$/', $request)) { - header("Content-Type", "application/json"); - } - elseif (preg_match('/\.js$/', $request)) { - header("Content-Type", "text/javascript; charset=utf-8"); - } - elseif (preg_match('/\.xml$/', $request)) { - header("Content-Type", "application/xml"); - } - elseif (preg_match('/\.rss$/', $request)) { - header("Content-Type", "application/rss+xml"); - } - else { - header("Content-Type", "text/html; charset=utf-8"); - } - header("Cache-Control: public, nocache, no-cache, max-age=0, must-revalidate"); - header("Expires: Fri, 22 Feb 1991 06:00:00 GMT"); - header("Last-Modified: ".date('r', filemtime($request))); - - //if (isset ($_SERVER['HTTP_ACCEPT_ENCODING']) && preg_match('/gzip/', $_SERVER['HTTP_ACCEPT_ENCODING']) && file_exists($request.".gz")) { - // header("Content-Encoding: gzip"); - // $file = fopen($request.".gz", 'r'); - //} - //else { - $file = fopen($request, 'r'); - //} - fpassthru($file); - fclose($file); -} -else { - die_404(); -} diff --git a/templates/post_form.html b/templates/post_form.html index 6facf749..316c2dcf 100644 --- a/templates/post_form.html +++ b/templates/post_form.html @@ -79,27 +79,6 @@ {% endif %} - {% if config.captcha.enabled %} - - - {% trans %}Verification{% endtrans %} - - - - - - {% elseif config.new_thread_capt %} - {% if not id %} - - - {% trans %}Verification{% endtrans %} - - - - - - {% endif %} - {% endif %} {% if config.user_flag %} {% trans %}Flag{% endtrans %} diff --git a/templates/themes/awsumchan/theme.php b/templates/themes/awsumchan/theme.php index 337aca22..c361b443 100644 --- a/templates/themes/awsumchan/theme.php +++ b/templates/themes/awsumchan/theme.php @@ -18,21 +18,13 @@ public function build($action, $settings) { global $config, $_theme; - if ($action == 'all') { + if ($action == 'all') copy('templates/themes/awsumchan/' . $settings['basecss'], $config['dir']['home'] . $settings['css']); - } $this->excluded = explode(' ', $settings['exclude']); - if ($action == 'all' || $action == 'news' || $action == 'post' || $action == 'post-thread' || $action == 'post-delete') { - $action = generation_strategy('sb_recent', []); - if ($action == 'delete') { - file_unlink($config['dir']['home'] . $settings['html']); - } - elseif ($action == 'rebuild') { - file_write($config['dir']['home'] . $settings['html'], $this->homepage($settings)); - } - } + if ($action == 'all' || $action == 'news' || $action == 'post' || $action == 'post-thread' || $action == 'post-delete') + file_write($config['dir']['home'] . $settings['html'], $this->homepage($settings)); } // Build news page diff --git a/templates/themes/catalog/theme.php b/templates/themes/catalog/theme.php index 77bcfeca..cff31cf5 100644 --- a/templates/themes/catalog/theme.php +++ b/templates/themes/catalog/theme.php @@ -15,28 +15,14 @@ if ($action == 'all') { foreach ($boards as $board) { - $b = new Catalog(); - - $action = generation_strategy("sb_catalog", array($board)); - if ($action == 'delete') { - file_unlink($config['dir']['home'] . $board . '/catalog.html'); - file_unlink($config['dir']['home'] . $board . '/index.rss'); - } - elseif ($action == 'rebuild') { + if (in_array($board, $boards)) { + $b = new Catalog(); $b->build($settings, $board); } } } elseif ($action == 'post-thread' || ($settings['update_on_posts'] && $action == 'post') || ($settings['update_on_posts'] && $action == 'post-delete') && in_array($board, $boards)) { $b = new Catalog(); - - $action = generation_strategy("sb_catalog", array($board)); - if ($action == 'delete') { - file_unlink($config['dir']['home'] . $board . '/catalog.html'); - file_unlink($config['dir']['home'] . $board . '/index.rss'); - } - elseif ($action == 'rebuild') { - $b->build($settings, $board); - } + $b->build($settings, $board); } } diff --git a/templates/themes/recent/theme.php b/templates/themes/recent/theme.php index 367f6a7a..81426b0d 100644 --- a/templates/themes/recent/theme.php +++ b/templates/themes/recent/theme.php @@ -18,21 +18,13 @@ public function build($action, $settings) { global $config, $_theme; - if ($action == 'all') { + if ($action == 'all') copy('templates/themes/recent/' . $settings['basecss'], $config['dir']['home'] . $settings['css']); - } $this->excluded = explode(' ', $settings['exclude']); - if ($action == 'all' || $action == 'post' || $action == 'post-thread' || $action == 'post-delete') { - $action = generation_strategy('sb_recent', array()); - if ($action == 'delete') { - file_unlink($config['dir']['home'] . $settings['html']); - } - elseif ($action == 'rebuild') { + if ($action == 'all' || $action == 'post' || $action == 'post-thread' || $action == 'post-delete') file_write($config['dir']['home'] . $settings['html'], $this->homepage($settings)); - } - } } // Build news page diff --git a/templates/themes/sitemap/theme.php b/templates/themes/sitemap/theme.php index 6bc035bb..86e2cde7 100644 --- a/templates/themes/sitemap/theme.php +++ b/templates/themes/sitemap/theme.php @@ -23,26 +23,19 @@ } } - $action = generation_strategy('sb_sitemap', array()); - - if ($action == 'delete') { - file_unlink($settings['path']); - } - elseif ($action == 'rebuild') { - $boards = explode(' ', $settings['boards']); - - $threads = array(); - - foreach ($boards as $board) { - $query = query(sprintf("SELECT `id`, `id` AS `thread_id`, `slug`, (SELECT `time` FROM ``posts_%s`` WHERE `thread` = `thread_id` OR `id` = `thread_id` ORDER BY `time` DESC LIMIT 1) AS `lastmod` FROM ``posts_%s`` WHERE `thread` IS NULL", $board, $board)) or error(db_error()); - $threads[$board] = $query->fetchAll(PDO::FETCH_ASSOC); - } - - file_write($settings['path'], Element('themes/sitemap/sitemap.xml', Array( - 'settings' => $settings, - 'config' => $config, - 'threads' => $threads, - 'boards' => $boards, - ))); + $boards = explode(' ', $settings['boards']); + + $threads = array(); + + foreach ($boards as $board) { + $query = query(sprintf("SELECT `id`, `id` AS `thread_id`, `slug`, (SELECT `time` FROM ``posts_%s`` WHERE `thread` = `thread_id` OR `id` = `thread_id` ORDER BY `time` DESC LIMIT 1) AS `lastmod` FROM ``posts_%s`` WHERE `thread` IS NULL", $board, $board)) or error(db_error()); + $threads[$board] = $query->fetchAll(PDO::FETCH_ASSOC); } + + file_write($settings['path'], Element('themes/sitemap/sitemap.xml', Array( + 'settings' => $settings, + 'config' => $config, + 'threads' => $threads, + 'boards' => $boards, + ))); } diff --git a/templates/themes/ukko/theme.php b/templates/themes/ukko/theme.php index 56a6da4a..5c431091 100644 --- a/templates/themes/ukko/theme.php +++ b/templates/themes/ukko/theme.php @@ -11,14 +11,7 @@ return; } - $action = generation_strategy('sb_ukko', array()); - - if ($action == 'delete') { - file_unlink($settings['uri'] . '/index.html'); - } - elseif ($action == 'rebuild') { - file_write($settings['uri'] . '/index.html', $ukko->build()); - } + file_write($settings['uri'] . '/index.html', $ukko->build()); } class ukko { diff --git a/tmp/locks/.gitkeep b/tmp/locks/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/tmp/queue/generate/.gitkeep b/tmp/queue/generate/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/tools/worker.php b/tools/worker.php deleted file mode 100755 index e19fe1c6..00000000 --- a/tools/worker.php +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/php -pop(2); - foreach ($q as $v) { - list($__, $func, $ary, $action) = unserialize($v); - echo "Starting to generate $func ".implode(" ", $ary)."... "; - - call_user_func_array($func, $ary); - - echo "done!\n"; - } - if (!$q) usleep(20000); // 0.02s -}