Pk11 3 years ago committed by GitHub
parent 189f55eae9
commit d99e1aa2be

@ -1,25 +1,60 @@
<?php /* <?php
Copyright © 2022 Pk11 /* Copyright © 2022 Pk11
*
Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the “Software”), * copy of this software and associated documentation files (the “Software”),
to deal in the Software without restriction, including without limitation * to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, * the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the * and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions: * Software is furnished to do so, subject to the following conditions:
*
The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
*
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
*/ ?> */
// Return source code
if(isset($_GET['source'])) {
header("Content-Type: text/plain");
die(file_get_contents(basename($_SERVER['PHP_SELF'])));
}
/* vars.php should contain the following, but with your variables as needed:
*
* // Application constants
* define('UPLOAD_PATH', 'image/'); // Folder to save images to
* define('MAX_FILE_SIZE', 8 << 20); // Maximum image size, 8 MiB
* define('ADMIN_ID', '<SHA1 uid from your cookies>'); // uid that is able to delete anything
* define('UID_SALT', '<some string to salt uids with>');
* define('MAX_POSTS', 50); // Max posts after which old posts will be auto deleted. Only existing posts count, not manually deleted ones.
* define('DISCORD_WEBHOOK', 'https://discord.com/api/webhooks/<webhook id>/<webhook token>'); // A message will be sent to this webhook on post, for easier moderation
*
* // Database constants for PostgreSQL database
* $DB_HOST = 'localhost';
* $DB_NAME = '<db name>';
* $DB_USER = '<db role name>';
* $DB_PASSWORD = '<db role password>';
*
* You also need to make the following table:
*
* CEATE TABLE posts (
* post_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
* post_time TIMESTAMPTZ NOT NULL DEFAULT NOW(),
* user_id VARCHAR(40),
* name VARCHAR(256),
* comment VARCHAR(2048),
* img VARCHAR(256)
* );
*/
require_once('vars.php');
?>
<!DOCTYPE html <!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@ -36,6 +71,7 @@
</p> </p>
<?php <?php
// Adds a post to the database
function post($name, $comment, $img, $save_cookie) { function post($name, $comment, $img, $save_cookie) {
$extensions = [ $extensions = [
'image/bmp' => '.bmp', 'image/bmp' => '.bmp',
@ -56,13 +92,13 @@
if(!move_uploaded_file($img['tmp_name'], $target)) { if(!move_uploaded_file($img['tmp_name'], $target)) {
// The new image file move failed, so delete the temporary file and return an error // The new image file move failed, so delete the temporary file and return an error
@unlink($img['tmp_name']); @unlink($img['tmp_name']);
return 'Sorry, there was a problem uploading your image.'; return 'Unable to upload image, please contact the webmaster.';
} }
} }
} else { } else {
// The new picture file is not valid, so delete the temporary file and return an error // The image is not valid, so delete the temporary file and return an error
@unlink($img['tmp_name']); @unlink($img['tmp_name']);
return "Your picture must be a PNG, GIF, JPEG, or BMP image file no greater than {MM_MAXFILESIZE >> 10} KiB."; return 'Your image must be a PNG, GIF, JPEG, or BMP image file no greater than ' . (MAX_FILE_SIZE >> 10) . ' KiB.';
} }
} }
@ -91,6 +127,7 @@
return ""; // Success, no error return ""; // Success, no error
} }
// Regex callback, makes >>quotes into links
function quote_link($match) { function quote_link($match) {
$query = "SELECT post_id FROM posts WHERE post_id=$1"; $query = "SELECT post_id FROM posts WHERE post_id=$1";
$result = pg_query_params($query, [$match[1]]) or die('Query failed: ' . pg_last_error()); $result = pg_query_params($query, [$match[1]]) or die('Query failed: ' . pg_last_error());
@ -102,9 +139,8 @@
return "<del>{$match[0]}</del>"; return "<del>{$match[0]}</del>";
} }
// Prints the post list
function show_posts() { function show_posts() {
$show_delete = FALSE;
$query = 'SELECT post_id, user_id, name, comment, img, TO_CHAR(post_time, \'YYYY-MM-DD HH24:MI (TZ)\') AS post_time FROM posts'; $query = 'SELECT post_id, user_id, name, comment, img, TO_CHAR(post_time, \'YYYY-MM-DD HH24:MI (TZ)\') AS post_time FROM posts';
$result = pg_query($query) or die('Query failed: ' . pg_last_error()); $result = pg_query($query) or die('Query failed: ' . pg_last_error());
@ -117,12 +153,14 @@
} }
} }
// Print posts
$show_delete = FALSE;
echo '<form action="' . $_SERVER['PHP_SELF'] .'#bottom" method="post">'; echo '<form action="' . $_SERVER['PHP_SELF'] .'#bottom" method="post">';
while ($row = pg_fetch_array($result)) { while ($row = pg_fetch_array($result)) {
echo "<fieldset id=\"p{$row['post_id']}\">"; echo "<fieldset id=\"p{$row['post_id']}\">";
echo '<legend>'; echo '<legend>';
if((!empty($row['user_id']) && ($row['user_id'] == $_COOKIE['uid'])) || $_COOKIE['uid'] == ADMIN_ID) { if((!empty($row['user_id']) && ($row['user_id'] == $_COOKIE['uid'])) || (!empty(ADMIN_ID) && ($_COOKIE['uid'] == ADMIN_ID))) {
echo '<input type="checkbox" name="delete[]" value="' . $row['post_id'] . '" /> '; echo '<input type="checkbox" name="delete[]" value="' . $row['post_id'] . '" /> ';
$show_delete = TRUE; $show_delete = TRUE;
} }
@ -130,40 +168,50 @@
echo "<a href=\"#p{$row['post_id']}\">#{$row['post_id']}</a>"; echo "<a href=\"#p{$row['post_id']}\">#{$row['post_id']}</a>";
echo '</legend>'; echo '</legend>';
if($row['img']){ if(!empty($row['img'])){
echo '<a href="' . UPLOAD_PATH . $row['img'] . '" target="_blank">'; echo '<a href="' . UPLOAD_PATH . $row['img'] . '" target="_blank">';
echo '<img src="' . UPLOAD_PATH . $row['img'] . '" alt="' . $row['img'] . '" />'; echo '<img src="' . UPLOAD_PATH . $row['img'] . '" alt="' . $row['img'] . '" />';
echo '</a>'; echo '</a>';
} }
$comment = $row['comment']; // Process quotes, links, and newlines
$comment = preg_replace('/^>[^>].*/m', '<strong>$0</strong>', $comment); if(!empty($row['comment'])) {
$comment = preg_replace('/https?:\/\/[^\s]+/m', '<a href="$0">$0</a>', $comment); $comment = $row['comment'];
$comment = preg_replace_callback('/>>\s*(\d+)/', quote_link, $comment); $comment = preg_replace('/^>[^>].*/m', '<strong>$0</strong>', $comment);
$comment = str_replace("\n", "<br />", $comment); $comment = preg_replace('/https?:\/\/[^\s]+/m', '<a href="$0">$0</a>', $comment);
echo "<p>$comment</p>"; $comment = preg_replace_callback('/>>\s*(\d+)/', quote_link, $comment);
$comment = str_replace("\n", "<br />", $comment);
echo "<p>$comment</p>";
}
echo '</fieldset>'; echo '</fieldset>';
} }
pg_free_result($result);
if($show_delete) if($show_delete)
echo '<p><input type="submit" name="submit" value="Delete" /></p>'; echo '<p><input type="submit" name="submit" value="Delete" /></p>';
echo '</form>'; echo '</form>';
} }
// Removes a post from the database and its image
function cleanup($id, $force = FALSE) { function cleanup($id, $force = FALSE) {
$query = "SELECT user_id, img FROM posts WHERE post_id=$1"; $query = "SELECT user_id, img FROM posts WHERE post_id=$1";
$result = pg_query_params($query, [$id]) or die('Query failed: ' . pg_last_error()); $result = pg_query_params($query, [$id]) or die('Query failed: ' . pg_last_error());
$row = pg_fetch_array($result); $row = pg_fetch_array($result);
pg_free_result($result); pg_free_result($result);
if($force || $row['user_id'] == $_COOKIE['uid'] || $_COOKIE['uid'] == ADMIN_ID) { if($force || $row['user_id'] == $_COOKIE['uid'] || (!empty(ADMIN_ID) && ($_COOKIE['uid'] == ADMIN_ID))) {
unlink(UPLOAD_PATH . $row['img']); unlink(UPLOAD_PATH . $row['img']);
$query = "DELETE FROM posts WHERE post_id=$1"; $query = "DELETE FROM posts WHERE post_id=$1";
pg_query_params($query, [$id]) or die('Query failed: ' . pg_last_error()); pg_query_params($query, [$id]) or die('Query failed: ' . pg_last_error());
} }
} }
// Sends a webhook to Discord
function webhook($name, $message, $img) { function webhook($name, $message, $img) {
if(empty(DISCORD_WEBHOOK))
return;
$data = [ $data = [
'username' => $name, 'username' => $name,
'embeds' => [ 'embeds' => [
@ -191,11 +239,6 @@
die("Error: Sending webhook failed with status $status."); die("Error: Sending webhook failed with status $status.");
} }
require_once('appvars.php');
require_once('connectvars.php');
$err = "";
// Connect to the database // Connect to the database
$dbc = pg_connect("host=$DB_HOST dbname=$DB_NAME user=$DB_USER password=$DB_PASSWORD") $dbc = pg_connect("host=$DB_HOST dbname=$DB_NAME user=$DB_USER password=$DB_PASSWORD")
or die('Could not connect: ' . pg_last_error()); or die('Could not connect: ' . pg_last_error());
@ -216,8 +259,6 @@
show_posts(); show_posts();
pg_free_result($result);
pg_close($dbc); pg_close($dbc);
?> ?>
@ -237,7 +278,7 @@
</tr> </tr>
<tr> <tr>
<td><label for="img">Image:</label></td> <td><label for="img">Image:</label></td>
<td><input type="file" id="img" name="img" /></td> <td><input type="file" id="img" name="img" /> (Limit: <?php echo MAX_FILE_SIZE >> 10; ?> KiB)</td>
</tr> </tr>
<tr> <tr>
<td><label for="save-cookie">Save cookie:</label></td> <td><label for="save-cookie">Save cookie:</label></td>
@ -254,11 +295,13 @@
</form> </form>
<p> <p>
Old posts are automatically deleted once there are more than 50, anything inappropriate will be deleted. Old posts are automatically deleted once there are more than <?php echo MAX_POSTS; ?>, anything inappropriate will be deleted.
</p> </p>
<p> <p>
[<a href="#top">top</a>] [<a href="javascript:window.location.reload();">reload</a>] [<a href="#top">top</a>]
[<a href="javascript:window.location.reload();">reload</a>]
[<a href="?source">source</a>]
</p> </p>
<p> <p>

Loading…
Cancel
Save