summaryrefslogtreecommitdiff
path: root/src/index.php
diff options
context:
space:
mode:
Diffstat (limited to 'src/index.php')
-rw-r--r--src/index.php166
1 files changed, 153 insertions, 13 deletions
diff --git a/src/index.php b/src/index.php
index 6258131..c75d112 100644
--- a/src/index.php
+++ b/src/index.php
@@ -1,5 +1,6 @@
<?php
+use Gregwar\Captcha\CaptchaBuilder;
use mystic\forum\Database;
use mystic\forum\exceptions\DatabaseConnectionException;
use mystic\forum\Messaging;
@@ -14,12 +15,17 @@ use mystic\forum\utils\ValidationUtils;
header_remove("X-Powered-By");
+if (($_SERVER["HTTP_USER_AGENT"] ?? "") === "") {
+ http_response_code(403);
+ exit;
+}
+
// function exception_error_handler($errno, $errstr, $errfile, $errline ) {
// throw new ErrorException(html_entity_decode($errstr), $errno, 0, $errfile, $errline);
// }
// set_error_handler("exception_error_handler");
-define("REGISTRATION_ENABLED", true);
+define("REGISTRATION_ENABLED", isTrue(env("REGISTRATION_ENABLED") ?? ""));
session_name("fsid");
session_start();
@@ -27,12 +33,21 @@ session_start();
const MAX_ATTACHMENT_SIZE = 0x200000;
const MAX_ATTACHMENT_COUNT = 4;
const THUMB_MAX_DIM = 100;
+const CAPTCHA_PHRASE_LENGTH = 7;
+const CAPTCHA_CHARSET = 'ABCDEFGHKLMNPQRTWXYZ234789abdefghkmnpqr';
$_rq_method = $_SERVER["REQUEST_METHOD"] ?? "GET";
$_action = $_GET["_action"] ?? null;
$GLOBALS["action"] = $_action;
+function generateCaptchaText(): string {
+ $phrase = "";
+ for ($i = 0; $i < CAPTCHA_PHRASE_LENGTH; ++$i)
+ $phrase .= CAPTCHA_CHARSET[random_int(0, strlen(CAPTCHA_CHARSET) - 1)];
+ return $phrase;
+}
+
function _view(string $name, array $params = []): void {
$___NAME = $name;
$___PARAMS = &$params;
@@ -42,13 +57,18 @@ function _view(string $name, array $params = []): void {
echo "<!--{/" . htmlentities($name) . "}-->\n";
}
+function isTrue(string $str): bool {
+ $str = strtolower($str);
+ return in_array($str, ["yes","true","y","t","on","enabled","1","?1"]);
+}
+
function reArrayFiles(&$file_post) {
$file_ary = [];
$file_count = count($file_post['name']);
$file_keys = array_keys($file_post);
for ($i=0; $i<$file_count; $i++) {
- if ($file_post["error"][$i] === UPLOAD_ERR_NO_FILE)
+ if ($file_post["error"][$i] !== UPLOAD_ERR_OK)
continue;
foreach ($file_keys as $key) {
$file_ary[$i][$key] = $file_post[$key][$i];
@@ -93,6 +113,13 @@ function renderPost(string $contents): string {
return $contents;
}
+function env(string $key): ?string {
+ $val = getenv($key);
+ if ($val === false)
+ return null;
+ return $val;
+}
+
require_once __DIR__ . "/vendor/autoload.php";
$db = null;
@@ -169,7 +196,7 @@ if ($_action === "auth") {
RequestUtils::setAuthorizedUser($user);
header("Location: " . $_GET["next"] ?? ".");
} else {
- _view("template_start", ["_title" => "Forum"]);
+ _view("template_start", ["_title" => "Log in"]);
_view("template_navigation_start");
_view("template_navigation", ["user" => RequestUtils::getAuthorizedUser($db)]);
_view("template_navigation_end");
@@ -189,11 +216,22 @@ if ($_action === "auth") {
}
if (RequestUtils::isRequestMethod("POST")) {
- $username = RequestUtils::getRequiredField("username");
+ $doNotFill = $_POST["username"] ?? null;
+ if ($doNotFill !== null) {
+ sleep(10);
+ http_response_code(204);
+ exit;
+ }
+ $username = RequestUtils::getRequiredField("df82a9bc21");
$password = RequestUtils::getRequiredField("password");
$passwordRetype = RequestUtils::getRequiredField("password_retype");
$email = trim(RequestUtils::getRequiredField("email"));
$displayName = RequestUtils::getRequiredField("display_name");
+ $captcha = RequestUtils::getRequiredField("captcha");
+
+ if ($captcha !== $_SESSION["captchaPhrase"]) {
+ RequestUtils::triggerFormError("Incorrect CAPTCHA text!");
+ }
// usernames are always lowercase
$username = strtolower($username);
@@ -250,7 +288,7 @@ if ($_action === "auth") {
Messaging::html('<p>Please click <a href="?_action=auth">here</a> to log in!</p>'),
]);
} else {
- _view("template_start", ["_title" => "Forum"]);
+ _view("template_start", ["_title" => "Register"]);
_view("template_navigation_start");
_view("template_navigation", ["user" => RequestUtils::getAuthorizedUser($db)]);
_view("template_navigation_end");
@@ -302,6 +340,7 @@ if ($_action === "auth") {
$post->content = $message;
$post->postDate = new DateTimeImmutable();
$post->deleted = false;
+ $post->edited = false;
$db->insert($post);
@@ -335,7 +374,7 @@ if ($_action === "auth") {
}
}
- _view("template_start", ["_title" => "Forum"]);
+ _view("template_start", ["_title" => $topic->title]);
_view("template_navigation_start");
_view("template_navigation", ["user" => RequestUtils::getAuthorizedUser($db)]);
_view("template_navigation_end");
@@ -383,6 +422,18 @@ if ($_action === "auth") {
$title = trim(RequestUtils::getRequiredField("title"));
$message = trim(RequestUtils::getRequiredField("message"));
+ $attachments = reArrayFiles($_FILES["files"]);
+
+ if (count($attachments) > MAX_ATTACHMENT_COUNT)
+ RequestUtils::triggerFormError("Too many attachments");
+
+ // check all attachments before saving one
+ foreach ($attachments as $att) {
+ if ($att["size"] > MAX_ATTACHMENT_SIZE) {
+ RequestUtils::triggerFormError("Individual file size exceeded");
+ }
+ }
+
if (strlen($title) < 1 || strlen($title) > 255) {
RequestUtils::triggerFormError("Title too short or too long!");
}
@@ -406,12 +457,29 @@ if ($_action === "auth") {
$post->content = $message;
$post->postDate = $topic->creationDate;
$post->deleted = false;
+ $post->edited = false;
$db->insert($post);
+ foreach ($attachments as $att) {
+ [
+ "name" => $name,
+ "type" => $type,
+ "tmp_name" => $tmpName,
+ ] = $att;
+ $attachment = new Attachment();
+ $attachment->id = $db->generateId();
+ $attachment->name = $name;
+ $attachment->mimeType = $type;
+ $attachment->postId = $post->id;
+ $attachment->contents = file_get_contents($tmpName);
+
+ $db->insert($attachment);
+ }
+
header("Location: ?_action=viewtopic&topic=" . urlencode($topic->id));
} else {
- _view("template_start", ["_title" => "Forum"]);
+ _view("template_start", ["_title" => "New topic"]);
_view("template_navigation_start");
_view("template_navigation", ["user" => RequestUtils::getAuthorizedUser($db)]);
_view("template_navigation_end");
@@ -522,7 +590,7 @@ if ($_action === "auth") {
continue;
$topics[$post->topicId] = $topic;
}
- _view("template_start", ["_title" => "Forum"]);
+ _view("template_start", ["_title" => $user->displayName]);
_view("template_navigation_start");
_view("template_navigation", ["user" => $currentUser]);
_view("template_navigation_end");
@@ -549,12 +617,27 @@ if ($_action === "auth") {
Messaging::error("No attachment exists with this id");
exit;
}
+
+ $name = preg_replace('/[\r\n\t\/]/', '_', $attachment->name);
$extension = pathinfo($attachment->name, PATHINFO_EXTENSION);
- header("Content-Type: " . FileUtils::getMimeTypeForExtension($extension));
+
+ $mime = FileUtils::getMimeTypeForExtension($extension);
+ switch ($mime) {
+ case "text/html":
+ case "text/css":
+ case "text/javascript":
+ case "text/xml":
+ case "application/css":
+ case "application/javascript":
+ case "application/xml":
+ $mime = "text/plain";
+ break;
+ }
+ header("Content-Type: " . $mime);
header("Content-Length: " . strlen($attachment->contents));
header("Cache-Control: no-cache");
- header("Content-Disposition: inline; filename=\"" . $attachment->name . "\"");
+ header("Content-Disposition: inline; filename=\"" . $name . "\"");
echo $attachment->contents;
} elseif ($_action === "profilepicture") {
$userId = $_GET["user"] ?? throw new Exception("Missing user id");
@@ -722,7 +805,7 @@ if ($_action === "auth") {
header("Location: ?_action=viewtopic&topic=" . urlencode($post->topicId));
} else {
- _view("template_start", ["_title" => "Forum"]);
+ _view("template_start", ["_title" => "Delete post"]);
_view("template_navigation_start");
_view("template_navigation", ["user" => RequestUtils::getAuthorizedUser($db)]);
_view("template_navigation_end");
@@ -733,6 +816,54 @@ if ($_action === "auth") {
]);
_view("template_end");
}
+} elseif ($_action === "updatepost") {
+ RequestUtils::ensureRequestMethod("POST");
+
+ if (!$currentUser) {
+ http_response_code(403);
+ Messaging::error("You need to be logged in to update posts!");
+ exit;
+ }
+
+ $postId = RequestUtils::getRequiredField("post");
+ $message = RequestUtils::getRequiredField("message");
+
+ $post = new Post();
+ $post->id = $postId;
+
+ if (!$db->fetch($post) || $post->deleted) {
+ http_response_code(404);
+ Messaging::error("No post exists with this id");
+ exit;
+ }
+
+ $topicAuthor = new User();
+ $topicAuthor->id = $post->authorId;
+
+ if (!$db->fetch($topicAuthor))
+ $topicAuthor = null;
+
+ $canEdit = ($currentUser->id === $topicAuthor?->id && $topicAuthor?->hasPermission(UserPermissions::EDIT_OWN_POST))
+ || ($currentUser->hasPermission(UserPermissions::EDIT_OTHER_POST));
+
+ if (!$canEdit) {
+ http_response_code(403);
+ Messaging::error("You don't have permission to edit this post");
+ exit;
+ }
+
+ $confirm = $_POST["confirm"] ?? null;
+
+ $post->content = $message;
+ $post->edited = true;
+
+ if (!$db->update($post)) {
+ http_response_code(500);
+ Messaging::error("Failed to update post");
+ exit;
+ }
+
+ header("Location: ?_action=viewtopic&topic=" . urlencode($post->topicId) . "#post-" . urlencode($postId));
} elseif ($_action === "deletetopic") {
RequestUtils::ensureRequestMethod("POST");
@@ -785,7 +916,7 @@ if ($_action === "auth") {
header("Location: .");
} else {
- _view("template_start", ["_title" => "Forum"]);
+ _view("template_start", ["_title" => "Delete topic"]);
_view("template_navigation_start");
_view("template_navigation", ["user" => RequestUtils::getAuthorizedUser($db)]);
_view("template_navigation_end");
@@ -840,8 +971,17 @@ if ($_action === "auth") {
}
header("Location: ./?_action=viewtopic&topic=" . urlencode($topicId));
+} elseif ($_action === "captcha") {
+ $phrase = generateCaptchaText();
+ $builder = new CaptchaBuilder($phrase);
+ $builder->build(192, 48);
+ $_SESSION["captchaPhrase"] = $phrase;
+ header("Content-Type: image/jpeg");
+ header("Pragma: no-cache");
+ header("Cache-Control: no-cache");
+ $builder->save(null, 40);
} elseif ($_action === null) {
- _view("template_start", ["_title" => "Forum"]);
+ _view("template_start");
_view("template_navigation_start");
_view("template_navigation", ["user" => RequestUtils::getAuthorizedUser($db)]);
_view("template_navigation_end");