Support locking threads

Resolves #41.
This commit is contained in:
Trevor Slocum 2020-07-31 16:16:37 -07:00
parent ec08da093a
commit c3e137d48d
11 changed files with 147 additions and 24 deletions

View File

@ -19,7 +19,7 @@ Features
- Delete post via password.
- Management panel:
- Administrators and moderators use separate passwords.
- Moderators are only able to sticky threads, delete posts, and approve posts when necessary. (See ``TINYIB_REQMOD``)
- Moderators are only able to sticky threads, lock threads, delete posts, and approve posts when necessary. (See ``TINYIB_REQMOD``)
- Ban offensive/abusive posters across all boards.
- Post using raw HTML.
- Upgrade automatically when installed via git. (Tested on Linux only)
@ -86,9 +86,6 @@ Updating
- If other files were updated, and you have made changes yourself:
- Visit [GitLab](https://gitlab.com/tslocum/tinyib) and review the changes made in the update.
- Ensure the update does not interfere with your changes.
3. Visit [GitLab](https://gitlab.com/tslocum/tinyib/wikis/NewSQLStructure) and check for new SQL queries which may be required to complete the update.
**Database structure was last modified on *15th Sep 2015*.** Are you unable to create new posts? Run the SQL on [this page](https://gitlab.com/tslocum/tinyib/wikis/NewSQLStructure) to finish the upgrade process.
Migrating
------------

View File

@ -91,6 +91,15 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
$post = newPost(setParent());
$hide_fields = $post['parent'] == TINYIB_NEWTHREAD ? $tinyib_hidefieldsop : $tinyib_hidefields;
if ($post['parent'] != TINYIB_NEWTHREAD && !$loggedin) {
$parent = postByID($post['parent']);
if (!isset($parent['locked'])) {
fancyDie("Invalid parent thread ID supplied, unable to create post.");
} else if ($parent['locked'] == 1) {
fancyDie('Replies are not allowed to locked threads.');
}
}
$post['ip'] = $_SERVER['REMOTE_ADDR'];
if ($rawpost || !in_array('name', $hide_fields)) {
list($post['name'], $post['tripcode']) = nameAndTripcode($_POST['name']);
@ -443,7 +452,7 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
if (!$link) {
fancyDie("Could not connect to database: " . ((is_object($link)) ? mysqli_error($link) : (($link_error = mysqli_connect_error()) ? $link_error : '(unknown error)')));
}
$db_selected = @mysqli_query($link, "USE " . constant('TINYIB_DBNAME'));
$db_selected = @mysqli_query($link, "USE " . TINYIB_DBNAME);
if (!$db_selected) {
fancyDie("Could not select database: " . ((is_object($link)) ? mysqli_error($link) : (($link_error = mysqli_connect_error()) ? $link_error : '(unknown error')));
}
@ -543,7 +552,7 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
if ($_GET['sticky'] > 0) {
$post = postByID($_GET['sticky']);
if ($post && $post['parent'] == TINYIB_NEWTHREAD) {
stickyThreadByID($post['id'], (intval($_GET['setsticky'])));
stickyThreadByID($post['id'], intval($_GET['setsticky']));
threadUpdated($post['id']);
$text .= manageInfo('Thread No.' . $post['id'] . ' ' . (intval($_GET['setsticky']) == 1 ? 'stickied' : 'un-stickied') . '.');
@ -553,6 +562,20 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
} else {
fancyDie("Form data was lost. Please go back and try again.");
}
} elseif (isset($_GET['lock']) && isset($_GET['setlock'])) {
if ($_GET['lock'] > 0) {
$post = postByID($_GET['lock']);
if ($post && $post['parent'] == TINYIB_NEWTHREAD) {
lockThreadByID($post['id'], intval($_GET['setlock']));
threadUpdated($post['id']);
$text .= manageInfo('Thread No.' . $post['id'] . ' ' . (intval($_GET['setlock']) == 1 ? 'locked' : 'unlocked') . '.');
} else {
fancyDie("Sorry, there doesn't appear to be a thread with that ID.");
}
} else {
fancyDie("Form data was lost. Please go back and try again.");
}
} elseif (isset($_GET["rawpost"])) {
$onload = manageOnLoad("rawpost");
$text .= buildPostForm(0, true);

View File

@ -28,6 +28,7 @@ define('POST_THUMB', 19);
define('POST_THUMB_WIDTH', 20);
define('POST_THUMB_HEIGHT', 21);
define('POST_STICKIED', 22);
define('POST_LOCKED', 23);
# Ban Structure
define('BANS_FILE', '.bans');
@ -83,10 +84,21 @@ function insertPost($newpost) {
$post[POST_THUMB_WIDTH] = $newpost['thumb_width'];
$post[POST_THUMB_HEIGHT] = $newpost['thumb_height'];
$post[POST_STICKIED] = $newpost['stickied'];
$post[POST_LOCKED] = $newpost['locked'];
return $GLOBALS['db']->insertWithAutoId(POSTS_FILE, POST_ID, $post);
}
function bumpThreadByID($id) {
$rows = $GLOBALS['db']->selectWhere(POSTS_FILE, new SimpleWhereClause(POST_ID, '=', $id, INTEGER_COMPARISON), 1);
if (count($rows) > 0) {
foreach ($rows as $post) {
$post[POST_BUMPED] = time();
$GLOBALS['db']->updateRowById(POSTS_FILE, POST_ID, $post);
}
}
}
function stickyThreadByID($id, $setsticky) {
$rows = $GLOBALS['db']->selectWhere(POSTS_FILE, new SimpleWhereClause(POST_ID, '=', $id, INTEGER_COMPARISON), 1);
if (count($rows) > 0) {
@ -97,11 +109,11 @@ function stickyThreadByID($id, $setsticky) {
}
}
function bumpThreadByID($id) {
function lockThreadByID($id, $setlock) {
$rows = $GLOBALS['db']->selectWhere(POSTS_FILE, new SimpleWhereClause(POST_ID, '=', $id, INTEGER_COMPARISON), 1);
if (count($rows) > 0) {
foreach ($rows as $post) {
$post[POST_BUMPED] = time();
$post[POST_LOCKED] = intval($setlock);
$GLOBALS['db']->updateRowById(POSTS_FILE, POST_ID, $post);
}
}
@ -139,6 +151,7 @@ function convertPostsToSQLStyle($posts, $singlepost = false) {
$post['thumb_width'] = $oldpost[POST_THUMB_WIDTH];
$post['thumb_height'] = $oldpost[POST_THUMB_HEIGHT];
$post['stickied'] = isset($oldpost[POST_STICKIED]) ? $oldpost[POST_STICKIED] : 0;
$post['locked'] = isset($oldpost[POST_LOCKED]) ? $oldpost[POST_LOCKED] : 0;
if ($post['parent'] == '') {
$post['parent'] = TINYIB_NEWTHREAD;

View File

@ -27,6 +27,14 @@ if (mysql_num_rows(mysql_query("SHOW TABLES LIKE '" . TINYIB_DBBANS . "'")) == 0
mysql_query($bans_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'");
}
if (mysql_num_rows(mysql_query("SHOW COLUMNS FROM `" . TINYIB_DBPOSTS . "` LIKE 'locked'")) == 0) {
mysql_query("ALTER TABLE `" . TINYIB_DBPOSTS . "` ADD COLUMN locked TINYINT(1) NOT NULL DEFAULT '0'");
}
# Post Functions
function uniquePosts() {
$row = mysql_fetch_row(mysql_query("SELECT COUNT(DISTINCT(`ip`)) FROM " . TINYIB_DBPOSTS));
@ -55,12 +63,16 @@ function approvePostByID($id) {
mysql_query("UPDATE `" . TINYIB_DBPOSTS . "` SET `moderated` = 1 WHERE `id` = " . $id . " LIMIT 1");
}
function bumpThreadByID($id) {
mysql_query("UPDATE `" . TINYIB_DBPOSTS . "` SET `bumped` = " . time() . " WHERE `id` = " . $id . " LIMIT 1");
}
function stickyThreadByID($id, $setsticky) {
mysql_query("UPDATE `" . TINYIB_DBPOSTS . "` SET `stickied` = '" . mysql_real_escape_string($setsticky) . "' WHERE `id` = " . $id . " LIMIT 1");
}
function bumpThreadByID($id) {
mysql_query("UPDATE `" . TINYIB_DBPOSTS . "` SET `bumped` = " . time() . " WHERE `id` = " . $id . " LIMIT 1");
function lockThreadByID($id, $setlock) {
mysql_query("UPDATE `" . TINYIB_DBPOSTS . "` SET `locked` = '" . mysql_real_escape_string($setlock) . "' WHERE `id` = " . $id . " LIMIT 1");
}
function countThreads() {

View File

@ -11,7 +11,7 @@ $link = @mysqli_connect(TINYIB_DBHOST, TINYIB_DBUSERNAME, TINYIB_DBPASSWORD);
if (!$link) {
fancyDie("Could not connect to database: " . ((is_object($link)) ? mysqli_error($link) : (($link_error = mysqli_connect_error()) ? $link_error : '(unknown error)')));
}
$db_selected = @mysqli_query($link, "USE " . constant('TINYIB_DBNAME'));
$db_selected = @mysqli_query($link, "USE " . TINYIB_DBNAME);
if (!$db_selected) {
fancyDie("Could not select database: " . ((is_object($link)) ? mysqli_error($link) : (($link_error = mysqli_connect_error()) ? $link_error : '(unknown error')));
}
@ -27,6 +27,14 @@ if (mysqli_num_rows(mysqli_query($link, "SHOW TABLES LIKE '" . TINYIB_DBBANS . "
mysqli_query($link, $bans_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'");
}
if (mysqli_num_rows(mysqli_query($link, "SHOW COLUMNS FROM `" . TINYIB_DBPOSTS . "` LIKE 'locked'")) == 0) {
mysqli_query($link,"ALTER TABLE `" . TINYIB_DBPOSTS . "` ADD COLUMN locked TINYINT(1) NOT NULL DEFAULT '0'");
}
# Post Functions
function uniquePosts() {
global $link;
@ -60,14 +68,19 @@ function approvePostByID($id) {
mysqli_query($link, "UPDATE `" . TINYIB_DBPOSTS . "` SET `moderated` = 1 WHERE `id` = " . $id . " LIMIT 1");
}
function bumpThreadByID($id) {
global $link;
mysqli_query($link, "UPDATE `" . TINYIB_DBPOSTS . "` SET `bumped` = " . time() . " WHERE `id` = " . $id . " LIMIT 1");
}
function stickyThreadByID($id, $setsticky) {
global $link;
mysqli_query($link, "UPDATE `" . TINYIB_DBPOSTS . "` SET `stickied` = '" . mysqli_real_escape_string($link, $setsticky) . "' WHERE `id` = " . $id . " LIMIT 1");
}
function bumpThreadByID($id) {
function lockThreadByID($id, $setlock) {
global $link;
mysqli_query($link, "UPDATE `" . TINYIB_DBPOSTS . "` SET `bumped` = " . time() . " WHERE `id` = " . $id . " LIMIT 1");
mysqli_query($link, "UPDATE `" . TINYIB_DBPOSTS . "` SET `locked` = '" . mysqli_real_escape_string($link, $setlock) . "' WHERE `id` = " . $id . " LIMIT 1");
}
function countThreads() {

View File

@ -54,7 +54,31 @@ if (!$bans_exists) {
$dbh->exec($bans_sql);
}
# Utililty
if (TINYIB_DBDRIVER === 'pgsql') {
$query = "SELECT column_name FROM information_schema.columns WHERE table_name='" . TINYIB_DBPOSTS . "' and column_name='stickied'";
$stickied_exists = $dbh->query($query)->fetchColumn() != 0;
} else {
$dbh->query("SHOW COLUMNS FROM `" . TINYIB_DBPOSTS . "` LIKE 'stickied'");
$stickied_exists = $dbh->query("SELECT FOUND_ROWS()")->fetchColumn() != 0;
}
if (!$stickied_exists) {
$dbh->exec("ALTER TABLE `" . TINYIB_DBPOSTS . "` ADD COLUMN stickied TINYINT(1) NOT NULL DEFAULT '0'");
}
if (TINYIB_DBDRIVER === 'pgsql') {
$query = "SELECT column_name FROM information_schema.columns WHERE table_name='" . TINYIB_DBPOSTS . "' and column_name='locked'";
$stickied_exists = $dbh->query($query)->fetchColumn() != 0;
} else {
$dbh->query("SHOW COLUMNS FROM `" . TINYIB_DBPOSTS . "` LIKE 'locked'");
$stickied_exists = $dbh->query("SELECT FOUND_ROWS()")->fetchColumn() != 0;
}
if (!$stickied_exists) {
$dbh->exec("ALTER TABLE `" . TINYIB_DBPOSTS . "` ADD COLUMN locked TINYINT(1) NOT NULL DEFAULT '0'");
}
# Utility
function pdoQuery($sql, $params = false) {
global $dbh;
@ -102,13 +126,17 @@ function approvePostByID($id) {
pdoQuery("UPDATE " . TINYIB_DBPOSTS . " SET moderated = ? WHERE id = ?", array('1', $id));
}
function bumpThreadByID($id) {
$now = time();
pdoQuery("UPDATE " . TINYIB_DBPOSTS . " SET bumped = ? WHERE id = ?", array($now, $id));
}
function stickyThreadByID($id, $setsticky) {
pdoQuery("UPDATE " . TINYIB_DBPOSTS . " SET stickied = ? WHERE id = ?", array($setsticky, $id));
}
function bumpThreadByID($id) {
$now = time();
pdoQuery("UPDATE " . TINYIB_DBPOSTS . " SET bumped = ? WHERE id = ?", array($now, $id));
function lockThreadByID($id, $setlock) {
pdoQuery("UPDATE " . TINYIB_DBPOSTS . " SET locked = ? WHERE id = ?", array($setlock, $id));
}
function countThreads() {

View File

@ -56,6 +56,9 @@ if (sqlite_num_rows($result) == 0) {
// Add stickied column if it isn't present
sqlite_query($db, "ALTER TABLE " . TINYIB_DBPOSTS . " ADD COLUMN stickied INTEGER NOT NULL DEFAULT '0'");
// Add locked column if it isn't present
sqlite_query($db, "ALTER TABLE " . TINYIB_DBPOSTS . " ADD COLUMN locked INTEGER NOT NULL DEFAULT '0'");
# Post Functions
function uniquePosts() {
return sqlite_fetch_single(sqlite_query($GLOBALS["db"], "SELECT COUNT(ip) FROM (SELECT DISTINCT ip FROM " . TINYIB_DBPOSTS . ")"));
@ -77,12 +80,16 @@ function insertPost($post) {
return sqlite_last_insert_rowid($GLOBALS["db"]);
}
function bumpThreadByID($id) {
sqlite_query($GLOBALS["db"], "UPDATE " . TINYIB_DBPOSTS . " SET bumped = " . time() . " WHERE id = " . $id);
}
function stickyThreadByID($id, $setsticky) {
sqlite_query($GLOBALS["db"], "UPDATE " . TINYIB_DBPOSTS . " SET stickied = '" . sqlite_escape_string($setsticky) . "' WHERE id = " . $id);
}
function bumpThreadByID($id) {
sqlite_query($GLOBALS["db"], "UPDATE " . TINYIB_DBPOSTS . " SET bumped = " . time() . " WHERE id = " . $id);
function lockThreadByID($id, $setlock) {
sqlite_query($GLOBALS["db"], "UPDATE " . TINYIB_DBPOSTS . " SET locked = '" . sqlite_escape_string($setlock) . "' WHERE id = " . $id);
}
function countThreads() {

View File

@ -57,6 +57,9 @@ if (!$result->fetchArray()) {
// Add stickied column if it isn't present
@$db->exec("ALTER TABLE " . TINYIB_DBPOSTS . " ADD COLUMN stickied INTEGER NOT NULL DEFAULT '0'");
// Add locked column if it isn't present
@$db->exec("ALTER TABLE " . TINYIB_DBPOSTS . " ADD COLUMN locked INTEGER NOT NULL DEFAULT '0'");
# Post Functions
function uniquePosts() {
global $db;
@ -82,14 +85,19 @@ function insertPost($post) {
return $db->lastInsertRowID();
}
function bumpThreadByID($id) {
global $db;
$db->exec("UPDATE " . TINYIB_DBPOSTS . " SET bumped = " . time() . " WHERE id = " . $id);
}
function stickyThreadByID($id, $setsticky) {
global $db;
$db->exec("UPDATE " . TINYIB_DBPOSTS . " SET stickied = '" . $db->escapeString($setsticky) . "' WHERE id = " . $id);
}
function bumpThreadByID($id) {
function lockThreadByID($id, $setlock) {
global $db;
$db->exec("UPDATE " . TINYIB_DBPOSTS . " SET bumped = " . time() . " WHERE id = " . $id);
$db->exec("UPDATE " . TINYIB_DBPOSTS . " SET locked = '" . $db->escapeString($setlock) . "' WHERE id = " . $id);
}
function countThreads() {

View File

@ -27,8 +27,9 @@ if (TINYIB_DBMODE == 'pdo' && TINYIB_DBDRIVER == 'pgsql') {
"thumb" varchar(255) NOT NULL,
"thumb_width" smallint NOT NULL default \'0\',
"thumb_height" smallint NOT NULL default \'0\',
"stickied" smallint NOT NULL default \'0\',
"moderated" smallint NOT NULL default \'1\',
"stickied" smallint NOT NULL default \'0\',
"locked" smallint NOT NULL default \'0\',
PRIMARY KEY ("id")
);
CREATE INDEX ON "' . TINYIB_DBPOSTS . '"("parent");
@ -231,8 +232,8 @@ function writePage($filename, $contents) {
}
function fixLinksInRes($html) {
$search = array(' href="css/', ' src="js/', ' href="src/', ' href="thumb/', ' href="res/', ' href="imgboard.php', ' href="favicon.ico', 'src="thumb/', 'src="inc/', 'src="sticky.png', ' action="imgboard.php');
$replace = array(' href="../css/', ' src="../js/', ' href="../src/', ' href="../thumb/', ' href="../res/', ' href="../imgboard.php', ' href="../favicon.ico', 'src="../thumb/', 'src="../inc/', 'src="../sticky.png', ' action="../imgboard.php');
$search = array(' href="css/', ' src="js/', ' href="src/', ' href="thumb/', ' href="res/', ' href="imgboard.php', ' href="favicon.ico', 'src="thumb/', 'src="inc/', 'src="sticky.png', 'src="lock.png', ' action="imgboard.php');
$replace = array(' href="../css/', ' src="../js/', ' href="../src/', ' href="../thumb/', ' href="../res/', ' href="../imgboard.php', ' href="../favicon.ico', 'src="../thumb/', 'src="../inc/', 'src="../sticky.png', 'src="../lock.png', ' action="../imgboard.php');
return str_replace($search, $replace, $html);
}

View File

@ -336,6 +336,10 @@ function buildPost($post, $res) {
$reflink .= ' <img src="sticky.png" alt="Stickied" title="Stickied" width="16" height="16">';
}
if ($post["locked"] == 1) {
$reflink .= ' <img src="lock.png" alt="Locked" title="Locked" width="16" height="16">';
}
if (!isset($post["omitted"])) {
$post["omitted"] = 0;
}
@ -703,6 +707,7 @@ function manageModeratePost($post) {
$post_or_thread = ($post['parent'] == TINYIB_NEWTHREAD) ? 'Thread' : 'Post';
$sticky_html = "";
$lock_html = "";
if ($post["parent"] == TINYIB_NEWTHREAD) {
$sticky_set = $post['stickied'] == 1 ? '0' : '1';
$sticky_unsticky = $post['stickied'] == 1 ? 'Un-sticky' : 'Sticky';
@ -719,6 +724,20 @@ function manageModeratePost($post) {
</td><td><small>$sticky_unsticky_help</small></td></tr>
EOF;
$lock_set = $post['locked'] == 1 ? '0' : '1';
$lock_label = $post['locked'] == 1 ? 'Unlock' : 'Lock';
$lock_help = $post['locked'] == 1 ? 'Allow replying to this thread.' : 'Disallow replying to this thread.';
$lock_html = <<<EOF
<tr><td align="right" width="50%;">
<form method="get" action="?">
<input type="hidden" name="manage" value="">
<input type="hidden" name="lock" value="${post['id']}">
<input type="hidden" name="setlock" value="$lock_set">
<input type="submit" value="$lock_label Thread" class="managebutton" style="width: 50%;">
</form>
</td><td><small>$lock_help</small></td></tr>
EOF;
$post_html = "";
$posts = postsInThreadByID($post["id"]);
foreach ($posts as $post_temp) {
@ -757,6 +776,8 @@ EOF;
$sticky_html
$lock_html
</table>
</fieldset>

BIN
lock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B