diff --git a/README.md b/README.md
index 33556ef..2681019 100644
--- a/README.md
+++ b/README.md
@@ -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
------------
diff --git a/imgboard.php b/imgboard.php
index c70047c..e9c17a2 100644
--- a/imgboard.php
+++ b/imgboard.php
@@ -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);
diff --git a/inc/database_flatfile.php b/inc/database_flatfile.php
index fd0f5ba..c15e5b4 100644
--- a/inc/database_flatfile.php
+++ b/inc/database_flatfile.php
@@ -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;
diff --git a/inc/database_mysql.php b/inc/database_mysql.php
index 0418358..6908e98 100644
--- a/inc/database_mysql.php
+++ b/inc/database_mysql.php
@@ -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() {
diff --git a/inc/database_mysqli.php b/inc/database_mysqli.php
index 216597f..7e5974b 100644
--- a/inc/database_mysqli.php
+++ b/inc/database_mysqli.php
@@ -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() {
diff --git a/inc/database_pdo.php b/inc/database_pdo.php
index 01fb634..ba6d826 100644
--- a/inc/database_pdo.php
+++ b/inc/database_pdo.php
@@ -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() {
diff --git a/inc/database_sqlite.php b/inc/database_sqlite.php
index daeff65..a972ae4 100644
--- a/inc/database_sqlite.php
+++ b/inc/database_sqlite.php
@@ -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() {
diff --git a/inc/database_sqlite3.php b/inc/database_sqlite3.php
index 4c795b3..4ab0b02 100644
--- a/inc/database_sqlite3.php
+++ b/inc/database_sqlite3.php
@@ -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() {
diff --git a/inc/functions.php b/inc/functions.php
index 034400f..b81d9e3 100644
--- a/inc/functions.php
+++ b/inc/functions.php
@@ -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);
}
diff --git a/inc/html.php b/inc/html.php
index 5ca0351..b37bd80 100644
--- a/inc/html.php
+++ b/inc/html.php
@@ -336,6 +336,10 @@ function buildPost($post, $res) {
$reflink .= ' ';
}
+ if ($post["locked"] == 1) {
+ $reflink .= '
';
+ }
+
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) {