svrjs-mods-directory/includes/page_submit.php
2024-12-27 15:05:54 +01:00

258 lines
No EOL
12 KiB
PHP

<?php
if (!defined('SVRJS_MOD_DIRECTORY')) die;
$errorMessage = null;
$modSubmitted = false;
$slug = null;
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (!isset($_POST['_csrf']) || $_POST['_csrf'] != $_SESSION['csrf']) {
$errorMessage = "Potential CSRF attack detected.";
} elseif (!isset($_POST['name'], $_POST['category'], $_POST['link']) || !$_POST['name'] || !$_POST['category'] || !$_POST['link']) {
$errorMessage = "You need to input name, category and download page URL.";
} elseif (!filter_var($_POST['link'], FILTER_VALIDATE_URL) || !preg_match('/^https?:\\/\\//', $_POST['link'])) {
$errorMessage = "Invalid download page URL.";
} elseif (isset($_POST['docslink']) && $_POST['docslink'] && (!filter_var($_POST['docslink'], FILTER_VALIDATE_URL) || !preg_match('/^https?:\\/\\//', $_POST['docslink']))) {
$errorMessage = "Invalid documentation URL.";
} elseif (!filter_var($_POST['category'], FILTER_VALIDATE_INT)) {
$errorMessage = "Invalid category.";
} else {
$categoryID = intval($_POST['category']);
$statement = $connection->prepare("SELECT id FROM categories WHERE id = ?");
if (!$statement) {
$errorMessage = "An unexpected error occurred while submitting the mod.";
} else {
$statement->bind_param('i', $categoryID);
$statement->execute();
$result = $statement->get_result();
if (!$result) {
$errorMessage = "An unexpected error occurred while submitting the mod.";
$statement->close();
} else {
$isCategoryPresent = boolval($result->fetch_assoc());
$statement->close();
if (!$isCategoryPresent) {
$errorMessage = "The selected category doesn't exist.";
} else {
$slugError = false;
$tempSlug = null;
$tempSlugCount = 1;
while (is_null($slug)) {
if (!$tempSlug) {
$tempSlug = strtolower($_POST['name']);
$tempSlug = preg_replace('/[^a-zA-Z0-9]+/', '-', $tempSlug);
$tempSlug = preg_replace('/^-+/', '', $tempSlug);
$tempSlug = preg_replace('/-+$/', '', $tempSlug);
}
$statement = $connection->prepare("SELECT slug FROM mods WHERE slug = ? UNION SELECT slug FROM mods_pending WHERE slug = ?");
if (!$statement) {
$slugError = true;
$errorMessage = "An unexpected error occurred while submitting the mod.";
break;
} else {
$tempSlug2 = $tempSlug . ($tempSlugCount > 1 ? '-' . strval($tempSlugCount) : '');
$statement->bind_param('ss', $tempSlug2, $tempSlug2);
$statement->execute();
$slugExistsResult = $statement->get_result();
if (!$slugExistsResult) {
$slugError = true;
$errorMessage = "An unexpected error occurred while submitting the mod.";
$statement->close();
break;
} else {
$slugExists = boolval($slugExistsResult->fetch_assoc());
$statement->close();
if (!$slugExists) {
$slug = $tempSlug2;
} else {
$tempSlugCount++;
}
}
}
}
if (!$slugError) {
$fileError = false;
$fileExtension = null;
$modPendingUploadDirectory = APP_FSROOT . '/img/mods_pending';
$modUploadDirectory = APP_FSROOT . '/img/mods';
if (isset($_FILES['cover']) && $_FILES['cover']['error'] != UPLOAD_ERR_NO_FILE) {
if ($_FILES['cover']['error'] != UPLOAD_ERR_OK) {
$fileError = true;
$errorMessage = "An unexpected error occurred while uploading the cover image.";
} else {
$fileTmpPath = $_FILES['cover']['tmp_name'];
$fileName = $_FILES['cover']['name'];
$fileSize = $_FILES['cover']['size'];
$fileType = $_FILES['cover']['type'];
$fileExtension = pathinfo($fileName, PATHINFO_EXTENSION);
if ($fileSize > IMAGE_MAX_SIZE) {
$fileError = true;
$errorMessage = "The cover image is too large. Maximum cover image size: " . formatFileSize(IMAGE_MAX_SIZE);
} elseif (!in_array($fileExtension, IMAGE_EXTENSIONS_ALLOWED, true)) {
$fileError = true;
$errorMessage = "Invalid cover image extension.";
} else {
$imageType = exif_imagetype($fileTmpPath);
if (!$imageType || ($fileType && image_type_to_mime_type($imageType) != $fileType)) {
$fileError = true;
$errorMessage = "The cover image is either corrupted or of wrong type.";
} else {
if (!file_exists($modPendingUploadDirectory) && !mkdir($modPendingUploadDirectory, 0777, true)) {
$fileError = true;
$errorMessage = "An unexpected error occurred while uploading the cover image.";
}
if (!$fileError) {
$uploadedCoverImagePathname = $modPendingUploadDirectory . '/' . str_replace(['/', '\\'], '', $modDataToEdit['slug']) . '.' . $fileExtension;
if (!move_uploaded_file($fileTmpPath, $uploadedCoverImagePathname)) {
$fileError = true;
$errorMessage = "An unexpected error occurred while uploading the cover image.";
}
}
}
}
}
}
if (!$fileError) {
$statement = $connection->prepare("INSERT INTO mods_pending (
name,
slug,
description,
category,
link,
docs_link,
user,
image_ext,
is_paid,
is_rejected
) VALUES (
?,
?,
?,
?,
?,
?,
?,
?,
?,
0
)");
if (!$statement) {
$errorMessage = "An unexpected error occurred while submitting the mod.";
} else {
$modName = $_POST['name'];
$modSlug = $slug;
$modDescription = isset($_POST['description']) && $_POST['description'] ? $_POST['description'] : null;
$modCategory = $categoryID;
$modLink = $_POST['link'];
$modDocsLink = isset($_POST['docslink']) && $_POST['docslink'] ? $_POST['docslink'] : null;
$modUser = $_SESSION['user'];
$modImageExt = $fileExtension;
$modIsPaid = isset($_POST['paid']) ? 1 : 0;
$statement->bind_param('sssissisi', $modName, $modSlug, $modDescription, $modCategory, $modLink, $modDocsLink, $modUser, $modImageExt, $modIsPaid);
if (!$statement->execute()) {
$errorMessage = "An unexpected error occurred while submitting the mod.";
$statement->close();
} else {
$modSubmitted = true;
$statement->close();
}
}
}
}
}
}
}
}
}
if (!$modSubmitted) {
$pageTitle = "Submit mod";
$pageDescription = "Submit the SVR.JS mod in SVR.JS Mods directory.";
} else {
$pageTitle = "Mod submitted";
$pageDescription = "The submitted mod is now awaiting moderators' approval.";
}
include 'header.php';
?>
<main class="content">
<?php if ($modSubmitted) { ?>
<h1>Mod submitted</h1>
<p>The submitted mod is now awaiting moderators' approval.</p>
<p><a href="<?php echo htmlspecialchars((URL_REWRITTEN ? APP_ROOT : APP_ROOT . APP_FILENAME . '/') . 'pending-mods'); ?>" class="btn">View pending mods</a></p>
<?php } else { ?>
<h1>Submit mod</h1>
<form action="<?php echo htmlspecialchars((URL_REWRITTEN ? APP_ROOT : APP_ROOT . APP_FILENAME . '/') . 'submit') ?>" method="post" class="form" enctype="multipart/form-data">
<div class="form-block">
<label for="name">Mod name:</label>
<input type="text" id="name" name="name" required maxlength="255">
</div>
<div class="form-block">
<label for="cover">Cover image:</label>
<input type="file" id="cover" name="cover" accept="<?php echo htmlspecialchars(implode(',', array_map(
function ($extension) {
return '.' . $extension;
},
IMAGE_EXTENSIONS_ALLOWED
))) ?>">
<p>Allowed file extensions for the cover image: <strong><?php echo htmlspecialchars(implode(', ', array_map(
function ($extension) {
return '.' . $extension;
},
IMAGE_EXTENSIONS_ALLOWED
))) ?></strong></p>
</div>
<div class="form-block">
<label for="category">Category:</label>
<select id="category" name="category" required>
<?php
$result = $connection->query('SELECT id, name FROM categories');
if ($result) {
while ($row = $result->fetch_assoc()) {
echo '<option value="' . htmlspecialchars(strval($row['id'])) . '">' . htmlspecialchars($row['name']) . '</option>';
}
}
?>
</select>
</div>
<div class="form-block">
<label for="description">Mod description:</label>
<textarea name="description" id="description" maxlength="10000"></textarea>
</div>
<div class="form-block">
<label for="link">Download page URL:</label>
<input type="url" id="link" name="link" required maxlength="255">
</div>
<div class="form-block">
<label for="docslink">Documentation URL:</label>
<input type="url" id="docslink" name="docslink" maxlength="255">
</div>
<div class="form-block-checkbox">
<input type="checkbox" name="paid" id="paid">
<label for="paid">Paid?</label>
</div>
<?php if ($errorMessage) echo '<p class="form-error">' . htmlspecialchars($errorMessage) . '</p>'; ?>
<div class="form-block">
<input type="submit" value="Submit mod">
</div>
<input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($_SESSION['csrf']) ?>">
</form>
<?php } ?>
</main>
<?php
include 'footer.php';
if ($modSubmitted) {
$moderatorResult = $connection->query("SELECT email AS address, username AS name FROM users WHERE is_moderator = 1;");
if ($moderatorResult) {
$moderators = [];
while ($moderator = $moderatorResult->fetch_assoc()) {
array_push($moderators, $moderator);
}
sendEmail($moderators, 'A mod has been submitted that requires approval', "A mod has been submitted that requires approval:\n\nMod name: " . str_replace(["\r\n", "\r", "\n"], '', $_POST['name']) . "\nSlug: " . $slug . "\n\nPlease review the mod and approve or reject it.");
}
}
?>