From b9938d9513ccbfc4bf1cb0731d4e9e979fcf02d7 Mon Sep 17 00:00:00 2001 From: Zankaria Date: Wed, 23 Apr 2025 22:01:49 +0200 Subject: [PATCH 1/3] post.php: remove nttpchan --- post.php | 552 +++++++++++++++++-------------------------------------- 1 file changed, 166 insertions(+), 386 deletions(-) diff --git a/post.php b/post.php index e6afe5b6..37af514f 100644 --- a/post.php +++ b/post.php @@ -353,166 +353,6 @@ function db_select_ban_appeals($ban_id) * Method handling functions */ -$dropped_post = false; - -function handle_nntpchan(Context $ctx) -{ - global $config; - if ($_SERVER['REMOTE_ADDR'] != $config['nntpchan']['trusted_peer']) { - error("NNTPChan: Forbidden. $_SERVER[REMOTE_ADDR] is not a trusted peer"); - } - - $_POST = []; - $_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') { - $ctx->get(LogDriver::class)->log(LogDriver::DEBUG, 'MM: Files: ' . print_r($GLOBALS, true)); - - $content = ''; - - $newfiles = []; - 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 = []; - $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 = []; - 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, - ); -} - function handle_delete(Context $ctx) { // Delete @@ -789,9 +629,9 @@ function handle_report(Context $ctx) function handle_post(Context $ctx) { - global $config, $dropped_post, $board, $mod, $pdo; + global $config, $board, $mod, $pdo; - if (!isset($_POST['body'], $_POST['board']) && !$dropped_post) { + if (!isset($_POST['body'], $_POST['board'])) { error($config['error']['bot']); } @@ -834,108 +674,104 @@ function handle_post(Context $ctx) } - if (!$dropped_post) { - // Check for CAPTCHA right after opening the board so the "return" link is in there. - if ($config['captcha']['mode'] !== false) { - if (!isset($_POST['captcha-response'], $_POST['captcha-form-id'])) { - error($config['error']['bot']); - } - - $expected_action = $post['op'] ? 'post-thread' : 'post-reply'; - $ret = check_captcha($config['captcha'], $_POST['captcha-form-id'], $post['board'], $_POST['captcha-response'], $_SERVER['REMOTE_ADDR'], $expected_action); - if (!$ret) { - error($config['error']['captcha']); - } - } - - if (isset($config['simple_spam']) && $post['op']) { - if (!isset($_POST['simple_spam']) || $config['simple_spam']['answer'] != $_POST['simple_spam']) { - error($config['error']['simple_spam']); - } - } - - if (isset($config['securimage']) && $config['securimage']) { - if (!isset($_POST['captcha'])) { - error($config['error']['securimage']['missing']); - } - - if (empty($_POST['captcha'])) { - error($config['error']['securimage']['empty']); - } - - if (!db_delete_captcha($_SERVER['REMOTE_ADDR'], $_POST['captcha'])) { - error($config['error']['securimage']['bad']); - } - } - - if ( - !(($post['op'] && $_POST['post'] == $config['button_newtopic']) || - (!$post['op'] && $_POST['post'] == $config['button_reply'])) - ) { + // Check for CAPTCHA right after opening the board so the "return" link is in there. + if ($config['captcha']['mode'] !== false) { + if (!isset($_POST['captcha-response'], $_POST['captcha-form-id'])) { 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']); + $expected_action = $post['op'] ? 'post-thread' : 'post-reply'; + $ret = check_captcha($config['captcha'], $_POST['captcha-form-id'], $post['board'], $_POST['captcha-response'], $_SERVER['REMOTE_ADDR'], $expected_action); + if (!$ret) { + error($config['error']['captcha']); + } + } + + if (isset($config['simple_spam']) && $post['op']) { + if (!isset($_POST['simple_spam']) || $config['simple_spam']['answer'] != $_POST['simple_spam']) { + error($config['error']['simple_spam']); + } + } + + if (isset($config['securimage']) && $config['securimage']) { + if (!isset($_POST['captcha'])) { + error($config['error']['securimage']['missing']); } - checkDNSBL(); - - // Check if banned - checkBan($board['uri']); - - if ($config['op_require_history'] && $post['op'] && !isIPv6()) { - $has_any = has_any_history($_SERVER['REMOTE_ADDR'], $_POST['password']); - if (!$has_any) { - error($config['error']['opnohistory']); - } + if (empty($_POST['captcha'])) { + error($config['error']['securimage']['empty']); } - if ($post['mod'] = isset($_POST['mod']) && $_POST['mod']) { - check_login($ctx, false); - if (!$mod) { - // Liar. You're not a mod >:-[ - error($config['error']['notamod']); - } + if (!db_delete_captcha($_SERVER['REMOTE_ADDR'], $_POST['captcha'])) { + error($config['error']['securimage']['bad']); + } + } - $post['sticky'] = $post['op'] && isset($_POST['sticky']); - $post['locked'] = $post['op'] && isset($_POST['lock']); - $post['raw'] = isset($_POST['raw']); + if ( + !(($post['op'] && $_POST['post'] == $config['button_newtopic']) || + (!$post['op'] && $_POST['post'] == $config['button_reply'])) + ) { + error($config['error']['bot']); + } - 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']); - } + // 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(); + + // Check if banned + checkBan($board['uri']); + + if ($config['op_require_history'] && $post['op'] && !isIPv6()) { + $has_any = has_any_history($_SERVER['REMOTE_ADDR'], $_POST['password']); + if (!$has_any) { + error($config['error']['opnohistory']); + } + } + + if ($post['mod'] = isset($_POST['mod']) && $_POST['mod']) { + check_login($ctx, false); + if (!$mod) { + // Liar. You're not a mod >:-[ + error($config['error']['notamod']); } - if (!$post['mod'] && $config['spam']['enabled'] == true) { - $post['antispam_hash'] = checkSpam( - array( - $board['uri'], - isset($post['thread']) ? $post['thread'] : ($config['try_smarter'] && isset($_POST['page']) ? 0 - (int) $_POST['page'] : null) - ) - ); - //$post['antispam_hash'] = checkSpam(); + $post['sticky'] = $post['op'] && isset($_POST['sticky']); + $post['locked'] = $post['op'] && isset($_POST['lock']); + $post['raw'] = isset($_POST['raw']); - if ($post['antispam_hash'] === true) { - error($config['error']['spam']); - } + 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 ($config['robot_enable'] && $config['robot_mute']) { - checkMute(); + if (!$post['mod'] && $config['spam']['enabled'] == true) { + $post['antispam_hash'] = checkSpam( + array( + $board['uri'], + isset($post['thread']) ? $post['thread'] : ($config['try_smarter'] && isset($_POST['page']) ? 0 - (int) $_POST['page'] : null) + ) + ); + //$post['antispam_hash'] = checkSpam(); + + if ($post['antispam_hash'] === true) { + error($config['error']['spam']); } - } else { - $mod = $post['mod'] = false; + } + + if ($config['robot_enable'] && $config['robot_mute']) { + checkMute(); } // Check if thread exists. @@ -1021,40 +857,35 @@ function handle_post(Context $ctx) $post['password'] = hashPassword($_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']); - - $replythreshold = isset($thread['cycle']) && $thread['cycle'] ? $numposts['replies'] - 1 : $numposts['replies']; - $imagethreshold = isset($thread['cycle']) && $thread['cycle'] ? $numposts['images'] - 1 : $numposts['images']; - - if ($config['reply_hard_limit'] != 0 && $config['reply_hard_limit'] <= $replythreshold) { - error($config['error']['reply_hard_limit']); - } - - if ($post['has_file'] && $config['image_hard_limit'] != 0 && $config['image_hard_limit'] <= $imagethreshold) { - error($config['error']['image_hard_limit']); - } - } - } else { - if (!$post['op']) { - $numposts = numPosts($post['thread']); + 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']); + + $replythreshold = isset($thread['cycle']) && $thread['cycle'] ? $numposts['replies'] - 1 : $numposts['replies']; + $imagethreshold = isset($thread['cycle']) && $thread['cycle'] ? $numposts['images'] - 1 : $numposts['images']; + + if ($config['reply_hard_limit'] != 0 && $config['reply_hard_limit'] <= $replythreshold) { + error($config['error']['reply_hard_limit']); + } + + if ($post['has_file'] && $config['image_hard_limit'] != 0 && $config['image_hard_limit'] <= $imagethreshold) { + error($config['error']['image_hard_limit']); + } + } + + if ($post['has_file']) { // Determine size sanity $size = 0; @@ -1160,18 +991,16 @@ function handle_post(Context $ctx) $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 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 too many files + if (sizeof($post['files']) > $config['max_images']) { + error($config['error']['toomanyimages']); } if ($config['strip_combining_chars']) { @@ -1181,33 +1010,31 @@ function handle_post(Context $ctx) $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) { - $body_mb_len = mb_strlen($post['body']); - $is_op = $post['op']; + // 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) { + $body_mb_len = mb_strlen($post['body']); + $is_op = $post['op']; - if (($is_op && $config['force_body_op']) || (!$is_op && $config['force_body'])) { - $min_body = $is_op ? $config['min_body_op'] : $config['min_body']; + if (($is_op && $config['force_body_op']) || (!$is_op && $config['force_body'])) { + $min_body = $is_op ? $config['min_body_op'] : $config['min_body']; - if ($body_mb_len < $min_body) { - error($config['error']['tooshort_body']); - } + if ($body_mb_len < $min_body) { + error($config['error']['tooshort_body']); } + } - $max_body = $is_op ? $config['max_body_op'] : $config['max_body']; - if ($body_mb_len > $max_body) { - error($config['error']['toolong_body']); - } + $max_body = $is_op ? $config['max_body_op'] : $config['max_body']; + if ($body_mb_len > $max_body) { + error($config['error']['toolong_body']); } } @@ -1219,33 +1046,32 @@ function handle_post(Context $ctx) $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_open('inc/lib/geoip/GeoIPv6.dat', GEOIP_STANDARD); + if (($config['country_flags'] && !$config['allow_no_country']) || ($config['country_flags'] && $config['allow_no_country'] && !isset($_POST['no_country']))) { + $gi = geoip_open('inc/lib/geoip/GeoIPv6.dat', GEOIP_STANDARD); - function ipv4to6($ip) - { - if (strpos($ip, ':') !== false) { - if (strpos($ip, '.') > 0) { - $ip = substr($ip, strrpos($ip, ':') + 1); - } else { - // Native ipv6. - return $ip; - } + function ipv4to6($ip) + { + if (strpos($ip, ':') !== false) { + if (strpos($ip, '.') > 0) { + $ip = substr($ip, strrpos($ip, ':') + 1); + } else { + // Native ipv6. + return $ip; } - $iparr = array_pad(explode('.', $ip), 4, 0); - $part7 = base_convert(($iparr[0] * 256) + $iparr[1], 10, 16); - $part8 = base_convert(($iparr[2] * 256) + $iparr[3], 10, 16); - return '::ffff:' . $part7 . ':' . $part8; } + $iparr = array_pad(explode('.', $ip), 4, 0); + $part7 = base_convert(($iparr[0] * 256) + $iparr[1], 10, 16); + $part8 = base_convert(($iparr[2] * 256) + $iparr[3], 10, 16); + return '::ffff:' . $part7 . ':' . $part8; + } - if ($country_code = geoip_country_code_by_addr_v6($gi, ipv4to6($_SERVER['REMOTE_ADDR']))) { - if (!in_array(strtolower($country_code), array('eu', 'ap', 'o1', 'a1', 'a2'))) { - $post['body'] .= "\n" . strtolower($country_code) . "" . - "\n" . geoip_country_name_by_addr_v6($gi, ipv4to6($_SERVER['REMOTE_ADDR'])) . ""; - } + if ($country_code = geoip_country_code_by_addr_v6($gi, ipv4to6($_SERVER['REMOTE_ADDR']))) { + if (!in_array(strtolower($country_code), array('eu', 'ap', 'o1', 'a1', 'a2'))) { + $post['body'] .= "\n" . strtolower($country_code) . "" . + "\n" . geoip_country_name_by_addr_v6($gi, ipv4to6($_SERVER['REMOTE_ADDR'])) . ""; } } + } if ($config['user_flag'] && isset($_POST['user_flag'])) if (!empty($_POST['user_flag'])) { @@ -1265,11 +1091,9 @@ function handle_post(Context $ctx) $post['body'] .= "\n" . $_POST['tag'] . ""; } - if (!$dropped_post) { - 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 . ""; - } + 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 . ""; } $post['body_nomarkup'] = $post['body']; @@ -1311,7 +1135,7 @@ function handle_post(Context $ctx) } } - 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($ctx, $post); } @@ -1616,7 +1440,7 @@ function handle_post(Context $ctx) } } - 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']) { error(sprintf($config['error']['muted'], mute())); @@ -1662,41 +1486,6 @@ function handle_post(Context $ctx) $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 @@ -1863,20 +1652,11 @@ function handle_appeal(Context $ctx) $ctx = Vichan\build_context($config); -// Is it a post coming from NNTP? Let's extract it and pretend it's a normal post. -if (isset($_GET['Newsgroups'])) { - if ($config['nntpchan']['enabled']) { - handle_nntpchan($ctx); - } else { - error("NNTPChan: NNTPChan support is disabled"); - } -} - if (isset($_POST['delete'])) { handle_delete($ctx); } elseif (isset($_POST['report'])) { handle_report($ctx); -} elseif (isset($_POST['post']) || $dropped_post) { +} elseif (isset($_POST['post'])) { handle_post($ctx); } elseif (isset($_POST['appeal'])) { handle_appeal($ctx); From 634f76959221a648bb412b80596673fa904c22da Mon Sep 17 00:00:00 2001 From: Zankaria Date: Wed, 23 Apr 2025 22:02:57 +0200 Subject: [PATCH 2/3] config.php: remove nntpchan options --- inc/config.php | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/inc/config.php b/inc/config.php index 55580cec..8e1f337c 100644 --- a/inc/config.php +++ b/inc/config.php @@ -1896,45 +1896,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 From 24e43a5aa14e78ff47b3d1dcbba4d9f82abf33c8 Mon Sep 17 00:00:00 2001 From: Zankaria Date: Wed, 23 Apr 2025 22:03:32 +0200 Subject: [PATCH 3/3] nntpchan: removed handler code --- inc/nntpchan/nntpchan.php | 152 -------------------------------------- inc/nntpchan/tests.php | 30 -------- 2 files changed, 182 deletions(-) delete mode 100644 inc/nntpchan/nntpchan.php delete mode 100644 inc/nntpchan/tests.php 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>"); -