Note: In a previous commit, I began making inc/mod/auth.php more modular with the check_login() function. Including it does NOT check mod login by default anymore like it does on vichan. You have to call check_login(). I've finally included it in inc/functions.php. If you have any custom pages that use inc/mod/auth.php, just including functions.php is enough now. =================================== Also: backports 351375185e5 (early 404)pull/47/head^2
@@ -511,6 +511,13 @@ | |||||
// The timeout for the above, in seconds. | // The timeout for the above, in seconds. | ||||
$config['upload_by_url_timeout'] = 15; | $config['upload_by_url_timeout'] = 15; | ||||
// Enable early 404? With default settings, a thread would 404 if it was to leave page 3, if it had less | |||||
// than 3 replies. | |||||
$config['early_404'] = false; | |||||
$config['early_404_page'] = 3; | |||||
$config['early_404_replies'] = 5; | |||||
// A wordfilter (sometimes referred to as just a "filter" or "censor") automatically scans users’ posts | // A wordfilter (sometimes referred to as just a "filter" or "censor") automatically scans users’ posts | ||||
// as they are submitted and changes or censors particular words or phrases. | // as they are submitted and changes or censors particular words or phrases. | ||||
@@ -1537,25 +1544,30 @@ | |||||
/* | /* | ||||
* ==================== | * ==================== | ||||
* Public post search | |||||
* Public pages | |||||
* ==================== | * ==================== | ||||
*/ | */ | ||||
// Public post search settings | |||||
$config['search'] = array(); | $config['search'] = array(); | ||||
// Enable the search form | // Enable the search form | ||||
$config['search']['enable'] = false; | $config['search']['enable'] = false; | ||||
// Maximal number of queries per IP address per minutes | // Maximal number of queries per IP address per minutes | ||||
$config['search']['queries_per_minutes'] = Array(15, 2); | |||||
$config['search']['queries_per_minutes'] = Array(15, 2); | |||||
// Global maximal number of queries per minutes | // Global maximal number of queries per minutes | ||||
$config['search']['queries_per_minutes_all'] = Array(50, 2); | |||||
$config['search']['queries_per_minutes_all'] = Array(50, 2); | |||||
// Limit of search results | // Limit of search results | ||||
$config['search']['search_limit'] = 100; | |||||
$config['search']['search_limit'] = 100; | |||||
// Boards for searching | // Boards for searching | ||||
//$config['search']['boards'] = array('a', 'b', 'c', 'd', 'e'); | |||||
//$config['search']['boards'] = array('a', 'b', 'c', 'd', 'e'); | |||||
// Enable public logs? 0: NO, 1: YES, 2: YES, but drop names | |||||
$config['public_logs'] = 0; | |||||
/* | /* | ||||
* ==================== | * ==================== | ||||
@@ -18,6 +18,7 @@ require_once 'inc/template.php'; | |||||
require_once 'inc/database.php'; | require_once 'inc/database.php'; | ||||
require_once 'inc/events.php'; | require_once 'inc/events.php'; | ||||
require_once 'inc/api.php'; | require_once 'inc/api.php'; | ||||
require_once 'inc/mod/auth.php'; | |||||
require_once 'inc/polyfill.php'; | require_once 'inc/polyfill.php'; | ||||
if (!extension_loaded('gettext')) { | if (!extension_loaded('gettext')) { | ||||
@@ -524,7 +525,8 @@ function setupBoard($array) { | |||||
$board = array( | $board = array( | ||||
'uri' => $array['uri'], | 'uri' => $array['uri'], | ||||
'title' => $array['title'], | 'title' => $array['title'], | ||||
'subtitle' => $array['subtitle'] | |||||
'subtitle' => $array['subtitle'], | |||||
#'indexed' => $array['indexed'], | |||||
); | ); | ||||
// older versions | // older versions | ||||
@@ -1270,7 +1272,7 @@ function deletePost($id, $error_if_doesnt_exist=true, $rebuild_after=true) { | |||||
return true; | return true; | ||||
} | } | ||||
function clean() { | |||||
function clean($pid = false) { | |||||
global $board, $config; | global $board, $config; | ||||
$offset = round($config['max_pages']*$config['threads_per_page']); | $offset = round($config['max_pages']*$config['threads_per_page']); | ||||
@@ -1281,6 +1283,22 @@ function clean() { | |||||
$query->execute() or error(db_error($query)); | $query->execute() or error(db_error($query)); | ||||
while ($post = $query->fetch(PDO::FETCH_ASSOC)) { | while ($post = $query->fetch(PDO::FETCH_ASSOC)) { | ||||
deletePost($post['id'], false, false); | deletePost($post['id'], false, false); | ||||
if ($pid) modLog("Automatically deleting thread #{$post['id']} due to new thread #{$pid}"); | |||||
} | |||||
// Bump off threads with X replies earlier, spam prevention method | |||||
if ($config['early_404']) { | |||||
$offset = round($config['early_404_page']*$config['threads_per_page']); | |||||
$query = prepare(sprintf("SELECT `id` AS `thread_id`, (SELECT COUNT(`id`) FROM ``posts_%s`` WHERE `thread` = `thread_id`) AS `reply_count` FROM ``posts_%s`` WHERE `thread` IS NULL ORDER BY `sticky` DESC, `bump` DESC LIMIT :offset, 9001", $board['uri'], $board['uri'])); | |||||
$query->bindValue(':offset', $offset, PDO::PARAM_INT); | |||||
$query->execute() or error(db_error($query)); | |||||
while ($post = $query->fetch(PDO::FETCH_ASSOC)) { | |||||
if ($post['reply_count'] < $config['early_404_replies']) { | |||||
deletePost($post['thread_id'], false, false); | |||||
if ($pid) modLog("Automatically deleting thread #{$post['thread_id']} due to new thread #{$pid} (early 404 is set, #{$post['thread_id']} had {$post['reply_count']} replies)"); | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -130,7 +130,7 @@ function destroyCookies() { | |||||
function modLog($action, $_board=null) { | function modLog($action, $_board=null) { | ||||
global $mod, $board, $config; | global $mod, $board, $config; | ||||
$query = prepare("INSERT INTO ``modlogs`` VALUES (:id, :ip, :board, :time, :text)"); | $query = prepare("INSERT INTO ``modlogs`` VALUES (:id, :ip, :board, :time, :text)"); | ||||
$query->bindValue(':id', $mod['id'], PDO::PARAM_INT); | |||||
$query->bindValue(':id', (isset($mod['id']) ? $mod['id'] : -1), PDO::PARAM_INT); | |||||
$query->bindValue(':ip', $_SERVER['REMOTE_ADDR']); | $query->bindValue(':ip', $_SERVER['REMOTE_ADDR']); | ||||
$query->bindValue(':time', time(), PDO::PARAM_INT); | $query->bindValue(':time', time(), PDO::PARAM_INT); | ||||
$query->bindValue(':text', $action); | $query->bindValue(':text', $action); | ||||
@@ -698,6 +698,42 @@ function mod_user_log($username, $page_no = 1) { | |||||
mod_page(_('Moderation log'), 'mod/log.html', array('logs' => $logs, 'count' => $count, 'username' => $username)); | mod_page(_('Moderation log'), 'mod/log.html', array('logs' => $logs, 'count' => $count, 'username' => $username)); | ||||
} | } | ||||
function mod_board_log($board, $page_no = 1, $hide_names = false, $public = false) { | |||||
global $config; | |||||
if ($page_no < 1) | |||||
error($config['error']['404']); | |||||
if (!hasPermission($config['mod']['mod_board_log'], $board) && !$public) | |||||
error($config['error']['noaccess']); | |||||
$query = prepare("SELECT `username`, `mod`, `ip`, `board`, `time`, `text` FROM ``modlogs`` LEFT JOIN ``mods`` ON `mod` = ``mods``.`id` WHERE `board` = :board ORDER BY `time` DESC LIMIT :offset, :limit"); | |||||
$query->bindValue(':board', $board); | |||||
$query->bindValue(':limit', $config['mod']['modlog_page'], PDO::PARAM_INT); | |||||
$query->bindValue(':offset', ($page_no - 1) * $config['mod']['modlog_page'], PDO::PARAM_INT); | |||||
$query->execute() or error(db_error($query)); | |||||
$logs = $query->fetchAll(PDO::FETCH_ASSOC); | |||||
if (empty($logs) && $page_no > 1) | |||||
error($config['error']['404']); | |||||
if (!hasPermission($config['mod']['show_ip'])) { | |||||
// Supports ipv4 only! | |||||
foreach ($logs as $i => &$log) { | |||||
$log['text'] = preg_replace_callback('/(?:<a href="\?\/IP\/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}">)?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?:<\/a>)?/', function($matches) { | |||||
return "xxxx";//less_ip($matches[1]); | |||||
}, $log['text']); | |||||
} | |||||
} | |||||
$query = prepare("SELECT COUNT(*) FROM ``modlogs`` LEFT JOIN ``mods`` ON `mod` = ``mods``.`id` WHERE `board` = :board"); | |||||
$query->bindValue(':board', $board); | |||||
$query->execute() or error(db_error($query)); | |||||
$count = $query->fetchColumn(); | |||||
mod_page(_('Board log'), 'mod/log.html', array('logs' => $logs, 'count' => $count, 'board' => $board, 'hide_names' => $hide_names, 'public' => $public)); | |||||
} | |||||
function mod_view_board($boardName, $page_no = 1) { | function mod_view_board($boardName, $page_no = 1) { | ||||
global $config, $mod; | global $config, $mod; | ||||
@@ -65,6 +65,7 @@ CREATE TABLE IF NOT EXISTS `boards` ( | |||||
`uri` varchar(58) CHARACTER SET utf8 NOT NULL, | `uri` varchar(58) CHARACTER SET utf8 NOT NULL, | ||||
`title` tinytext NOT NULL, | `title` tinytext NOT NULL, | ||||
`subtitle` tinytext, | `subtitle` tinytext, | ||||
-- `indexed` boolean default true, | |||||
PRIMARY KEY (`uri`) | PRIMARY KEY (`uri`) | ||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; | ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; | ||||
@@ -0,0 +1,24 @@ | |||||
<?php | |||||
include 'inc/functions.php'; | |||||
include 'inc/mod/pages.php'; | |||||
if (!isset($_GET['board']) || !preg_match("/{$config['board_regex']}/u", $_GET['board'])) { | |||||
http_response_code(400); | |||||
error('Bad board.'); | |||||
} | |||||
if (!openBoard($_GET['board'])) { | |||||
http_response_code(404); | |||||
error('No board.'); | |||||
} | |||||
if ($config['public_logs'] == 0) error('This board has public logs disabled. Ask the board owner to enable it.'); | |||||
if ($config['public_logs'] == 1) $hide_names = false; | |||||
if ($config['public_logs'] == 2) $hide_names = true; | |||||
if (!isset($_GET['page'])) { | |||||
$page = 1; | |||||
} else { | |||||
$page = (int)$_GET['page']; | |||||
}; | |||||
mod_board_log($board['uri'], $page, $hide_names, true); |
@@ -5,13 +5,13 @@ | |||||
*/ | */ | ||||
require_once 'inc/functions.php'; | require_once 'inc/functions.php'; | ||||
require_once 'inc/bans.php'; | |||||
require_once 'inc/mod/pages.php'; | |||||
require_once 'inc/mod/auth.php'; | |||||
if ($config['debug']) | if ($config['debug']) | ||||
$parse_start_time = microtime(true); | $parse_start_time = microtime(true); | ||||
require_once 'inc/bans.php'; | |||||
require_once 'inc/mod/pages.php'; | |||||
check_login(true); | check_login(true); | ||||
$query = isset($_SERVER['QUERY_STRING']) ? rawurldecode($_SERVER['QUERY_STRING']) : ''; | $query = isset($_SERVER['QUERY_STRING']) ? rawurldecode($_SERVER['QUERY_STRING']) : ''; | ||||
@@ -70,9 +70,11 @@ if (isset($_POST['delete'])) { | |||||
if (isset($_POST['file'])) { | if (isset($_POST['file'])) { | ||||
// Delete just the file | // Delete just the file | ||||
deleteFile($id); | deleteFile($id); | ||||
modLog("User deleted file from his own post #$id"); | |||||
} else { | } else { | ||||
// Delete entire post | // Delete entire post | ||||
deletePost($id); | deletePost($id); | ||||
modLog("User deleted his own post #$id"); | |||||
} | } | ||||
_syslog(LOG_INFO, 'Deleted post: ' . | _syslog(LOG_INFO, 'Deleted post: ' . | ||||
@@ -233,7 +235,6 @@ if (isset($_POST['delete'])) { | |||||
checkBan($board['uri']); | checkBan($board['uri']); | ||||
if ($post['mod'] = isset($_POST['mod']) && $_POST['mod']) { | if ($post['mod'] = isset($_POST['mod']) && $_POST['mod']) { | ||||
require 'inc/mod/auth.php'; | |||||
check_login(false); | check_login(false); | ||||
if (!$mod) { | if (!$mod) { | ||||
// Liar. You're not a mod. | // Liar. You're not a mod. | ||||
@@ -945,7 +946,7 @@ if (isset($_POST['delete'])) { | |||||
$build_pages = range(1, $config['max_pages']); | $build_pages = range(1, $config['max_pages']); | ||||
if ($post['op']) | if ($post['op']) | ||||
clean(); | |||||
clean($pid); | |||||
event('post-after', $post); | event('post-after', $post); | ||||
@@ -10,7 +10,15 @@ | |||||
<tr> | <tr> | ||||
<td class="minimal"> | <td class="minimal"> | ||||
{% if log.username %} | {% if log.username %} | ||||
<a href="?/log:{{ log.username|e }}">{{ log.username|e }}</a> | |||||
{% if hide_names %} | |||||
<em>hidden</em> | |||||
{% else %} | |||||
{% if not mod|hasPermission(config.mod.modlog) %} | |||||
<a href="?/new_PM/{{ log.username|e }}">{{ log.username|e }}</a> | |||||
{% else %} | |||||
<a href="?/log:{{ log.username|e }}">{{ log.username|e }}</a> | |||||
{% endif %} | |||||
{% endif %} | |||||
{% elseif log.mod == -1 %} | {% elseif log.mod == -1 %} | ||||
<em>system</em> | <em>system</em> | ||||
{% else %} | {% else %} | ||||
@@ -44,7 +52,11 @@ | |||||
{% if count > logs|count %} | {% if count > logs|count %} | ||||
<p class="unimportant" style="text-align:center;word-wrap:break-word"> | <p class="unimportant" style="text-align:center;word-wrap:break-word"> | ||||
{% for i in range(0, (count - 1) / config.mod.modlog_page) %} | {% for i in range(0, (count - 1) / config.mod.modlog_page) %} | ||||
<a href="?/log{% if username %}:{{ username }}{% endif %}/{{ i + 1 }}">[{{ i + 1 }}]</a> | |||||
{% if public %} | |||||
<a href="?page={{ i + 1 }}&board={{ board|url_encode }}">[{{ i + 1 }}]</a> | |||||
{% else %} | |||||
<a href="?/log{% if username %}:{{ username }}{% elseif board %}:b:{{ board }}{% endif %}/{{ i + 1 }}">[{{ i + 1 }}]</a> | |||||
{% endif %} | |||||
{% endfor %} | {% endfor %} | ||||
</p> | </p> | ||||
{% endif %} | {% endif %} | ||||
@@ -39,7 +39,6 @@ if(!getenv('TINYBOARD_PATH')) { | |||||
putenv('TINYBOARD_PATH=' . getcwd()); | putenv('TINYBOARD_PATH=' . getcwd()); | ||||
require 'inc/functions.php'; | require 'inc/functions.php'; | ||||
require 'inc/mod/auth.php'; | |||||
$mod = Array( | $mod = Array( | ||||
'id' => -1, | 'id' => -1, | ||||