Better and faster basic flood prevention, while merging it into $config['filters'].
This commit is contained in:
parent
14ff0fbeb3
commit
f309e4037c
177
inc/config.php
177
inc/config.php
@ -168,13 +168,6 @@
|
||||
* ====================
|
||||
*/
|
||||
|
||||
// Minimum time between between each post by the same IP address.
|
||||
$config['flood_time'] = 10;
|
||||
// Minimum time between between each post with the exact same content AND same IP address.
|
||||
$config['flood_time_ip'] = 120;
|
||||
// Same as above but by a different IP address. (Same content, not necessarily same IP address.)
|
||||
$config['flood_time_same'] = 30;
|
||||
|
||||
/*
|
||||
* To further prevent spam and abuse, you can use DNS blacklists (DNSBL). A DNSBL is a list of IP
|
||||
* addresses published through the Internet Domain Name Service (DNS) either as a zone file that can be
|
||||
@ -283,6 +276,118 @@
|
||||
$config['recaptcha_public'] = '6LcXTcUSAAAAAKBxyFWIt2SO8jwx4W7wcSMRoN3f';
|
||||
$config['recaptcha_private'] = '6LcXTcUSAAAAAOGVbVdhmEM1_SyRF4xTKe8jbzf_';
|
||||
|
||||
/*
|
||||
* Custom filters detect certain posts and reject/ban accordingly. They are made up of a condition and an
|
||||
* action (for when ALL conditions are met). As every single post has to be put through each filter,
|
||||
* having hundreds probably isn't ideal as it could slow things down.
|
||||
*
|
||||
* By default, the custom filters array is populated with basic flood prevention conditions. This
|
||||
* includes forcing users to wait at least 5 seconds between posts. To disable (or amend) these flood
|
||||
* prevention settings, you will need to empty the $config['filters'] array first. You can do so by
|
||||
* adding "$config['filters'] = array();" to inc/instance-config.php. Basic flood prevention used to be
|
||||
* controlled solely by config variables such as $config['flood_time'] and $config['flood_time_ip'], and
|
||||
* it still is, as long as you leave the relevant $config['filters'] intact. These old config variables
|
||||
* still exist for backwards-compatability and general convenience.
|
||||
*
|
||||
* Read more: http://tinyboard.org/docs/index.php?p=Config/Filters
|
||||
*/
|
||||
|
||||
// Minimum time between between each post by the same IP address.
|
||||
$config['flood_time'] = 10;
|
||||
// Minimum time between between each post with the exact same content AND same IP address.
|
||||
$config['flood_time_ip'] = 120;
|
||||
// Same as above but by a different IP address. (Same content, not necessarily same IP address.)
|
||||
$config['flood_time_same'] = 30;
|
||||
|
||||
// Minimum time between posts by the same IP address (all boards).
|
||||
$config['filters'][] = array(
|
||||
'condition' => array(
|
||||
'flood-match' => array('ip'), // Only match IP address
|
||||
'flood-time' => &$config['flood_time'] // 10 seconds minimum
|
||||
),
|
||||
'action' => 'reject',
|
||||
'message' => &$config['error']['flood']
|
||||
);
|
||||
|
||||
// Minimum time between posts by the same IP address with the same text.
|
||||
$config['filters'][] = array(
|
||||
'condition' => array(
|
||||
'flood-match' => array('ip', 'body'), // Match IP address and post body
|
||||
'flood-time' => &$config['flood_time_ip'] // 2 minutes minimum
|
||||
),
|
||||
'action' => 'reject',
|
||||
'message' => &$config['error']['flood']
|
||||
);
|
||||
|
||||
// Minimum time between posts with the same text. (Same content, but not always the same IP address.)
|
||||
$config['filters'][] = array(
|
||||
'condition' => array(
|
||||
'flood-match' => array('body'), // Match IP address and post body
|
||||
'flood-time' => &$config['flood_time_same'] // 30 seconds minimum
|
||||
),
|
||||
'action' => 'reject',
|
||||
'message' => &$config['error']['flood']
|
||||
);
|
||||
|
||||
// Example: Minimum time between posts with the same file hash.
|
||||
// $config['filters'][] = array(
|
||||
// 'condition' => array(
|
||||
// 'flood-match' => array('file'), // Match file hash
|
||||
// 'flood-time' => 60 * 2 // 2 minutes minimum
|
||||
// ),
|
||||
// 'action' => 'reject',
|
||||
// 'message' => &$config['error']['flood']
|
||||
// );
|
||||
|
||||
// An example of blocking an imaginary known spammer, who keeps posting a reply with the name "surgeon",
|
||||
// ending his posts with "regards, the surgeon" or similar.
|
||||
// $config['filters'][] = array(
|
||||
// 'condition' => array(
|
||||
// 'name' => '/^surgeon$/',
|
||||
// 'body' => '/regards,\s+(the )?surgeon$/i',
|
||||
// 'OP' => false
|
||||
// ),
|
||||
// 'action' => 'reject',
|
||||
// 'message' => 'Go away, spammer.'
|
||||
// );
|
||||
|
||||
// Same as above, but issuing a 3-hour ban instead of just reject the post.
|
||||
// $config['filters'][] = array(
|
||||
// 'condition' => array(
|
||||
// 'name' => '/^surgeon$/',
|
||||
// 'body' => '/regards,\s+(the )?surgeon$/i',
|
||||
// 'OP' => false
|
||||
// ),
|
||||
// 'action' => 'ban',
|
||||
// 'expires' => 60 * 60 * 3, // 3 hours
|
||||
// 'reason' => 'Go away, spammer.'
|
||||
// );
|
||||
|
||||
// PHP 5.3+ (anonymous functions)
|
||||
// There is also a "custom" condition, making the possibilities of this feature pretty much endless.
|
||||
// This is a bad example, because there is already a "name" condition built-in.
|
||||
// $config['filters'][] = array(
|
||||
// 'condition' => array(
|
||||
// 'body' => '/h$/i',
|
||||
// 'OP' => false,
|
||||
// 'custom' => function($post) {
|
||||
// if($post['name'] == 'Anonymous')
|
||||
// return true;
|
||||
// else
|
||||
// return false;
|
||||
// }
|
||||
// ),
|
||||
// 'action' => 'reject'
|
||||
// );
|
||||
|
||||
// Filter flood prevention conditions ("flood-match") depend on a table which contains a cache of recent
|
||||
// posts across all boards. This table is automatically purged of older posts, determining the maximum
|
||||
// "age" by looking at each filter. However, when determining the maximum age, Tinyboard does not look
|
||||
// outside the current board. This means that if you have a special flood condition for a specific board
|
||||
// (contained in a board configuration file) which has a flood-time greater than any of those in the
|
||||
// global configuration, you need to set the following variable to the maximum flood-time condition value.
|
||||
// $config['flood_cache'] = 60 * 60 * 24; // 24 hours
|
||||
|
||||
/*
|
||||
* ====================
|
||||
* Post settings
|
||||
@ -401,57 +506,6 @@
|
||||
// Require users to see the ban page at least once for a ban even if it has since expired.
|
||||
$config['require_ban_view'] = true;
|
||||
|
||||
/*
|
||||
* Custom filters detect certain posts and reject/ban accordingly. They are made up of a
|
||||
* condition and an action (for when ALL conditions are met). As every single post has to
|
||||
* be put through each filter, having hundreds probably isn’t ideal as it could slow things down.
|
||||
*
|
||||
* Read more: http://tinyboard.org/docs/index.php?p=Config/Filters
|
||||
*
|
||||
* This used to be named $config['flood_filters'] (still exists as an alias).
|
||||
*/
|
||||
|
||||
// An example of blocking an imaginary known spammer, who keeps posting a reply with the name "surgeon",
|
||||
// ending his posts with "regards, the surgeon" or similar.
|
||||
// $config['filters'][] = array(
|
||||
// 'condition' => array(
|
||||
// 'name' => '/^surgeon$/',
|
||||
// 'body' => '/regards,\s+(the )?surgeon$/i',
|
||||
// 'OP' => false
|
||||
// ),
|
||||
// 'action' => 'reject',
|
||||
// 'message' => 'Go away, spammer.'
|
||||
// );
|
||||
|
||||
// Same as above, but issuing a 3-hour ban instead of just reject the post.
|
||||
// $config['filters'][] = array(
|
||||
// 'condition' => array(
|
||||
// 'name' => '/^surgeon$/',
|
||||
// 'body' => '/regards,\s+(the )?surgeon$/i',
|
||||
// 'OP' => false
|
||||
// ),
|
||||
// 'action' => 'ban',
|
||||
// 'expires' => 60 * 60 * 3, // 3 hours
|
||||
// 'reason' => 'Go away, spammer.'
|
||||
// );
|
||||
|
||||
// PHP 5.3+ (anonymous functions)
|
||||
// There is also a "custom" condition, making the possibilities of this feature pretty much endless.
|
||||
// This is a bad example, because there is already a "name" condition built-in.
|
||||
// $config['filters'][] = array(
|
||||
// 'condition' => array(
|
||||
// 'body' => '/h$/i',
|
||||
// 'OP' => false,
|
||||
// 'custom' => function($post) {
|
||||
// if($post['name'] == 'Anonymous')
|
||||
// return true;
|
||||
// else
|
||||
// return false;
|
||||
// }
|
||||
// ),
|
||||
// 'action' => 'reject'
|
||||
// );
|
||||
|
||||
/*
|
||||
* ====================
|
||||
* Markup settings
|
||||
@ -593,10 +647,6 @@
|
||||
// that as a thumbnail instead of resizing/redrawing.
|
||||
$config['minimum_copy_resize'] = false;
|
||||
|
||||
// Image hashing function. There's really no reason to change this.
|
||||
// sha1_file, md5_file, etc. You can also define your own similar function.
|
||||
$config['file_hash'] = 'sha1_file';
|
||||
|
||||
// Maximum image upload size in bytes.
|
||||
$config['max_filesize'] = 10 * 1024 * 1024; // 10MB
|
||||
// Maximum image dimensions.
|
||||
@ -1156,7 +1206,8 @@
|
||||
// Post bypass unoriginal content check on robot-enabled boards
|
||||
$config['mod']['postunoriginal'] = ADMIN;
|
||||
// Bypass flood check
|
||||
$config['mod']['flood'] = ADMIN;
|
||||
$config['mod']['bypass_filters'] = ADMIN;
|
||||
$config['mod']['flood'] = &$config['mod']['bypass_filters'];
|
||||
// Raw HTML posting
|
||||
$config['mod']['rawhtml'] = ADMIN;
|
||||
|
||||
|
109
inc/filters.php
109
inc/filters.php
@ -7,6 +7,7 @@
|
||||
defined('TINYBOARD') or exit;
|
||||
|
||||
class Filter {
|
||||
public $flood_check;
|
||||
private $condition;
|
||||
|
||||
public function __construct(array $arr) {
|
||||
@ -22,6 +23,56 @@ class Filter {
|
||||
if (!is_callable($match))
|
||||
error('Custom condition for filter is not callable!');
|
||||
return $match($post);
|
||||
case 'flood-match':
|
||||
if (!is_array($match))
|
||||
error('Filter condition "flood-match" must be an array.');
|
||||
|
||||
// Filter out "flood" table entries which do not match this filter.
|
||||
|
||||
$flood_check_matched = array();
|
||||
|
||||
foreach ($this->flood_check as $flood_post) {
|
||||
foreach ($match as $flood_match_arg) {
|
||||
switch ($flood_match_arg) {
|
||||
case 'ip':
|
||||
if ($flood_post['ip'] != $_SERVER['REMOTE_ADDR'])
|
||||
continue 3;
|
||||
break;
|
||||
case 'body':
|
||||
if ($flood_post['posthash'] != md5($post['body_nomarkup']))
|
||||
continue 3;
|
||||
break;
|
||||
case 'file':
|
||||
if (!isset($post['filehash']))
|
||||
return false;
|
||||
if ($flood_post['filehash'] != $post['filehash'])
|
||||
continue 3;
|
||||
break;
|
||||
case 'board':
|
||||
if ($flood_post['board'] != $post['board'])
|
||||
continue 3;
|
||||
break;
|
||||
case 'isreply':
|
||||
if ($flood_post['isreply'] == $post['op'])
|
||||
continue 3;
|
||||
break;
|
||||
default:
|
||||
error('Invalid filter flood condition: ' . $flood_match_arg);
|
||||
}
|
||||
}
|
||||
$flood_check_matched[] = $flood_post;
|
||||
}
|
||||
|
||||
$this->flood_check = $flood_check_matched;
|
||||
|
||||
return !empty($this->flood_check);
|
||||
case 'flood-time':
|
||||
foreach ($this->flood_check as $flood_post) {
|
||||
if (time() - $flood_post['time'] <= $match) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
case 'name':
|
||||
return preg_match($match, $post['name']);
|
||||
case 'trip':
|
||||
@ -31,7 +82,7 @@ class Filter {
|
||||
case 'subject':
|
||||
return preg_match($match, $post['subject']);
|
||||
case 'body':
|
||||
return preg_match($match, $post['body']);
|
||||
return preg_match($match, $post['body_nomarkup']);
|
||||
case 'filename':
|
||||
if (!$post['has_file'])
|
||||
return false;
|
||||
@ -126,14 +177,64 @@ class Filter {
|
||||
}
|
||||
}
|
||||
|
||||
function purge_flood_table() {
|
||||
global $config;
|
||||
|
||||
// Determine how long we need to keep a cache of posts for flood prevention. Unfortunately, it is not
|
||||
// aware of flood filters in other board configurations. You can solve this problem by settings the
|
||||
// config variable $config['flood_cache'] (seconds).
|
||||
|
||||
if (isset($config['flood_cache'])) {
|
||||
$max_time = &$config['flood_cache'];
|
||||
} else {
|
||||
$max_time = 0;
|
||||
foreach ($config['filters'] as $filter) {
|
||||
if (isset($filter['condition']['flood-time']))
|
||||
$max_time = max($max_time, $filter['condition']['flood-time']);
|
||||
}
|
||||
}
|
||||
|
||||
$time = time() - $max_time;
|
||||
|
||||
query("DELETE FROM ``flood`` WHERE ``time`` < $time") or error(db_error());
|
||||
}
|
||||
|
||||
function do_filters(array $post) {
|
||||
global $config;
|
||||
|
||||
if (!isset($config['filters']))
|
||||
if (!isset($config['filters']) || empty($config['filters']))
|
||||
return;
|
||||
|
||||
foreach ($config['filters'] as $arr) {
|
||||
$filter = new Filter($arr);
|
||||
foreach ($config['filters'] as $filter) {
|
||||
if (isset($filter['condition']['flood-match'])) {
|
||||
$has_flood = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
purge_flood_table();
|
||||
|
||||
if (isset($has_flood)) {
|
||||
if ($post['has_file']) {
|
||||
$query = prepare("SELECT * FROM ``flood`` WHERE `ip` = :ip OR `posthash` = :posthash OR `filehash` = :filehash");
|
||||
$query->bindValue(':ip', $_SERVER['REMOTE_ADDR']);
|
||||
$query->bindValue(':posthash', md5($post['body_nomarkup']));
|
||||
$query->bindValue(':filehash', $post['filehash']);
|
||||
} else {
|
||||
$query = prepare("SELECT * FROM ``flood`` WHERE `ip` = :ip OR `posthash` = :posthash");
|
||||
$query->bindValue(':ip', $_SERVER['REMOTE_ADDR']);
|
||||
$query->bindValue(':posthash', md5($post['body_nomarkup']));
|
||||
|
||||
}
|
||||
$query->execute() or error(db_error($query));
|
||||
$flood_check = $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
} else {
|
||||
$flood_check = false;
|
||||
}
|
||||
|
||||
foreach ($config['filters'] as $filter_array) {
|
||||
$filter = new Filter($filter_array);
|
||||
$filter->flood_check = $flood_check;
|
||||
if ($filter->check($post))
|
||||
$filter->action();
|
||||
}
|
||||
|
@ -572,30 +572,6 @@ function listBoards() {
|
||||
return $boards;
|
||||
}
|
||||
|
||||
function checkFlood($post) {
|
||||
global $board, $config;
|
||||
|
||||
$query = prepare(sprintf("SELECT COUNT(*) FROM ``posts_%s`` WHERE
|
||||
(`ip` = :ip AND `time` >= :floodtime)
|
||||
OR
|
||||
(`ip` = :ip AND :body != '' AND `body_nomarkup` = :body AND `time` >= :floodsameiptime)
|
||||
OR
|
||||
(:body != '' AND `body_nomarkup` = :body AND `time` >= :floodsametime) LIMIT 1", $board['uri']));
|
||||
$query->bindValue(':ip', $_SERVER['REMOTE_ADDR']);
|
||||
$query->bindValue(':body', $post['body']);
|
||||
$query->bindValue(':floodtime', time()-$config['flood_time'], PDO::PARAM_INT);
|
||||
$query->bindValue(':floodsameiptime', time()-$config['flood_time_ip'], PDO::PARAM_INT);
|
||||
$query->bindValue(':floodsametime', time()-$config['flood_time_same'], PDO::PARAM_INT);
|
||||
$query->execute() or error(db_error($query));
|
||||
|
||||
$flood = (bool) $query->fetchColumn();
|
||||
|
||||
if (event('check-flood', $post))
|
||||
return true;
|
||||
|
||||
return $flood;
|
||||
}
|
||||
|
||||
function until($timestamp) {
|
||||
$difference = $timestamp - time();
|
||||
if ($difference < 60) {
|
||||
@ -780,6 +756,22 @@ function threadExists($id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function insertFloodPost(array $post) {
|
||||
global $board;
|
||||
|
||||
$query = prepare("INSERT INTO ``flood`` VALUES (NULL, :ip, :board, :time, :posthash, :filehash, :isreply)");
|
||||
$query->bindValue(':ip', $_SERVER['REMOTE_ADDR']);
|
||||
$query->bindValue(':board', $board['uri']);
|
||||
$query->bindValue(':time', time());
|
||||
$query->bindValue(':posthash', md5($post['body_nomarkup']));
|
||||
if ($post['has_file'])
|
||||
$query->bindValue(':filehash', $post['filehash']);
|
||||
else
|
||||
$query->bindValue(':filehash', null, PDO::PARAM_NULL);
|
||||
$query->bindValue(':isreply', !$post['op']);
|
||||
$query->execute() or error(db_error($query));
|
||||
}
|
||||
|
||||
function post(array $post) {
|
||||
global $pdo, $board;
|
||||
$query = prepare(sprintf("INSERT INTO ``posts_%s`` VALUES ( NULL, :thread, :subject, :email, :name, :trip, :capcode, :body, :body_nomarkup, :time, :time, :thumb, :thumbwidth, :thumbheight, :file, :width, :height, :filesize, :filename, :filehash, :password, :ip, :sticky, :locked, 0, :embed)", $board['uri']));
|
||||
@ -788,19 +780,19 @@ function post(array $post) {
|
||||
if (!empty($post['subject'])) {
|
||||
$query->bindValue(':subject', $post['subject']);
|
||||
} else {
|
||||
$query->bindValue(':subject', NULL, PDO::PARAM_NULL);
|
||||
$query->bindValue(':subject', null, PDO::PARAM_NULL);
|
||||
}
|
||||
|
||||
if (!empty($post['email'])) {
|
||||
$query->bindValue(':email', $post['email']);
|
||||
} else {
|
||||
$query->bindValue(':email', NULL, PDO::PARAM_NULL);
|
||||
$query->bindValue(':email', null, PDO::PARAM_NULL);
|
||||
}
|
||||
|
||||
if (!empty($post['trip'])) {
|
||||
$query->bindValue(':trip', $post['trip']);
|
||||
} else {
|
||||
$query->bindValue(':trip', NULL, PDO::PARAM_NULL);
|
||||
$query->bindValue(':trip', null, PDO::PARAM_NULL);
|
||||
}
|
||||
|
||||
$query->bindValue(':name', $post['name']);
|
||||
@ -811,27 +803,27 @@ function post(array $post) {
|
||||
$query->bindValue(':ip', isset($post['ip']) ? $post['ip'] : $_SERVER['REMOTE_ADDR']);
|
||||
|
||||
if ($post['op'] && $post['mod'] && isset($post['sticky']) && $post['sticky']) {
|
||||
$query->bindValue(':sticky', 1, PDO::PARAM_INT);
|
||||
$query->bindValue(':sticky', true, PDO::PARAM_INT);
|
||||
} else {
|
||||
$query->bindValue(':sticky', 0, PDO::PARAM_INT);
|
||||
$query->bindValue(':sticky', false, PDO::PARAM_INT);
|
||||
}
|
||||
|
||||
if ($post['op'] && $post['mod'] && isset($post['locked']) && $post['locked']) {
|
||||
$query->bindValue(':locked', 1, PDO::PARAM_INT);
|
||||
$query->bindValue(':locked', true, PDO::PARAM_INT);
|
||||
} else {
|
||||
$query->bindValue(':locked', 0, PDO::PARAM_INT);
|
||||
$query->bindValue(':locked', false, PDO::PARAM_INT);
|
||||
}
|
||||
|
||||
if ($post['mod'] && isset($post['capcode']) && $post['capcode']) {
|
||||
$query->bindValue(':capcode', $post['capcode'], PDO::PARAM_INT);
|
||||
} else {
|
||||
$query->bindValue(':capcode', NULL, PDO::PARAM_NULL);
|
||||
$query->bindValue(':capcode', null, PDO::PARAM_NULL);
|
||||
}
|
||||
|
||||
if (!empty($post['embed'])) {
|
||||
$query->bindValue(':embed', $post['embed']);
|
||||
} else {
|
||||
$query->bindValue(':embed', NULL, PDO::PARAM_NULL);
|
||||
$query->bindValue(':embed', null, PDO::PARAM_NULL);
|
||||
}
|
||||
|
||||
if ($post['op']) {
|
||||
|
17
install.php
17
install.php
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
// Installation/upgrade file
|
||||
define('VERSION', 'v0.9.6-dev-18');
|
||||
define('VERSION', 'v0.9.6-dev-19');
|
||||
|
||||
require 'inc/functions.php';
|
||||
|
||||
@ -392,6 +392,21 @@ if (file_exists($config['has_installed'])) {
|
||||
query("ALTER TABLE ``ip_notes``
|
||||
DROP INDEX `ip`,
|
||||
ADD INDEX `ip_lookup` (`ip`, `time`)") or error(db_error());
|
||||
case 'v0.9.6-dev-18':
|
||||
query("CREATE TABLE IF NOT EXISTS ``flood`` (
|
||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`ip` varchar(39) CHARACTER SET ascii NOT NULL,
|
||||
`board` varchar(58) CHARACTER SET utf8 NOT NULL,
|
||||
`time` int(11) NOT NULL,
|
||||
`posthash` char(32) NOT NULL,
|
||||
`filehash` char(32) DEFAULT NULL,
|
||||
`isreply` tinyint(1) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ip` (`ip`),
|
||||
KEY `posthash` (`posthash`),
|
||||
KEY `filehash` (`filehash`),
|
||||
KEY `time` (`time`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=ascii COLLATE=ascii_bin AUTO_INCREMENT=1 ;") or error(db_error());
|
||||
case false:
|
||||
// Update version number
|
||||
file_write($config['has_installed'], VERSION);
|
||||
|
21
install.sql
21
install.sql
@ -245,6 +245,27 @@ CREATE TABLE IF NOT EXISTS `theme_settings` (
|
||||
KEY `theme` (`theme`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `flood`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `flood` (
|
||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`ip` varchar(39) CHARACTER SET ascii NOT NULL,
|
||||
`board` varchar(58) CHARACTER SET utf8 NOT NULL,
|
||||
`time` int(11) NOT NULL,
|
||||
`posthash` char(32) NOT NULL,
|
||||
`filehash` char(32) DEFAULT NULL,
|
||||
`isreply` tinyint(1) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ip` (`ip`),
|
||||
KEY `posthash` (`posthash`),
|
||||
KEY `filehash` (`filehash`),
|
||||
KEY `time` (`time`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=ascii COLLATE=ascii_bin AUTO_INCREMENT=1 ;
|
||||
|
||||
/*!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 */;
|
||||
|
23
post.php
23
post.php
@ -198,7 +198,7 @@ if (isset($_POST['delete'])) {
|
||||
}
|
||||
|
||||
if ($post['mod'] = isset($_POST['mod']) && $_POST['mod']) {
|
||||
require 'inc/mod.php';
|
||||
require 'inc/mod/auth.php';
|
||||
if (!$mod) {
|
||||
// Liar. You're not a mod.
|
||||
error($config['error']['notamod']);
|
||||
@ -428,11 +428,6 @@ if (isset($_POST['delete'])) {
|
||||
|
||||
wordfilters($post['body']);
|
||||
|
||||
// Check for a flood
|
||||
if (!hasPermission($config['mod']['flood'], $board['uri']) && checkFlood($post)) {
|
||||
error($config['error']['flood']);
|
||||
}
|
||||
|
||||
$post['body'] = escape_markup_modifiers($post['body']);
|
||||
|
||||
if ($mod && isset($post['raw']) && $post['raw']) {
|
||||
@ -468,10 +463,8 @@ if (isset($_POST['delete'])) {
|
||||
}
|
||||
|
||||
$post['tracked_cites'] = markup($post['body'], true);
|
||||
|
||||
|
||||
require_once 'inc/filters.php';
|
||||
|
||||
do_filters($post);
|
||||
|
||||
if ($post['has_file']) {
|
||||
if (!in_array($post['extension'], $config['allowed_ext']) && !in_array($post['extension'], $config['allowed_ext_files']))
|
||||
@ -487,9 +480,17 @@ if (isset($_POST['delete'])) {
|
||||
if (!is_readable($upload))
|
||||
error($config['error']['nomove']);
|
||||
|
||||
$post['filehash'] = $config['file_hash']($upload);
|
||||
$post['filehash'] = md5_file($upload);
|
||||
$post['filesize'] = filesize($upload);
|
||||
}
|
||||
|
||||
if (!hasPermission($config['mod']['bypass_filters'], $board['uri'])) {
|
||||
require_once 'inc/filters.php';
|
||||
|
||||
do_filters($post);
|
||||
}
|
||||
|
||||
if ($post['has_file']) {
|
||||
if ($is_an_image && $config['ie_mime_type_detection'] !== false) {
|
||||
// Check IE MIME type detection XSS exploit
|
||||
$buffer = file_get_contents($upload, null, null, null, 255);
|
||||
@ -679,6 +680,8 @@ if (isset($_POST['delete'])) {
|
||||
|
||||
$post['id'] = $id = post($post);
|
||||
|
||||
insertFloodPost($post);
|
||||
|
||||
if (isset($post['antispam_hash'])) {
|
||||
incrementSpamHash($post['antispam_hash']);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user