Support blocking keywords

Resolves #122.
This commit is contained in:
Trevor Slocum 2020-11-23 12:44:02 -08:00
parent bce5c8fc30
commit 67483c3774
18 changed files with 810 additions and 165 deletions

View file

@ -20,6 +20,7 @@ See [TinyIB Installations](https://gitlab.com/tslocum/tinyib/wikis/Home) for dem
- Reference links. `>>###`
- Delete posts via password.
- Report posts.
- Block keywords.
- Management panel:
- Administrators and moderators use separate passwords.
- Moderators are only able to sticky threads, lock threads, delete posts, and approve posts when necessary. (See ``TINYIB_REQMOD``)

View file

@ -122,6 +122,13 @@ if (TINYIB_DBMODE == 'pdo' && TINYIB_DBDRIVER == 'pgsql') {
"post" integer NOT NULL,
PRIMARY KEY ("id")
);';
$keywords_sql = 'CREATE TABLE "' . TINYIB_DBKEYWORDS . '" (
"id" bigserial NOT NULL,
"text" varchar(255) NOT NULL,
"action" varchar(255) NOT NULL,
PRIMARY KEY ("id")
);';
} else {
$posts_sql = "CREATE TABLE `" . TINYIB_DBPOSTS . "` (
`id` mediumint(7) unsigned NOT NULL auto_increment,
@ -171,6 +178,13 @@ if (TINYIB_DBMODE == 'pdo' && TINYIB_DBDRIVER == 'pgsql') {
`post` int(20) NOT NULL,
PRIMARY KEY (`id`)
)";
$keywords_sql = "CREATE TABLE `" . TINYIB_DBKEYWORDS . "` (
`id` mediumint(7) unsigned NOT NULL auto_increment,
`text` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`action` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
)";
}
// Check directories are writable by the script
@ -261,6 +275,57 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
if ($rawpost || !in_array('password', $hide_fields)) {
$post['password'] = ($_POST['password'] != '') ? hashData($_POST['password']) : '';
}
$report_post = false;
foreach (array($post['name'], $post['email'], $post['subject'], $post['message']) as $field) {
$keyword = checkKeywords($field);
if (empty($keyword)) {
continue;
}
$expire = -1;
switch ($keyword['action']) {
case 'report':
$report_post = true;
break;
case 'delete':
fancyDie(__('Your post contains a blocked keyword.'));
case 'ban0':
$expire = 0;
break;
case 'ban1h':
$expire = 3600;
break;
case 'ban1d':
$expire = 86400;
break;
case 'ban2d':
$expire = 172800;
break;
case 'ban1w':
$expire = 604800;
break;
case 'ban2w':
$expire = 1209600;
break;
case 'ban1m':
$expire = 2592000;
break;
}
if ($expire >= 0) {
$ban = array();
$ban['ip'] = $post['ip'];
$ban['expire'] = $expire > 0 ? (time() + $expire) : 0;
$ban['reason'] = 'Keyword: ' . $keyword['text'];
insertBan($ban);
$expire_txt = ($ban['expire'] > 0) ? ('<br>This ban will expire ' . strftime(TINYIB_DATEFMT, $ban['expire'])) : '<br>This ban is permanent and will not expire.';
$reason_txt = ($ban['reason'] == '') ? '' : ('<br>Reason: ' . $ban['reason']);
fancyDie('Your IP address ' . $_SERVER['REMOTE_ADDR'] . ' has been banned from posting on this image board. ' . $expire_txt . $reason_txt);
}
break;
}
$post['nameblock'] = nameBlock($post['name'], $post['tripcode'], $post['email'], time(), $rawposttext);
if (isset($_POST['embed']) && trim($_POST['embed']) != '' && ($rawpost || !in_array('embed', $hide_fields))) {
@ -369,6 +434,11 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
$post['id'] = insertPost($post);
if ($report_post) {
$report = array('ip' => $post['ip'], 'post' => $post['id']);
insertReport($report);
}
if ($post['moderated'] == '1') {
if (TINYIB_ALWAYSNOKO || strtolower($post['email']) == 'noko') {
$redirect = 'res/' . ($post['parent'] == TINYIB_NEWTHREAD ? $post['id'] : $post['parent']) . '.html#' . $post['id'];
@ -495,6 +565,40 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
$onload = manageOnLoad('bans');
$text .= manageBanForm();
$text .= manageBansTable();
} elseif (isset($_GET['keywords'])) {
if (isset($_POST['text']) && $_POST['text'] != '') {
if ($_GET['keywords'] > 0) {
deleteKeyword($_GET['keywords']);
}
$keyword_exists = keywordByText($_POST['text']);
if ($keyword_exists) {
fancyDie(__('Sorry, that keyword has already been added.'));
}
$keyword = array();
$keyword['text'] = $_POST['text'];
$keyword['action'] = $_POST['action'];
insertKeyword($keyword);
if ($_GET['keywords'] > 0) {
$text .= manageInfo(__('Keyword updated.'));
$_GET['keywords'] = 0;
} else {
$text .= manageInfo(__('Keyword added.'));
}
} elseif (isset($_GET['deletekeyword'])) {
deleteKeyword($_GET['deletekeyword']);
$text .= manageInfo(__('Keyword deleted.'));
}
$onload = manageOnLoad('keywords');
if ($_GET['keywords'] > 0) {
$text .= manageEditKeyword($_GET['keywords']);
} else {
$text .= manageEditKeyword(0);
$text .= manageKeywordsTable();
}
} else if (isset($_GET['update'])) {
if (is_dir('.git')) {
$git_output = shell_exec('git pull 2>&1');

View file

@ -320,3 +320,50 @@ function deleteReportsByIP($ip) {
$GLOBALS['db']->deleteWhere(REPORTS_FILE, $ipClause);
}
// Keyword functions
function keywordByID($id) {
$clause = new SimpleWhereClause(KEYWORD_ID, '=', $id, INTEGER_COMPARISON);
return convertKeywordsToSQLStyle($GLOBALS['db']->selectWhere(KEYWORDS_FILE, $clause, 1), true);
}
function keywordByText($text) {
$text = strtolower($text);
$clause = new SimpleWhereClause(KEYWORD_TEXT, '=', $text, STRING_COMPARISON);
return convertKeywordsToSQLStyle($GLOBALS['db']->selectWhere(KEYWORDS_FILE, $clause, 1), true);
}
function allKeywords() {
$rows = $GLOBALS['db']->selectWhere(KEYWORDS_FILE, NULL, -1, new OrderBy(KEYWORD_TEXT, ASCENDING, INTEGER_COMPARISON));
return convertKeywordsToSQLStyle($rows);
}
function convertKeywordsToSQLStyle($keywords, $singlekeyword = false) {
$newkeywords = array();
foreach ($keywords as $oldkeyword) {
$keyword = array();
$keyword['id'] = $oldkeyword[KEYWORD_ID];
$keyword['text'] = $oldkeyword[KEYWORD_TEXT];
$keyword['action'] = $oldkeyword[KEYWORD_ACTION];
if ($singlekeyword) {
return $keyword;
}
$newkeywords[] = $keyword;
}
return $newkeywords;
}
function insertKeyword($newkeyword) {
$newkeyword['text'] = strtolower($newkeyword['text']);
$keyword = array();
$keyword[KEYWORD_ID] = '0';
$keyword[KEYWORD_TEXT] = $newkeyword['text'];
$keyword[KEYWORD_ACTION] = $newkeyword['action'];
$GLOBALS['db']->insertWithAutoId(KEYWORDS_FILE, KEYWORD_ID, $keyword);
}
function deleteKeyword($id) {
$GLOBALS['db']->deleteWhere(KEYWORDS_FILE, new SimpleWhereClause(KEYWORD_ID, '=', $id, INTEGER_COMPARISON));
}

View file

@ -45,6 +45,12 @@ define('REPORT_ID', 0);
define('REPORT_IP', 1);
define('REPORT_POST', 2);
// Keywords table
define('KEYWORDS_FILE', '.keywords');
define('KEYWORD_ID', 0);
define('KEYWORD_TEXT', 1);
define('KEYWORD_ACTION', 2);
require_once 'flatfile/flatfile.php';
$db = new Flatfile();
$db->datadir = 'inc/database/flatfile/';
@ -101,4 +107,12 @@ if (function_exists('insertPost')) {
$report[REPORT_POST] = $newreport['post'];
$GLOBALS['db']->insertWithAutoId(REPORTS_FILE, REPORT_ID, $report);
}
function migrateKeyword($newkeyword) {
$keyword = array();
$keyword[KEYWORD_ID] = $newkeyword['id'];
$keyword[KEYWORD_TEXT] = $newkeyword['text'];
$keyword[KEYWORD_ACTION] = $newkeyword['action'];
$GLOBALS['db']->insertWithAutoId(KEYWORDS_FILE, KEYWORD_ID, $keyword);
}
}

View file

@ -221,3 +221,44 @@ function deleteReportsByPost($post) {
function deleteReportsByIP($ip) {
mysql_query("DELETE FROM `" . TINYIB_DBREPORTS . "` WHERE `ip` = " . mysql_real_escape_string($ip) . " OR `ip` = " . mysql_real_escape_string(hashData($ip)));
}
// Keyword functions
function keywordByID($id) {
$result = mysql_query("SELECT * FROM `" . TINYIB_DBKEYWORDS . "` WHERE `id` = '" . mysql_real_escape_string($id) . "' LIMIT 1");
if ($result) {
while ($keyword = mysql_fetch_assoc($result)) {
return $keyword;
}
}
}
function keywordByText($text) {
$text = strtolower($text);
$result = mysql_query("SELECT * FROM `" . TINYIB_DBKEYWORDS . "` WHERE `text` = '" . mysql_real_escape_string($text) . "'");
if ($result) {
while ($keyword = mysql_fetch_assoc($result)) {
return $keyword;
}
}
return array();
}
function allKeywords() {
$keywords = array();
$result = mysql_query("SELECT * FROM `" . TINYIB_DBKEYWORDS . "` ORDER BY `text` ASC");
if ($result) {
while ($keyword = mysql_fetch_assoc($result)) {
$keywords[] = $keyword;
}
}
return $keywords;
}
function insertKeyword($keyword) {
$keyword['text'] = strtolower($keyword['text']);
mysql_query("INSERT INTO `" . TINYIB_DBKEYWORDS . "` (`text`, `action`) VALUES ('" . mysql_real_escape_string($keyword['text']) . "', '" . mysql_real_escape_string($keyword['action']) . "')");
}
function deleteKeyword($id) {
mysql_query("DELETE FROM `" . TINYIB_DBKEYWORDS . "` WHERE `id` = " . mysql_real_escape_string($id));
}

View file

@ -32,6 +32,11 @@ if (mysql_num_rows(mysql_query("SHOW TABLES LIKE '" . TINYIB_DBREPORTS . "'")) =
mysql_query($reports_sql);
}
// Create the keywords table if it does not exist
if (mysql_num_rows(mysql_query("SHOW TABLES LIKE '" . TINYIB_DBKEYWORDS . "'")) == 0) {
mysql_query($keywords_sql);
}
if (mysql_num_rows(mysql_query("SHOW COLUMNS FROM `" . TINYIB_DBPOSTS . "` LIKE 'stickied'")) == 0) {
mysql_query("ALTER TABLE `" . TINYIB_DBPOSTS . "` ADD COLUMN stickied TINYINT(1) NOT NULL DEFAULT '0'");
}
@ -55,4 +60,8 @@ if (function_exists('insertPost')) {
function migrateReport($report) {
mysql_query("INSERT INTO " . TINYIB_DBREPORTS . " (id, ip, post) VALUES ('" . mysql_real_escape_string($report['id']) . "', '" . mysql_real_escape_string($report['ip']) . "', '" . mysql_real_escape_string($report['post']) . "')");
}
function migrateKeyword($keyword) {
mysql_query("INSERT INTO " . TINYIB_DBKEYWORDS . " (id, text, action) VALUES ('" . mysql_real_escape_string($keyword['id']) . "', '" . mysql_real_escape_string($keyword['text']) . "', '" . mysql_real_escape_string($keyword['action']) . "')");
}
}

View file

@ -251,6 +251,53 @@ function deleteReportsByIP($ip) {
mysqli_query($link, "DELETE FROM `" . TINYIB_DBREPORTS . "` WHERE `ip` = '" . mysqli_real_escape_string($link, $ip) . "' OR `ip` = '" . mysqli_real_escape_string($link, hashData($ip)) . "'");
}
// Keyword functions
function keywordByID($id) {
global $link;
$result = mysqli_query($link, "SELECT * FROM `" . TINYIB_DBKEYWORDS . "` WHERE `id` = '" . mysqli_real_escape_string($link, $id) . "' LIMIT 1");
if ($result) {
while ($keyword = mysqli_fetch_assoc($result)) {
return $keyword;
}
}
return array();
}
function keywordByText($text) {
global $link;
$text = strtolower($text);
$result = mysqli_query($link, "SELECT * FROM `" . TINYIB_DBKEYWORDS . "` WHERE `text` = '" . mysqli_real_escape_string($link, $text) . "'");
if ($result) {
while ($keyword = mysqli_fetch_assoc($result)) {
return $keyword;
}
}
return array();
}
function allKeywords() {
global $link;
$keywords = array();
$result = mysqli_query($link, "SELECT * FROM `" . TINYIB_DBKEYWORDS . "` ORDER BY `text` ASC");
if ($result) {
while ($keyword = mysqli_fetch_assoc($result)) {
$keywords[] = $keyword;
}
}
return $keywords;
}
function insertKeyword($keyword) {
global $link;
$keyword['text'] = strtolower($keyword['text']);
mysqli_query($link, "INSERT INTO `" . TINYIB_DBKEYWORDS . "` (`text`, `action`) VALUES ('" . mysqli_real_escape_string($link, $keyword['text']) . "', '" . mysqli_real_escape_string($link, $keyword['action']) . "')");
}
function deleteKeyword($id) {
global $link;
mysqli_query($link, "DELETE FROM `" . TINYIB_DBKEYWORDS . "` WHERE `id` = '" . mysqli_real_escape_string($link, $id) . "'");
}
// Utility functions
function mysqli_result($res, $row, $field = 0) {
$res->data_seek($row);

View file

@ -32,6 +32,11 @@ if (mysqli_num_rows(mysqli_query($link, "SHOW TABLES LIKE '" . TINYIB_DBREPORTS
mysqli_query($link, $reports_sql);
}
// Create the keywords table if it does not exist
if (mysqli_num_rows(mysqli_query($link, "SHOW TABLES LIKE '" . TINYIB_DBKEYWORDS . "'")) == 0) {
mysqli_query($link, $keywords_sql);
}
if (mysqli_num_rows(mysqli_query($link, "SHOW COLUMNS FROM `" . TINYIB_DBPOSTS . "` LIKE 'stickied'")) == 0) {
mysqli_query($link, "ALTER TABLE `" . TINYIB_DBPOSTS . "` ADD COLUMN stickied TINYINT(1) NOT NULL DEFAULT '0'");
}
@ -58,4 +63,9 @@ if (function_exists('insertPost')) {
global $link;
sqlite_query($GLOBALS["db"], "INSERT INTO " . TINYIB_DBREPORTS . " (id, ip, post) VALUES ('" . mysqli_real_escape_string($link, $report['id']) . "', '" . mysqli_real_escape_string($link, $report['ip']) . "', '" . mysqli_real_escape_string($link, $report['post']) . "')");
}
function migrateKeyword($keyword) {
global $link;
sqlite_query($GLOBALS["db"], "INSERT INTO " . TINYIB_DBKEYWORDS . " (id, text, action) VALUES ('" . mysqli_real_escape_string($link, $keyword['id']) . "', '" . mysqli_real_escape_string($link, $keyword['text']) . "', '" . mysqli_real_escape_string($link, $keyword['action']) . "')");
}
}

View file

@ -206,3 +206,39 @@ function deleteReportsByPost($post) {
function deleteReportsByIP($ip) {
pdoQuery("DELETE FROM " . TINYIB_DBREPORTS . " WHERE ip = ? OR ip = ?", array($ip, hashData($ip)));
}
// Keyword functions
function keywordByID($id) {
$result = pdoQuery("SELECT * FROM " . TINYIB_DBKEYWORDS . " WHERE id = ? LIMIT 1", array($id));
return $result->fetch(PDO::FETCH_ASSOC);
}
function keywordByText($text) {
$text = strtolower($text);
$keywords = array();
$results = pdoQuery("SELECT * FROM " . TINYIB_DBKEYWORDS . " WHERE text = ?", array($text));
while ($row = $results->fetch(PDO::FETCH_ASSOC)) {
$keywords[] = $row;
}
return $keywords;
}
function allKeywords() {
$keywords = array();
$results = pdoQuery("SELECT * FROM " . TINYIB_DBKEYWORDS . " ORDER BY text ASC");
while ($row = $results->fetch(PDO::FETCH_ASSOC)) {
$keywords[] = $row;
}
return $keywords;
}
function insertKeyword($keyword) {
global $dbh;
$keyword['text'] = strtolower($keyword['text']);
$stm = $dbh->prepare("INSERT INTO " . TINYIB_DBKEYWORDS . " (text, action) VALUES (?, ?)");
$stm->execute(array($keyword['text'], $keyword['action']));
}
function deleteKeyword($id) {
pdoQuery("DELETE FROM " . TINYIB_DBKEYWORDS . " WHERE id = ?", array($id));
}

View file

@ -64,6 +64,18 @@ if (!$reports_exists) {
$dbh->exec($reports_sql);
}
// Create the keywords table if it does not exist
if (TINYIB_DBDRIVER === 'pgsql') {
$query = "SELECT COUNT(*) FROM pg_catalog.pg_tables WHERE tablename LIKE " . $dbh->quote(TINYIB_DBKEYWORDS);
$keywords_exists = $dbh->query($query)->fetchColumn() != 0;
} else {
$dbh->query("SHOW TABLES LIKE " . $dbh->quote(TINYIB_DBKEYWORDS));
$keywords_exists = $dbh->query("SELECT FOUND_ROWS()")->fetchColumn() != 0;
}
if (!$keywords_exists) {
$dbh->exec($keywords_sql);
}
if (TINYIB_DBDRIVER === 'pgsql') {
$query = "SELECT column_name FROM information_schema.columns WHERE table_name='" . TINYIB_DBPOSTS . "' and column_name='moderated'";
$moderated_exists = $dbh->query($query)->fetchColumn() != 0;
@ -142,4 +154,10 @@ if (function_exists('insertPost')) {
$stm = $dbh->prepare("INSERT INTO " . TINYIB_DBREPORTS . " (id, ip, post) VALUES (?, ?, ?)");
$stm->execute(array($report['id'], $report['ip'], $report['post']));
}
function migrateKeyword($keyword) {
global $dbh;
$stm = $dbh->prepare("INSERT INTO " . TINYIB_DBKEYWORDS . " (id, text, action) VALUES (?, ?, ?)");
$stm->execute(array($keyword['id'], $keyword['text'], $keyword['action']));
}
}

View file

@ -192,3 +192,39 @@ function deleteReportsByPost($post) {
function deleteReportsByIP($ip) {
sqlite_query($GLOBALS["db"], "DELETE FROM " . TINYIB_DBREPORTS . " WHERE ip = '" . sqlite_escape_string($ip) . "' OR ip = '" . sqlite_escape_string(hashData($ip)) . "'");
}
// Keyword functions
function keywordByID($id) {
$result = sqlite_fetch_all(sqlite_query($GLOBALS["db"], "SELECT * FROM " . TINYIB_DBKEYWORDS . " WHERE id = '" . sqlite_escape_string($id) . "' LIMIT 1"), SQLITE_ASSOC);
foreach ($result as $keyword) {
return $keyword;
}
return array();
}
function keywordByText($text) {
$text = strtolower($text);
$result = sqlite_fetch_all(sqlite_query($GLOBALS["db"], "SELECT * FROM " . TINYIB_DBKEYWORDS . " WHERE text = '" . sqlite_escape_string($text) . "'"), SQLITE_ASSOC);
foreach ($result as $keyword) {
return $keyword;
}
return array();
}
function allKeywords() {
$keywords = array();
$result = sqlite_fetch_all(sqlite_query($GLOBALS["db"], "SELECT * FROM " . TINYIB_DBKEYWORDS . " ORDER BY text ASC"), SQLITE_ASSOC);
foreach ($result as $keyword) {
$keywords[] = $keyword;
}
return $keywords;
}
function insertKeyword($keyword) {
$keyword['text'] = strtolower($keyword['text']);
sqlite_query($GLOBALS["db"], "INSERT INTO " . TINYIB_DBKEYWORDS . " (text, action) VALUES ('" . sqlite_escape_string($keyword['text']) . "', '" . sqlite_escape_string($keyword['action']) . "')");
}
function deleteKeyword($id) {
sqlite_query($GLOBALS["db"], "DELETE FROM " . TINYIB_DBKEYWORDS . " WHERE id = " . sqlite_escape_string($id));
}

View file

@ -221,3 +221,44 @@ function deleteReportsByIP($ip) {
global $db;
$db->exec("DELETE FROM " . TINYIB_DBREPORTS . " WHERE ip = '" . $db->escapeString($ip) . "' OR ip = '" . $db->escapeString(hashData($ip)) . "'");
}
// Keyword functions
function keywordByID($id) {
global $db;
$result = $db->query("SELECT * FROM " . TINYIB_DBKEYWORDS . " WHERE id = '" . $db->escapeString($id) . "' LIMIT 1");
while ($keyword = $result->fetchArray()) {
return $keyword;
}
return array();
}
function keywordByText($text) {
global $db;
$text = strtolower($text);
$result = $db->query("SELECT * FROM " . TINYIB_DBKEYWORDS . " WHERE text = '" . $db->escapeString($text) . "'");
while ($keyword = $result->fetchArray()) {
return $keyword;
}
return array();
}
function allKeywords() {
global $db;
$keywords = array();
$result = $db->query("SELECT * FROM " . TINYIB_DBKEYWORDS . " ORDER BY text ASC");
while ($keyword = $result->fetchArray()) {
$keywords[] = $keyword;
}
return $keywords;
}
function insertKeyword($keyword) {
global $db;
$keyword['text'] = strtolower($keyword['text']);
$db->exec("INSERT INTO " . TINYIB_DBKEYWORDS . " (text, action) VALUES ('" . $db->escapeString($keyword['text']) . "', '" . $db->escapeString($keyword['action']) . "')");
}
function deleteKeyword($id) {
global $db;
$db->exec("DELETE FROM " . TINYIB_DBKEYWORDS . " WHERE id = " . $db->escapeString($id));
}

View file

@ -66,6 +66,16 @@ if (!$result->fetchArray()) {
)");
}
// Create the keywords table if it does not exist
$result = $db->query("SELECT name FROM sqlite_master WHERE type='table' AND name='" . TINYIB_DBKEYWORDS . "'");
if (!$result->fetchArray()) {
$db->exec("CREATE TABLE " . TINYIB_DBKEYWORDS . " (
id INTEGER PRIMARY KEY,
text TEXT NOT NULL,
action TEXT NOT NULL
)");
}
// Add moderated column if it isn't present
@$db->exec("ALTER TABLE " . TINYIB_DBPOSTS . " ADD COLUMN moderated INTEGER NOT NULL DEFAULT '0'");
@ -93,4 +103,9 @@ if (function_exists('insertPost')) {
global $db;
$db->exec("INSERT INTO " . TINYIB_DBREPORTS . " (id, ip, post) VALUES ('" . $db->escapeString($report['id']) . "', '" . $db->escapeString($report['ip']) . "', '" . $db->escapeString($report['post']) . "')");
}
function migrateKeyword($keyword) {
global $db;
$db->exec("INSERT INTO " . TINYIB_DBKEYWORDS . " (id, text, action) VALUES ('" . $db->escapeString($keyword['id']) . "', '" . $db->escapeString($keyword['text']) . "', '" . $db->escapeString($keyword['action']) . "')");
}
}

View file

@ -65,6 +65,16 @@ if (sqlite_num_rows($result) == 0) {
)");
}
// Create the keywords table if it does not exist
$result = sqlite_query($db, "SELECT name FROM sqlite_master WHERE type='table' AND name='" . TINYIB_DBKEYWORDS . "'");
if (sqlite_num_rows($result) == 0) {
sqlite_query($db, "CREATE TABLE " . TINYIB_DBKEYWORDS . " (
id INTEGER PRIMARY KEY,
text TEXT NOT NULL,
action TEXT NOT NULL
)");
}
// Add moderated column if it isn't present
sqlite_query($db, "ALTER TABLE " . TINYIB_DBPOSTS . " ADD COLUMN moderated INTEGER NOT NULL DEFAULT '0'");
@ -89,4 +99,8 @@ if (function_exists('insertPost')) {
function migrateReport($report) {
sqlite_query($GLOBALS["db"], "INSERT INTO " . TINYIB_DBREPORTS . " (id, ip, post) VALUES ('" . sqlite_escape_string($report['id']) . "', '" . sqlite_escape_string($report['ip']) . "', '" . sqlite_escape_string($report['post']) . "')");
}
function migrateKeyword($keyword) {
sqlite_query($GLOBALS["db"], "INSERT INTO " . TINYIB_DBKEYWORDS . " (id, text, action) VALUES ('" . sqlite_escape_string($keyword['id']) . "', '" . sqlite_escape_string($keyword['text']) . "', '" . sqlite_escape_string($keyword['action']) . "')");
}
}

View file

@ -285,6 +285,16 @@ function checkBanned() {
}
}
function checkKeywords($text) {
$keywords = allKeywords();
foreach ($keywords as $keyword) {
if (stripos($text, $keyword['text']) !== false) {
return $keyword;
}
}
return array();
}
function checkFlood() {
if (TINYIB_DELAY > 0) {
$lastpost = lastPostByIP();

View file

@ -716,6 +716,7 @@ function adminBar() {
$output = '[<a href="?manage">' . __('Status') . '</a>] [';
if ($isadmin) {
$output .= '<a href="?manage&bans">' . __('Bans') . '</a>] [';
$output .= '<a href="?manage&keywords">' . __('Keywords') . '</a>] [';
}
$output .= '<a href="?manage&moderate">' . __('Moderate Post') . '</a>] [<a href="?manage&rawpost">' . __('Raw Post') . '</a>] [';
if ($isadmin) {
@ -757,6 +758,8 @@ function manageOnLoad($page) {
return ' onload="document.tinyib.managepassword.focus();"';
case 'moderate':
return ' onload="document.tinyib.moderate.focus();"';
case 'keywords':
return ' onload="document.tinyib.text.focus();"';
case 'rawpost':
return ' onload="document.tinyib.message.focus();"';
case 'bans':
@ -999,6 +1002,95 @@ EOF;
EOF;
}
function manageEditKeyword($id) {
$id = intval($id);
$v_text = '';
$v_action = '';
if ($id > 0) {
$keyword = keywordByID($id);
if (empty($keyword)) {
fancyDie(__("Sorry, there doesn't appear to be a keyword with that ID."));
}
$v_text = htmlentities($keyword['text'], ENT_QUOTES);
$v_action = $keyword['action'];
}
$txt_keyword = __('Keyword');
$txt_keywords = __('Keywords');
$txt_action = __('Action:');
$txt_submit = $id > 0 ? __('Update') : __('Add');
$return = <<<EOF
<form id="tinyib" name="tinyib" method="post" action="?manage&keywords=$id">
<fieldset>
<legend>$txt_keywords</legend>
<div valign="top"><label for="keyword">$txt_keyword</label> <input type="text" name="text" id="text" value="$v_text"><br>
<label for="action">$txt_action</label>
<select name="action">
EOF;
if (TINYIB_REPORT) {
$return .= '<option value="report"' . ($v_action == 'report' ? ' selected' : '') . '>' . __('Report') . '</option>';
}
$return .= '<option value="delete"' . ($v_action == 'delete' ? ' selected' : '') . '>' . __('Delete') . '</option>';
$return .= '<option value="ban1h"' . ($v_action == 'ban1h' ? ' selected' : '') . '>' . __('Delete and ban for 1 hour') . '</option>';
$return .= '<option value="ban1d"' . ($v_action == 'ban1d' ? ' selected' : '') . '>' . __('Delete and ban for 1 day') . '</option>';
$return .= '<option value="ban2d"' . ($v_action == 'ban2d' ? ' selected' : '') . '>' . __('Delete and ban for 2 days') . '</option>';
$return .= '<option value="ban1w"' . ($v_action == 'ban1w' ? ' selected' : '') . '>' . __('Delete and ban for 1 week') . '</option>';
$return .= '<option value="ban2w"' . ($v_action == 'ban2w' ? ' selected' : '') . '>' . __('Delete and ban for 2 weeks') . '</option>';
$return .= '<option value="ban1m"' . ($v_action == 'ban1m' ? ' selected' : '') . '>' . __('Delete and ban for 1 month') . '</option>';
$return .= '<option value="ban0"' . ($v_action == 'ban0' ? ' selected' : '') . '>' . __('Delete and ban permanently') . '</option>';
return $return . <<<EOF
</select><br><br>
<input type="submit" value="$txt_submit" class="managebutton"></div>
</fieldset>
</form><br>
EOF;
}
function manageKeywordsTable() {
$text = '';
$keywords = allKeywords();
if (count($keywords) > 0) {
$text .= '<table border="1"><tr><th>' . __('Keyword') . '</th><th>' . __('Action') . '</th><th>&nbsp;</th></tr>';
foreach ($keywords as $keyword) {
$action = '';
switch ($keyword['action']) {
case 'report':
$action = __('Report');
break;
case 'delete':
$action = __('Delete');
break;
case 'ban0':
$action = __('Delete and ban permanently');
break;
case 'ban1h':
$action = __('Delete and ban for 1 hour');
break;
case 'ban1d':
$action = __('Delete and ban for 1 day');
break;
case 'ban2d':
$action = __('Delete and ban for 2 days');
break;
case 'ban1w':
$action = __('Delete and ban for 1 week');
break;
case 'ban2w':
$action = __('Delete and ban for 2 weeks');
break;
case 'ban1m':
$action = __('Delete and ban for 1 month');
break;
}
$text .= '<tr><td>' . htmlentities($keyword['text']) . '</td><td>' . $action . '</td><td><a href="?manage&keywords=' . $keyword['id'] . '">' . __('Edit') . '</a> <a href="?manage&keywords&deletekeyword=' . $keyword['id'] . '">' . __('Delete') . '</a></td></tr>';
}
$text .= '</table>';
}
return $text;
}
function manageStatus() {
global $isadmin;
$threads = countThreads();
@ -1007,7 +1099,7 @@ function manageStatus() {
$info = $threads . ' ' . plural($threads, __('thread'), __('threads'));
if (TINYIB_REPORT) {
$info .= ', ' . count($reports). ' ' . plural(count($reports), __('report'), __('reports'));
$info .= ', ' . count($reports) . ' ' . plural(count($reports), __('report'), __('reports'));
}
$info .= ', ' . $bans . ' ' . plural($bans, __('ban'), __('bans'));

View file

@ -1,8 +1,8 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2020-10-22 09:12-0700\n"
"PO-Revision-Date: 2020-10-22 09:12-0700\n"
"POT-Creation-Date: 2020-11-23 12:37-0800\n"
"PO-Revision-Date: 2020-11-23 12:37-0800\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: en\n"
@ -17,254 +17,290 @@ msgstr ""
"X-Poedit-SearchPath-1: inc/functions.php\n"
"X-Poedit-SearchPath-2: inc/html.php\n"
#: imgboard.php:60
#: imgboard.php:46
msgid "Click here to go back"
msgstr ""
#: imgboard.php:84
msgid "TINYIB_TRIPSEED and TINYIB_ADMINPASS must be configured."
msgstr ""
#: imgboard.php:88
msgid "TINYIB_RECAPTCHA_SITE and TINYIB_RECAPTCHA_SECRET must be configured."
msgstr ""
#: imgboard.php:93 imgboard.php:501
#: imgboard.php:72 imgboard.php:614
msgid "Unknown database mode specified."
msgstr ""
#: imgboard.php:190
#: imgboard.php:183
#, php-format
msgid "Directory '%s' can not be written to. Please modify its permissions."
msgstr ""
#: imgboard.php:207
#: imgboard.php:193
msgid "TINYIB_TRIPSEED and TINYIB_ADMINPASS must be configured."
msgstr ""
#: imgboard.php:197
msgid "TINYIB_RECAPTCHA_SITE and TINYIB_RECAPTCHA_SECRET must be configured."
msgstr ""
#: imgboard.php:210
msgid "Posting is currently disabled.<br>Please try again in a few moments."
msgstr ""
#: imgboard.php:226 inc/functions.php:300
#: imgboard.php:229 inc/functions.php:346
msgid "Invalid parent thread ID supplied, unable to create post."
msgstr ""
#: imgboard.php:228
#: imgboard.php:231
msgid "Replies are not allowed to locked threads."
msgstr ""
#: imgboard.php:265
#: imgboard.php:278
msgid "Your post contains a blocked keyword."
msgstr ""
#: imgboard.php:319
msgid "Embedding a URL and uploading a file at the same time is not supported."
msgstr ""
#: imgboard.php:271
#: imgboard.php:325
#, php-format
msgid "Invalid embed URL. Only %s URLs are supported."
msgstr ""
#: imgboard.php:275 inc/functions.php:326 inc/functions.php:566
#: imgboard.php:329 inc/functions.php:372 inc/functions.php:612
#, php-format
msgid "That file is larger than %s."
msgstr ""
#: imgboard.php:280 imgboard.php:286
#: imgboard.php:334 imgboard.php:340
msgid "Failed to download file at specified URL."
msgstr ""
#: imgboard.php:308
#: imgboard.php:362
msgid "Error while processing audio/video."
msgstr ""
#: imgboard.php:315 inc/functions.php:651 inc/functions.php:662
#: imgboard.php:369 inc/functions.php:697 inc/functions.php:708
msgid "Could not create thumbnail."
msgstr ""
#: imgboard.php:338
#: imgboard.php:392
msgid "upload a file or embed a URL"
msgstr ""
#: imgboard.php:340
#: imgboard.php:394
msgid "upload a file"
msgstr ""
#: imgboard.php:342
#: imgboard.php:396
msgid "embed a URL"
msgstr ""
#: imgboard.php:345
#: imgboard.php:399
#, php-format
msgid "Please %s to start a new thread."
msgstr ""
#: imgboard.php:351
#: imgboard.php:405
#, php-format
msgid "Please enter a message and/or %s."
msgstr ""
#: imgboard.php:353
#: imgboard.php:407
msgid "Please enter a message."
msgstr ""
#: imgboard.php:355
#: imgboard.php:409
#, php-format
msgid "Please %s."
msgstr ""
#: imgboard.php:358
#: imgboard.php:412
#, php-format
msgid "%s uploaded."
msgstr ""
#: imgboard.php:363
#: imgboard.php:417
#, php-format
msgid "Your %s will be shown <b>once it has been approved</b>."
msgstr ""
#: imgboard.php:376
#: imgboard.php:435
msgid "Updating thread..."
msgstr ""
#: imgboard.php:389
#: imgboard.php:448
msgid "Updating index..."
msgstr ""
#: imgboard.php:395
msgid "Tick the box next to a post and click \"Delete\" to delete it."
#: imgboard.php:454
msgid "Reporting is disabled."
msgstr ""
#: imgboard.php:399
msgid ""
"Post deletion is currently disabled.<br>Please try again in a few moments."
msgstr ""
#: imgboard.php:416
msgid "Post deleted."
msgstr ""
#: imgboard.php:418
msgid "Invalid password."
msgstr ""
#: imgboard.php:421
#: imgboard.php:459 imgboard.php:500
msgid ""
"Sorry, an invalid post identifier was sent. Please go back, refresh the "
"page, and try again."
msgstr ""
#: imgboard.php:445
#: imgboard.php:464
msgid "You have already submitted a report for that post."
msgstr ""
#: imgboard.php:470
msgid "Post reported."
msgstr ""
#: imgboard.php:474
msgid "Tick the box next to a post and click \"Delete\" to delete it."
msgstr ""
#: imgboard.php:478
msgid ""
"Post deletion is currently disabled.<br>Please try again in a few moments."
msgstr ""
#: imgboard.php:495
msgid "Post deleted."
msgstr ""
#: imgboard.php:497 inc/functions.php:326
msgid "Invalid password."
msgstr ""
#: imgboard.php:524
msgid "Rebuilt board."
msgstr ""
#: imgboard.php:453
#: imgboard.php:532
msgid "Sorry, there is already a ban on record for that IP address."
msgstr ""
#: imgboard.php:462
#: imgboard.php:541
#, php-format
msgid "Ban record added for %s"
msgstr ""
#: imgboard.php:468
#: imgboard.php:547
#, php-format
msgid "Ban record lifted for %s"
msgstr ""
#: imgboard.php:536
#: imgboard.php:562
msgid "Sorry, that keyword has already been added."
msgstr ""
#: imgboard.php:571
msgid "Keyword updated."
msgstr ""
#: imgboard.php:574
msgid "Keyword added."
msgstr ""
#: imgboard.php:578
msgid "Keyword deleted."
msgstr ""
#: imgboard.php:650
#, php-format
msgid "Post No.%d deleted."
msgstr ""
#: imgboard.php:538 imgboard.php:554 imgboard.php:563 imgboard.php:578
#: imgboard.php:592
#: imgboard.php:652 imgboard.php:668 imgboard.php:677 imgboard.php:692
#: imgboard.php:706 imgboard.php:719
msgid "Sorry, there doesn't appear to be a post with that ID."
msgstr ""
#: imgboard.php:552
#: imgboard.php:666
#, php-format
msgid "Post No.%d approved."
msgstr ""
#: imgboard.php:581 imgboard.php:595
#: imgboard.php:695 imgboard.php:709
msgid "Form data was lost. Please go back and try again."
msgstr ""
#: inc/functions.php:127 inc/html.php:1055
#: imgboard.php:717
msgid "Reports cleared."
msgstr ""
#: inc/functions.php:135 inc/html.php:1217
msgid "Anonymous"
msgstr ""
#: inc/functions.php:236
#: inc/functions.php:268
msgid "Please enter the CAPTCHA text."
msgstr ""
#: inc/functions.php:238
#: inc/functions.php:270
msgid ""
"Incorrect CAPTCHA text entered. Please try again.<br>Click the image to "
"retrieve a new CAPTCHA."
msgstr ""
#: inc/functions.php:269
#: inc/functions.php:311
#, php-format
msgid ""
"Please shorten your message, or post it in multiple parts. Your message is "
"%1$d characters long, and the maximum allowed is %2$d."
msgstr ""
#: inc/functions.php:329
#: inc/functions.php:375
#, php-format
msgid ""
"The uploaded file exceeds the upload_max_filesize directive (%s) in php.ini."
msgstr ""
#: inc/functions.php:332
#: inc/functions.php:378
msgid "The uploaded file was only partially uploaded."
msgstr ""
#: inc/functions.php:335
#: inc/functions.php:381
msgid "No file was uploaded."
msgstr ""
#: inc/functions.php:338
#: inc/functions.php:384
msgid "Missing a temporary folder."
msgstr ""
#: inc/functions.php:341
#: inc/functions.php:387
msgid "Failed to write file to disk"
msgstr ""
#: inc/functions.php:344
#: inc/functions.php:390
msgid "Unable to save the uploaded file."
msgstr ""
#: inc/functions.php:352
#: inc/functions.php:398
#, php-format
msgid ""
"Duplicate file uploaded. That file has already been posted <a href=\"%s"
"\">here</a>."
msgstr ""
#: inc/functions.php:383
#: inc/functions.php:429
msgid ""
"Unable to read the uploaded file while creating its thumbnail. A common "
"cause for this is an incorrect extension when the file is actually of a "
"different type."
msgstr ""
#: inc/functions.php:560
#: inc/functions.php:606
msgid "File transfer failure. Please retry the submission."
msgstr ""
#: inc/functions.php:582
#: inc/functions.php:628
msgid ""
"Failed to read the MIME type and size of the uploaded file. Please retry the "
"submission."
msgstr ""
#: inc/functions.php:596 inc/functions.php:601
#: inc/functions.php:642 inc/functions.php:647
msgid "Could not copy uploaded file."
msgstr ""
#: inc/functions.php:607
#: inc/functions.php:653
msgid "File transfer failure. Please go back and try again."
msgstr ""
#: inc/functions.php:626
#: inc/functions.php:672
msgid "Sorry, your video appears to be corrupt."
msgstr ""
@ -278,7 +314,7 @@ msgstr ""
msgid "Supported file types are %1$s and %2$s."
msgstr ""
#: inc/html.php:77 inc/html.php:781 inc/html.php:819
#: inc/html.php:77 inc/html.php:820 inc/html.php:858
msgid "Submit"
msgstr ""
@ -300,7 +336,7 @@ msgstr ""
msgid "Line-breaks must be specified with \"&lt;br&gt;\"."
msgstr ""
#: inc/html.php:149
#: inc/html.php:149 inc/html.php:795
msgid "(enter the text below)"
msgstr ""
@ -359,7 +395,7 @@ msgstr ""
msgid "Message"
msgstr ""
#: inc/html.php:298 inc/html.php:564
#: inc/html.php:298 inc/html.php:570
msgid "Password"
msgstr ""
@ -367,326 +403,399 @@ msgstr ""
msgid "(for post and file deletion)"
msgstr ""
#: inc/html.php:356
#: inc/html.php:350 inc/html.php:1033 inc/html.php:1060
msgid "Report"
msgstr ""
#: inc/html.php:362
msgid "Stickied"
msgstr ""
#: inc/html.php:360
#: inc/html.php:366
msgid "Locked"
msgstr ""
#: inc/html.php:373
#: inc/html.php:379
msgid "Embed:"
msgstr ""
#: inc/html.php:373
#: inc/html.php:379
msgid "File:"
msgstr ""
#: inc/html.php:470
#: inc/html.php:476
msgid "Reply"
msgstr ""
#: inc/html.php:476
#: inc/html.php:482
msgid "Post truncated. Click Reply to view."
msgstr ""
#: inc/html.php:487
#: inc/html.php:493
msgid "1 post omitted. Click Reply to view."
msgstr ""
#: inc/html.php:489
#: inc/html.php:495
#, php-format
msgid "%d posts omitted. Click Reply to view."
msgstr ""
#: inc/html.php:505 inc/html.php:540 inc/html.php:552
#: inc/html.php:511 inc/html.php:546 inc/html.php:558
msgid "Catalog"
msgstr ""
#: inc/html.php:515
#: inc/html.php:521
msgid "Previous"
msgstr ""
#: inc/html.php:528
#: inc/html.php:534
msgid "Next"
msgstr ""
#: inc/html.php:552 inc/html.php:554 inc/html.php:701
#: inc/html.php:558 inc/html.php:560 inc/html.php:711
msgid "Return"
msgstr ""
#: inc/html.php:554
#: inc/html.php:560
msgid "Posting mode: Reply"
msgstr ""
#: inc/html.php:562
#: inc/html.php:568
msgid "Manage"
msgstr ""
#: inc/html.php:563
#: inc/html.php:569
msgid "Style"
msgstr ""
#: inc/html.php:565 inc/html.php:979
#: inc/html.php:571 inc/html.php:1035 inc/html.php:1063 inc/html.php:1087
#: inc/html.php:1132
msgid "Delete"
msgstr ""
#: inc/html.php:566
#: inc/html.php:572
msgid "Delete Post"
msgstr ""
#: inc/html.php:706 inc/html.php:1006
#: inc/html.php:716 inc/html.php:1172
msgid "Status"
msgstr ""
#: inc/html.php:708
#: inc/html.php:718
msgid "Bans"
msgstr ""
#: inc/html.php:710
#: inc/html.php:719 inc/html.php:1020
msgid "Keywords"
msgstr ""
#: inc/html.php:721
msgid "Moderate Post"
msgstr ""
#: inc/html.php:710
#: inc/html.php:721
msgid "Raw Post"
msgstr ""
#: inc/html.php:712
#: inc/html.php:723
msgid "Rebuild All"
msgstr ""
#: inc/html.php:715
#: inc/html.php:726 inc/html.php:1022
msgid "Update"
msgstr ""
#: inc/html.php:718
#: inc/html.php:729
msgid "Migrate Database"
msgstr ""
#: inc/html.php:720
#: inc/html.php:731
msgid "Log Out"
msgstr ""
#: inc/html.php:726
#: inc/html.php:737
msgid "Manage mode"
msgstr ""
#: inc/html.php:758
#: inc/html.php:771
msgid "Log In"
msgstr ""
#: inc/html.php:759
#: inc/html.php:772
msgid "Enter an administrator or moderator password"
msgstr ""
#: inc/html.php:775
#: inc/html.php:814
msgid "Add a ban"
msgstr ""
#: inc/html.php:776 inc/html.php:805
#: inc/html.php:815 inc/html.php:844
msgid "IP Address"
msgstr ""
#: inc/html.php:777
#: inc/html.php:816
msgid "Expire(sec)"
msgstr ""
#: inc/html.php:778 inc/html.php:805
#: inc/html.php:817 inc/html.php:844
msgid "Reason"
msgstr ""
#: inc/html.php:779
#: inc/html.php:818
msgid "never"
msgstr ""
#: inc/html.php:780
#: inc/html.php:819
msgid "optional"
msgstr ""
#: inc/html.php:782
#: inc/html.php:821
msgid "1 hour"
msgstr ""
#: inc/html.php:783
#: inc/html.php:822
msgid "1 day"
msgstr ""
#: inc/html.php:784
#: inc/html.php:823
msgid "2 days"
msgstr ""
#: inc/html.php:785
#: inc/html.php:824
msgid "1 week"
msgstr ""
#: inc/html.php:786
#: inc/html.php:825
msgid "2 weeks"
msgstr ""
#: inc/html.php:787
#: inc/html.php:826
msgid "1 month"
msgstr ""
#: inc/html.php:805
#: inc/html.php:844
msgid "Set At"
msgstr ""
#: inc/html.php:805
#: inc/html.php:844
msgid "Expires"
msgstr ""
#: inc/html.php:807
#: inc/html.php:846
msgid "Does not expire"
msgstr ""
#: inc/html.php:809
#: inc/html.php:848
msgid "lift"
msgstr ""
#: inc/html.php:817
#: inc/html.php:856
msgid "Moderate a post"
msgstr ""
#: inc/html.php:818
#: inc/html.php:857
msgid "Post ID"
msgstr ""
#: inc/html.php:820
#: inc/html.php:859
msgid "Tip:"
msgstr ""
#: inc/html.php:821
#: inc/html.php:860
msgid ""
"While browsing the image board, you can easily moderate a post if you are "
"logged in."
msgstr ""
#: inc/html.php:822
#: inc/html.php:861
msgid ""
"Tick the box next to a post and click \"Delete\" at the bottom of the page "
"with a blank password."
msgstr ""
#: inc/html.php:841
#: inc/html.php:880
#, php-format
msgid " A ban record already exists for %s"
msgstr ""
#: inc/html.php:844
#: inc/html.php:883
msgid "Only an administrator may ban an IP address."
msgstr ""
#: inc/html.php:846
#: inc/html.php:885
#, php-format
msgid "IP address: %s"
msgstr ""
#: inc/html.php:849
#: inc/html.php:888
msgid "This will delete the entire thread below."
msgstr ""
#: inc/html.php:849
#: inc/html.php:888
msgid "This will delete the post below."
msgstr ""
#: inc/html.php:850
#: inc/html.php:889
msgid "Thread"
msgstr ""
#: inc/html.php:850
#: inc/html.php:889
msgid "Post"
msgstr ""
#: inc/html.php:856
#: inc/html.php:895
msgid "Un-sticky"
msgstr ""
#: inc/html.php:856
#: inc/html.php:895
msgid "Sticky"
msgstr ""