mirror of
https://github.com/vichan-devel/vichan.git
synced 2025-01-09 21:11:44 +01:00
Merge pull request #858 from vichan-devel/removecurrentantibot
Remove current antibot system
This commit is contained in:
commit
b2ca26dba5
196
inc/anti-bot.php
196
inc/anti-bot.php
@ -1,199 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010-2013 Tinyboard Development Group
|
* Anti-bot.php has been deprecated and removed due to its functions not being necessary and being easily bypassable, by both customized and uncustomized spambots.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
defined('TINYBOARD') or exit;
|
|
||||||
|
|
||||||
class AntiBot {
|
|
||||||
public $salt;
|
|
||||||
public $inputs = [];
|
|
||||||
public $index = 0;
|
|
||||||
|
|
||||||
public static function randomString($length, $uppercase = false, $special_chars = false, $unicode_chars = false) {
|
|
||||||
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
|
||||||
if ($uppercase) {
|
|
||||||
$chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
||||||
}
|
|
||||||
if ($special_chars) {
|
|
||||||
$chars .= ' ~!@#$%^&*()_+,./;\'[]\\{}|:<>?=-` ';
|
|
||||||
}
|
|
||||||
if ($unicode_chars) {
|
|
||||||
$len = strlen($chars) / 10;
|
|
||||||
for ($n = 0; $n < $len; $n++) {
|
|
||||||
$chars .= mb_convert_encoding('&#' . mt_rand(0x2600, 0x26FF) . ';', 'UTF-8', 'HTML-ENTITIES');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$chars = preg_split('//u', $chars, -1, PREG_SPLIT_NO_EMPTY);
|
|
||||||
|
|
||||||
$ch = [];
|
|
||||||
|
|
||||||
// fill up $ch until we reach $length
|
|
||||||
while (count($ch) < $length) {
|
|
||||||
$n = $length - count($ch);
|
|
||||||
$keys = array_rand($chars, $n > count($chars) ? count($chars) : $n);
|
|
||||||
if ($n == 1) {
|
|
||||||
$ch[] = $chars[$keys];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
shuffle($keys);
|
|
||||||
foreach ($keys as $key) {
|
|
||||||
$ch[] = $chars[$key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$chars = $ch;
|
|
||||||
|
|
||||||
return implode('', $chars);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function make_confusing($string) {
|
|
||||||
$chars = preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY);
|
|
||||||
|
|
||||||
foreach ($chars as &$c) {
|
|
||||||
if (mt_rand(0, 3) != 0) {
|
|
||||||
$c = utf8tohtml($c);
|
|
||||||
} else {
|
|
||||||
$c = mb_encode_numericentity($c, [ 0, 0xffff, 0, 0xffff ], 'UTF-8');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return implode('', $chars);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __construct(array $salt = []) {
|
|
||||||
global $config;
|
|
||||||
|
|
||||||
if (!empty($salt)) {
|
|
||||||
// Create a salted hash of the "extra salt"
|
|
||||||
$this->salt = implode(':', $salt);
|
|
||||||
} else {
|
|
||||||
$this->salt = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
shuffle($config['spam']['hidden_input_names']);
|
|
||||||
|
|
||||||
$input_count = mt_rand($config['spam']['hidden_inputs_min'], $config['spam']['hidden_inputs_max']);
|
|
||||||
$hidden_input_names_x = 0;
|
|
||||||
|
|
||||||
for ($x = 0; $x < $input_count ; $x++) {
|
|
||||||
if ($hidden_input_names_x === false || mt_rand(0, 2) == 0) {
|
|
||||||
// Use an obscure name
|
|
||||||
$name = $this->randomString(mt_rand(10, 40), false, false, $config['spam']['unicode']);
|
|
||||||
} else {
|
|
||||||
// Use a pre-defined confusing name
|
|
||||||
$name = $config['spam']['hidden_input_names'][$hidden_input_names_x++];
|
|
||||||
if ($hidden_input_names_x >= count($config['spam']['hidden_input_names'])) {
|
|
||||||
$hidden_input_names_x = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mt_rand(0, 2) == 0) {
|
|
||||||
// Value must be null
|
|
||||||
$this->inputs[$name] = '';
|
|
||||||
} elseif (mt_rand(0, 4) == 0) {
|
|
||||||
// Numeric value
|
|
||||||
$this->inputs[$name] = (string)mt_rand(0, 100000);
|
|
||||||
} else {
|
|
||||||
// Obscure value
|
|
||||||
$this->inputs[$name] = $this->randomString(mt_rand(5, 100), true, true, $config['spam']['unicode']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function space() {
|
|
||||||
if (mt_rand(0, 3) != 0) {
|
|
||||||
return ' ';
|
|
||||||
}
|
|
||||||
return str_repeat(' ', mt_rand(1, 3));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function html($count = false) {
|
|
||||||
$elements = [
|
|
||||||
'<input type="hidden" name="%name%" value="%value%">',
|
|
||||||
'<input type="hidden" value="%value%" name="%name%">',
|
|
||||||
'<input name="%name%" value="%value%" type="hidden">',
|
|
||||||
'<input value="%value%" name="%name%" type="hidden">',
|
|
||||||
'<input style="display:none" type="text" name="%name%" value="%value%">',
|
|
||||||
'<input style="display:none" type="text" value="%value%" name="%name%">',
|
|
||||||
'<span style="display:none"><input type="text" name="%name%" value="%value%"></span>',
|
|
||||||
'<div style="display:none"><input type="text" name="%name%" value="%value%"></div>',
|
|
||||||
'<div style="display:none"><input type="text" name="%name%" value="%value%"></div>',
|
|
||||||
'<textarea style="display:none" name="%name%">%value%</textarea>',
|
|
||||||
'<textarea name="%name%" style="display:none">%value%</textarea>'
|
|
||||||
];
|
|
||||||
|
|
||||||
$html = '';
|
|
||||||
|
|
||||||
if ($count === false) {
|
|
||||||
$count = mt_rand(1, (int)abs(count($this->inputs) / 15) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($count === true) {
|
|
||||||
// All elements
|
|
||||||
$inputs = array_slice($this->inputs, $this->index);
|
|
||||||
} else {
|
|
||||||
$inputs = array_slice($this->inputs, $this->index, $count);
|
|
||||||
}
|
|
||||||
$this->index += count($inputs);
|
|
||||||
|
|
||||||
foreach ($inputs as $name => $value) {
|
|
||||||
$element = false;
|
|
||||||
while (!$element) {
|
|
||||||
$element = $elements[array_rand($elements)];
|
|
||||||
$element = str_replace(' ', self::space(), $element);
|
|
||||||
if (mt_rand(0, 5) == 0) {
|
|
||||||
$element = str_replace('>', self::space() . '>', $element);
|
|
||||||
}
|
|
||||||
if (strpos($element, 'textarea') !== false && $value == '') {
|
|
||||||
// There have been some issues with mobile web browsers and empty <textarea>'s.
|
|
||||||
$element = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$element = str_replace('%name%', utf8tohtml($name), $element);
|
|
||||||
|
|
||||||
if (mt_rand(0, 2) == 0) {
|
|
||||||
$value = $this->make_confusing($value);
|
|
||||||
} else {
|
|
||||||
$value = utf8tohtml($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strpos($element, 'textarea') === false) {
|
|
||||||
$value = str_replace('"', '"', $value);
|
|
||||||
}
|
|
||||||
|
|
||||||
$element = str_replace('%value%', $value, $element);
|
|
||||||
|
|
||||||
$html .= $element;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $html;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function reset() {
|
|
||||||
$this->index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function hash() {
|
|
||||||
global $config;
|
|
||||||
|
|
||||||
// This is the tricky part: create a hash to validate it after
|
|
||||||
// First, sort the keys in alphabetical order (A-Z)
|
|
||||||
$inputs = $this->inputs;
|
|
||||||
ksort($inputs);
|
|
||||||
|
|
||||||
$hash = '';
|
|
||||||
// Iterate through each input
|
|
||||||
foreach ($inputs as $name => $value) {
|
|
||||||
$hash .= $name . '=' . $value;
|
|
||||||
}
|
|
||||||
// Add a salt to the hash
|
|
||||||
$hash .= $config['cookies']['salt'];
|
|
||||||
|
|
||||||
// Use SHA1 for the hash
|
|
||||||
return sha1($hash . $this->salt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -275,83 +275,6 @@
|
|||||||
// To prevent bump attacks; returns the thread to last position after the last post is deleted.
|
// To prevent bump attacks; returns the thread to last position after the last post is deleted.
|
||||||
$config['anti_bump_flood'] = false;
|
$config['anti_bump_flood'] = false;
|
||||||
|
|
||||||
/*
|
|
||||||
* Introduction to vichan's spam filter:
|
|
||||||
*
|
|
||||||
* In simple terms, whenever a posting form on a page is generated (which happens whenever a
|
|
||||||
* post is made), vichan will add a random amount of hidden, obscure fields to it to
|
|
||||||
* confuse bots and upset hackers. These fields and their respective obscure values are
|
|
||||||
* validated upon posting with a 160-bit "hash". That hash can only be used as many times
|
|
||||||
* as you specify; otherwise, flooding bots could just keep reusing the same hash.
|
|
||||||
* Once a new set of inputs (and the hash) are generated, old hashes for the same thread
|
|
||||||
* and board are set to expire. Because you have to reload the page to get the new set
|
|
||||||
* of inputs and hash, if they expire too quickly and more than one person is viewing the
|
|
||||||
* page at a given time, vichan would return false positives (depending on how long the
|
|
||||||
* user sits on the page before posting). If your imageboard is quite fast/popular, set
|
|
||||||
* $config['spam']['hidden_inputs_max_pass'] and $config['spam']['hidden_inputs_expire'] to
|
|
||||||
* something higher to avoid false positives.
|
|
||||||
*
|
|
||||||
* See also: https://github.com/vichan-devel/vichan/wiki/your_request_looks_automated
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Number of hidden fields to generate.
|
|
||||||
$config['spam']['hidden_inputs_min'] = 4;
|
|
||||||
$config['spam']['hidden_inputs_max'] = 12;
|
|
||||||
|
|
||||||
// How many times can a "hash" be used to post?
|
|
||||||
$config['spam']['hidden_inputs_max_pass'] = 12;
|
|
||||||
|
|
||||||
// How soon after regeneration do hashes expire (in seconds)?
|
|
||||||
$config['spam']['hidden_inputs_expire'] = 60 * 60 * 3; // three hours
|
|
||||||
|
|
||||||
// Whether to use Unicode characters in hidden input names and values.
|
|
||||||
$config['spam']['unicode'] = true;
|
|
||||||
|
|
||||||
// These are fields used to confuse the bots. Make sure they aren't actually used by vichan, or it won't work.
|
|
||||||
$config['spam']['hidden_input_names'] = array(
|
|
||||||
'user',
|
|
||||||
'username',
|
|
||||||
'login',
|
|
||||||
'search',
|
|
||||||
'q',
|
|
||||||
'url',
|
|
||||||
'firstname',
|
|
||||||
'lastname',
|
|
||||||
'text',
|
|
||||||
'message'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Always update this when adding new valid fields to the post form, or EVERYTHING WILL BE DETECTED AS SPAM!
|
|
||||||
$config['spam']['valid_inputs'] = array(
|
|
||||||
'hash',
|
|
||||||
'board',
|
|
||||||
'thread',
|
|
||||||
'mod',
|
|
||||||
'name',
|
|
||||||
'email',
|
|
||||||
'subject',
|
|
||||||
'post',
|
|
||||||
'body',
|
|
||||||
'password',
|
|
||||||
'sticky',
|
|
||||||
'lock',
|
|
||||||
'raw',
|
|
||||||
'embed',
|
|
||||||
'g-recaptcha-response',
|
|
||||||
'h-captcha-response',
|
|
||||||
'captcha_cookie',
|
|
||||||
'captcha_text',
|
|
||||||
'spoiler',
|
|
||||||
'page',
|
|
||||||
'file_url',
|
|
||||||
'json_response',
|
|
||||||
'user_flag',
|
|
||||||
'no_country',
|
|
||||||
'tag',
|
|
||||||
'simple_spam'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Enable simple anti-spam measure. Requires the end-user to answer a question before making a post.
|
// Enable simple anti-spam measure. Requires the end-user to answer a question before making a post.
|
||||||
// Works very well against uncustomized spam. Answers are case-insensitive.
|
// Works very well against uncustomized spam. Answers are case-insensitive.
|
||||||
// $config['simple_spam'] = array (
|
// $config['simple_spam'] = array (
|
||||||
|
@ -391,12 +391,6 @@ function define_groups() {
|
|||||||
ksort($config['mod']['groups']);
|
ksort($config['mod']['groups']);
|
||||||
}
|
}
|
||||||
|
|
||||||
function create_antibot($board, $thread = null) {
|
|
||||||
require_once dirname(__FILE__) . '/anti-bot.php';
|
|
||||||
|
|
||||||
return _create_antibot($board, $thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sprintf3($str, $vars, $delim = '%') {
|
function sprintf3($str, $vars, $delim = '%') {
|
||||||
$replaces = array();
|
$replaces = array();
|
||||||
foreach ($vars as $k => $v) {
|
foreach ($vars as $k => $v) {
|
||||||
@ -1528,43 +1522,6 @@ function purge_old_antispam() {
|
|||||||
return $query->rowCount();
|
return $query->rowCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
function _create_antibot($board, $thread) {
|
|
||||||
global $config, $purged_old_antispam;
|
|
||||||
|
|
||||||
$antibot = new AntiBot([$board, $thread]);
|
|
||||||
|
|
||||||
// Delete old expired antispam, skipping those with NULL expiration timestamps (infinite lifetime).
|
|
||||||
if (!isset($purged_old_antispam) && $config['auto_maintenance']) {
|
|
||||||
$purged_old_antispam = true;
|
|
||||||
query('DELETE FROM ``antispam`` WHERE `expires` < UNIX_TIMESTAMP()') or error(db_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep the now invalid timestamps around for a bit to enable users to post if they're still on an old version of
|
|
||||||
// the HTML page.
|
|
||||||
// By virtue of existing, we know that we're making a new version of the page, and the user from now on may just reload.
|
|
||||||
if ($thread) {
|
|
||||||
$query = prepare('UPDATE ``antispam`` SET `expires` = UNIX_TIMESTAMP() + :expires WHERE `board` = :board AND `thread` = :thread AND `expires` IS NULL');
|
|
||||||
} else {
|
|
||||||
$query = prepare('UPDATE ``antispam`` SET `expires` = UNIX_TIMESTAMP() + :expires WHERE `board` = :board AND `thread` IS NULL AND `expires` IS NULL');
|
|
||||||
}
|
|
||||||
|
|
||||||
$query->bindValue(':board', $board);
|
|
||||||
if ($thread) {
|
|
||||||
$query->bindValue(':thread', $thread);
|
|
||||||
}
|
|
||||||
$query->bindValue(':expires', $config['spam']['hidden_inputs_expire']);
|
|
||||||
$query->execute() or error(db_error($query));
|
|
||||||
|
|
||||||
// Insert an antispam with infinite life as the HTML page of a thread might last well beyond the expiry date.
|
|
||||||
$query = prepare('INSERT INTO ``antispam`` VALUES (:board, :thread, :hash, UNIX_TIMESTAMP(), NULL, 0)');
|
|
||||||
$query->bindValue(':board', $board);
|
|
||||||
$query->bindValue(':thread', $thread);
|
|
||||||
$query->bindValue(':hash', $antibot->hash());
|
|
||||||
$query->execute() or error(db_error($query));
|
|
||||||
|
|
||||||
return $antibot;
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkSpam(array $extra_salt = array()) {
|
function checkSpam(array $extra_salt = array()) {
|
||||||
global $config, $pdo;
|
global $config, $pdo;
|
||||||
|
|
||||||
@ -1632,7 +1589,6 @@ function buildIndex($global_api = "yes") {
|
|||||||
$catalog_api_action = generation_strategy('sb_api', array($board['uri']));
|
$catalog_api_action = generation_strategy('sb_api', array($board['uri']));
|
||||||
|
|
||||||
$pages = null;
|
$pages = null;
|
||||||
$antibot = null;
|
|
||||||
|
|
||||||
if ($config['api']['enabled']) {
|
if ($config['api']['enabled']) {
|
||||||
$api = new Api(
|
$api = new Api(
|
||||||
@ -1684,21 +1640,12 @@ function buildIndex($global_api = "yes") {
|
|||||||
if ($wont_build_this_page) continue;
|
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) {
|
if (!$pages) {
|
||||||
$pages = getPages();
|
$pages = getPages();
|
||||||
}
|
}
|
||||||
$content['pages'] = $pages;
|
$content['pages'] = $pages;
|
||||||
$content['pages'][$page-1]['selected'] = true;
|
$content['pages'][$page-1]['selected'] = true;
|
||||||
$content['btn'] = getPageButtons($content['pages']);
|
$content['btn'] = getPageButtons($content['pages']);
|
||||||
$content['antibot'] = $antibot;
|
|
||||||
if ($mod) {
|
if ($mod) {
|
||||||
$content['pm'] = create_pm_header();
|
$content['pm'] = create_pm_header();
|
||||||
}
|
}
|
||||||
@ -2282,7 +2229,6 @@ function buildThread($id, $return = false, $mod = false) {
|
|||||||
error($config['error']['nonexistant']);
|
error($config['error']['nonexistant']);
|
||||||
|
|
||||||
$hasnoko50 = $thread->postCount() >= $config['noko50_min'];
|
$hasnoko50 = $thread->postCount() >= $config['noko50_min'];
|
||||||
$antibot = $mod || $return ? false : create_antibot($board['uri'], $id);
|
|
||||||
|
|
||||||
$options = [
|
$options = [
|
||||||
'board' => $board,
|
'board' => $board,
|
||||||
@ -2293,7 +2239,6 @@ function buildThread($id, $return = false, $mod = false) {
|
|||||||
'mod' => $mod,
|
'mod' => $mod,
|
||||||
'hasnoko50' => $hasnoko50,
|
'hasnoko50' => $hasnoko50,
|
||||||
'isnoko50' => false,
|
'isnoko50' => false,
|
||||||
'antibot' => $antibot,
|
|
||||||
'boardlist' => createBoardlist($mod),
|
'boardlist' => createBoardlist($mod),
|
||||||
'return' => ($mod ? '?' . $board['url'] . $config['file_index'] : $config['root'] . $board['dir'] . $config['file_index'])
|
'return' => ($mod ? '?' . $board['url'] . $config['file_index'] : $config['root'] . $board['dir'] . $config['file_index'])
|
||||||
];
|
];
|
||||||
@ -2330,20 +2275,17 @@ function buildThread($id, $return = false, $mod = false) {
|
|||||||
} elseif ($action == 'rebuild') {
|
} elseif ($action == 'rebuild') {
|
||||||
$noko50fn = $board['dir'] . $config['dir']['res'] . link_for($thread, true);
|
$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);
|
buildThread50($id, $return, $mod, $thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
file_write($board['dir'] . $config['dir']['res'] . link_for($thread), $body);
|
file_write($board['dir'] . $config['dir']['res'] . link_for($thread), $body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildThread50($id, $return = false, $mod = false, $thread = null, $antibot = false) {
|
function buildThread50($id, $return = false, $mod = false, $thread = null) {
|
||||||
global $board, $config;
|
global $board, $config;
|
||||||
$id = round($id);
|
$id = round($id);
|
||||||
|
|
||||||
if ($antibot)
|
|
||||||
$antibot->reset();
|
|
||||||
|
|
||||||
if (!$thread) {
|
if (!$thread) {
|
||||||
$query = prepare(sprintf("SELECT * FROM ``posts_%s`` WHERE (`thread` IS NULL AND `id` = :id) OR `thread` = :id ORDER BY `thread`,`id` DESC LIMIT :limit", $board['uri']));
|
$query = prepare(sprintf("SELECT * FROM ``posts_%s`` WHERE (`thread` IS NULL AND `id` = :id) OR `thread` = :id ORDER BY `thread`,`id` DESC LIMIT :limit", $board['uri']));
|
||||||
$query->bindValue(':id', $id, PDO::PARAM_INT);
|
$query->bindValue(':id', $id, PDO::PARAM_INT);
|
||||||
@ -2405,7 +2347,6 @@ function buildThread50($id, $return = false, $mod = false, $thread = null, $anti
|
|||||||
'mod' => $mod,
|
'mod' => $mod,
|
||||||
'hasnoko50' => $hasnoko50,
|
'hasnoko50' => $hasnoko50,
|
||||||
'isnoko50' => true,
|
'isnoko50' => true,
|
||||||
'antibot' => $mod ? false : ($antibot ? $antibot : create_antibot($board['uri'], $id)),
|
|
||||||
'boardlist' => createBoardlist($mod),
|
'boardlist' => createBoardlist($mod),
|
||||||
'return' => ($mod ? '?' . $board['url'] . $config['file_index'] : $config['root'] . $board['dir'] . $config['file_index'])
|
'return' => ($mod ? '?' . $board['url'] . $config['file_index'] : $config['root'] . $board['dir'] . $config['file_index'])
|
||||||
];
|
];
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
<form name="post" onsubmit="return doPost(this);" enctype="multipart/form-data" action="{{ config.post_url }}" method="post">
|
<form name="post" onsubmit="return doPost(this);" enctype="multipart/form-data" action="{{ config.post_url }}" method="post">
|
||||||
{{ antibot.html() }}
|
|
||||||
{% if id %}<input type="hidden" name="thread" value="{{ id }}">{% endif %}
|
{% if id %}<input type="hidden" name="thread" value="{{ id }}">{% endif %}
|
||||||
{{ antibot.html() }}
|
|
||||||
<input type="hidden" name="board" value="{{ board.uri }}">
|
<input type="hidden" name="board" value="{{ board.uri }}">
|
||||||
{{ antibot.html() }}
|
|
||||||
{% if current_page %}
|
{% if current_page %}
|
||||||
<input type="hidden" name="page" value="{{ current_page }}">
|
<input type="hidden" name="page" value="{{ current_page }}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -12,11 +9,9 @@
|
|||||||
{% if not config.field_disable_name or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri)) %}<tr>
|
{% if not config.field_disable_name or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri)) %}<tr>
|
||||||
<th>
|
<th>
|
||||||
{% trans %}Name{% endtrans %}
|
{% trans %}Name{% endtrans %}
|
||||||
{{ antibot.html() }}
|
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="name" size="25" maxlength="35" autocomplete="off"> {% if config.allow_no_country and config.country_flags %}<input id="no_country" name="no_country" type="checkbox"> <label for="no_country">{% trans %}Don't show my flag{% endtrans %}</label>{% endif %}
|
<input type="text" name="name" size="25" maxlength="35" autocomplete="off"> {% if config.allow_no_country and config.country_flags %}<input id="no_country" name="no_country" type="checkbox"> <label for="no_country">{% trans %}Don't show my flag{% endtrans %}</label>{% endif %}
|
||||||
{{ antibot.html() }}
|
|
||||||
</td>
|
</td>
|
||||||
</tr>{% endif %}
|
</tr>{% endif %}
|
||||||
{% if not config.field_disable_email or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri)) %}<tr>
|
{% if not config.field_disable_email or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri)) %}<tr>
|
||||||
@ -26,7 +21,6 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
{% trans %}Email{% endtrans %}
|
{% trans %}Email{% endtrans %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ antibot.html() }}
|
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
{% if (mod and not post.mod|hasPermission(config.mod.bypass_field_disable, board.uri) and config.field_email_selectbox) or (not mod and config.field_email_selectbox) %}
|
{% if (mod and not post.mod|hasPermission(config.mod.bypass_field_disable, board.uri) and config.field_email_selectbox) or (not mod and config.field_email_selectbox) %}
|
||||||
@ -39,17 +33,14 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<input type="text" name="email" size="25" maxlength="40" autocomplete="off">
|
<input type="text" name="email" size="25" maxlength="40" autocomplete="off">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ antibot.html() }}
|
|
||||||
{% if not (not (config.field_disable_subject or (id and config.field_disable_reply_subject)) or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri))) %}
|
{% if not (not (config.field_disable_subject or (id and config.field_disable_reply_subject)) or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri))) %}
|
||||||
<input accesskey="s" style="margin-left:2px;" type="submit" name="post" value="{% if id %}{{ config.button_reply }}{% else %}{{ config.button_newtopic }}{% endif %}" />{% if config.spoiler_images %} <input id="spoiler" name="spoiler" type="checkbox"> <label for="spoiler">{% trans %}Spoiler Image{% endtrans %}</label> {% endif %}
|
<input accesskey="s" style="margin-left:2px;" type="submit" name="post" value="{% if id %}{{ config.button_reply }}{% else %}{{ config.button_newtopic }}{% endif %}" />{% if config.spoiler_images %} <input id="spoiler" name="spoiler" type="checkbox"> <label for="spoiler">{% trans %}Spoiler Image{% endtrans %}</label> {% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ antibot.html() }}
|
|
||||||
</td>
|
</td>
|
||||||
</tr>{% endif %}
|
</tr>{% endif %}
|
||||||
{% if not (config.field_disable_subject or (id and config.field_disable_reply_subject)) or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri)) %}<tr>
|
{% if not (config.field_disable_subject or (id and config.field_disable_reply_subject)) or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri)) %}<tr>
|
||||||
<th>
|
<th>
|
||||||
{% trans %}Subject{% endtrans %}
|
{% trans %}Subject{% endtrans %}
|
||||||
{{ antibot.html() }}
|
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<input style="float:left;" type="text" name="subject" size="25" maxlength="100" autocomplete="off">
|
<input style="float:left;" type="text" name="subject" size="25" maxlength="100" autocomplete="off">
|
||||||
@ -60,11 +51,9 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{% trans %}Comment{% endtrans %}
|
{% trans %}Comment{% endtrans %}
|
||||||
{{ antibot.html() }}
|
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<textarea name="body" id="body" rows="5" cols="35"></textarea>
|
<textarea name="body" id="body" rows="5" cols="35"></textarea>
|
||||||
{{ antibot.html() }}
|
|
||||||
{% if not (not (config.field_disable_subject or (id and config.field_disable_reply_subject)) or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri))) %}
|
{% if not (not (config.field_disable_subject or (id and config.field_disable_reply_subject)) or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri))) %}
|
||||||
{% if not (not config.field_disable_email or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri))) %}
|
{% if not (not config.field_disable_email or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri))) %}
|
||||||
<input accesskey="s" style="margin-left:2px;" type="submit" name="post" value="{% if id %}{{ config.button_reply }}{% else %}{{ config.button_newtopic }}{% endif %}" />{% if config.spoiler_images %} <input id="spoiler" name="spoiler" type="checkbox"> <label for="spoiler">{% trans %}Spoiler Image{% endtrans %}</label>{% endif %}
|
<input accesskey="s" style="margin-left:2px;" type="submit" name="post" value="{% if id %}{{ config.button_reply }}{% else %}{{ config.button_newtopic }}{% endif %}" />{% if config.spoiler_images %} <input id="spoiler" name="spoiler" type="checkbox"> <label for="spoiler">{% trans %}Spoiler Image{% endtrans %}</label>{% endif %}
|
||||||
@ -80,11 +69,9 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<th>
|
<th>
|
||||||
{% trans %}Verification{% endtrans %}
|
{% trans %}Verification{% endtrans %}
|
||||||
{{ antibot.html() }}
|
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<div class="g-recaptcha" data-sitekey="{{ config.captcha.recaptcha.sitekey }}"></div>
|
<div class="g-recaptcha" data-sitekey="{{ config.captcha.recaptcha.sitekey }}"></div>
|
||||||
{{ antibot.html() }}
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -92,11 +79,9 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{% trans %}Verification{% endtrans %}
|
{% trans %}Verification{% endtrans %}
|
||||||
{{ antibot.html() }}
|
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<div class="h-captcha" data-sitekey="{{ config.captcha.hcaptcha.sitekey }}"></div>
|
<div class="h-captcha" data-sitekey="{{ config.captcha.hcaptcha.sitekey }}"></div>
|
||||||
{{ antibot.html() }}
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -173,14 +158,12 @@
|
|||||||
<input style="display:inline" type="text" id="file_url" name="file_url" size="35">
|
<input style="display:inline" type="text" id="file_url" name="file_url" size="35">
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ antibot.html() }}
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% if config.enable_embedding %}
|
{% if config.enable_embedding %}
|
||||||
<tr id="upload_embed">
|
<tr id="upload_embed">
|
||||||
<th>
|
<th>
|
||||||
{% trans %}Embed{% endtrans %}
|
{% trans %}Embed{% endtrans %}
|
||||||
{{ antibot.html() }}
|
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="embed" value="" size="30" maxlength="120" autocomplete="off">
|
<input type="text" name="embed" value="" size="30" maxlength="120" autocomplete="off">
|
||||||
@ -211,27 +194,21 @@
|
|||||||
{% if not config.field_disable_password or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri)) %}<tr>
|
{% if not config.field_disable_password or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri)) %}<tr>
|
||||||
<th>
|
<th>
|
||||||
{% trans %}Password{% endtrans %}
|
{% trans %}Password{% endtrans %}
|
||||||
{{ antibot.html() }}
|
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="password" value="" size="12" maxlength="18" autocomplete="off">
|
<input type="text" name="password" value="" size="12" maxlength="18" autocomplete="off">
|
||||||
<span class="unimportant">{% trans %}(For file deletion.){% endtrans %}</span>
|
<span class="unimportant">{% trans %}(For file deletion.){% endtrans %}</span>
|
||||||
{{ antibot.html() }}
|
|
||||||
</td>
|
</td>
|
||||||
</tr>{% endif %}
|
</tr>{% endif %}
|
||||||
{% if config.simple_spam and not id %}<tr>
|
{% if config.simple_spam and not id %}<tr>
|
||||||
<th>
|
<th>
|
||||||
{{ config.simple_spam.question }}
|
{{ config.simple_spam.question }}
|
||||||
{{ antibot.html() }}
|
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="simple_spam" value="" size="12" maxlength="18" autocomplete="off">
|
<input type="text" name="simple_spam" value="" size="12" maxlength="18" autocomplete="off">
|
||||||
{{ antibot.html() }}
|
|
||||||
</td>
|
</td>
|
||||||
</tr>{% endif %}
|
</tr>{% endif %}
|
||||||
</table>
|
</table>
|
||||||
{{ antibot.html(true) }}
|
|
||||||
<input type="hidden" name="hash" value="{{ antibot.hash() }}">
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<script type="text/javascript">{% verbatim %}
|
<script type="text/javascript">{% verbatim %}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user