summaryrefslogtreecommitdiff
path: root/public
diff options
context:
space:
mode:
authorilotterytea <iltsu@alright.party>2025-06-18 15:00:49 +0500
committerilotterytea <iltsu@alright.party>2025-06-18 15:00:49 +0500
commit312b5d6e873d53b78db4bef628fe01391a30cdb0 (patch)
tree677ea09ae06471784509602421ba78d24d68dbb0 /public
parent01b4d8ac76a2a6a7ee57dd173f3894022977d2cb (diff)
feat: file bans
Diffstat (limited to 'public')
-rw-r--r--public/ban.php104
-rw-r--r--public/catalogue.php3
-rw-r--r--public/index.php124
-rw-r--r--public/mod.php2
-rw-r--r--public/static/style.css15
-rw-r--r--public/upload.php9
6 files changed, 199 insertions, 58 deletions
diff --git a/public/ban.php b/public/ban.php
new file mode 100644
index 0000000..c9fdfd6
--- /dev/null
+++ b/public/ban.php
@@ -0,0 +1,104 @@
+<?php
+include_once $_SERVER['DOCUMENT_ROOT'] . '/../config.php';
+include_once $_SERVER['DOCUMENT_ROOT'] . '/../lib/utils.php';
+include_once $_SERVER['DOCUMENT_ROOT'] . '/../lib/file.php';
+include_once $_SERVER['DOCUMENT_ROOT'] . '/../lib/alert.php';
+
+session_start();
+
+if (!MOD_BAN_FILES || !isset($_SESSION['is_moderator'])) {
+ generate_alert(
+ '/',
+ "File ban is not allowed",
+ 403
+ );
+ exit();
+}
+
+if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+ http_response_code(405);
+ exit;
+}
+
+$file_id = $_POST['f'] ?? null;
+$reason = $_POST['reason'] ?? null;
+
+if (!isset($file_id)) {
+ generate_alert(
+ '/',
+ "File ID must be set!",
+ 400
+ );
+ exit();
+}
+
+$file_id = explode('.', $file_id);
+$file_ext = $file_id[1];
+$file_id = $file_id[0];
+
+if (!preg_match('/^[a-zA-Z0-9_-]+$/', $file_id) || !preg_match('/^[a-zA-Z0-9]+$/', $file_ext)) {
+ generate_alert(
+ '/',
+ "File not found",
+ 404
+ );
+ exit();
+}
+
+$file_path = FILE_UPLOAD_DIRECTORY . "/$file_id.$file_ext";
+
+if (!is_file($file_path)) {
+ generate_alert(
+ '/',
+ "File not found",
+ 404
+ );
+ exit;
+}
+
+$db = new PDO(DB_URL, DB_USER, DB_PASS);
+$stmt = $db->prepare('SELECT f.id FROM files f
+ WHERE f.id = ? AND f.extension = ?
+ AND f.id NOT IN (SELECT id FROM file_bans)
+');
+$stmt->execute([$file_id, $file_ext]);
+
+$file = $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
+
+if (!$file) {
+ generate_alert(
+ "/",
+ "File not found",
+ 404
+ );
+ exit();
+}
+
+$file_sha = hash_file('sha256', $file_path);
+
+if (!delete_file($file_id, $file_ext)) {
+ generate_alert(
+ "/$file_id.$file_ext",
+ 'Failed to remove files. Try again later',
+ 500
+ );
+ exit();
+}
+
+$db->prepare('INSERT IGNORE INTO hash_bans(sha256, reason) VALUES (?,?)')
+ ->execute([$file_sha, $reason]);
+
+$db->prepare('INSERT INTO file_bans(id, hash_ban) VALUES (?,?)')
+ ->execute([$file_id, $file_sha]);
+
+generate_alert(
+ $_GET['r'] ?? '/',
+ 'Successfully banned the file',
+ 200,
+ [
+ 'id' => $file_id,
+ 'extension' => $file_ext,
+ 'sha256' => $file_sha,
+ 'reason' => $reason
+ ]
+); \ No newline at end of file
diff --git a/public/catalogue.php b/public/catalogue.php
index 756675a..add156e 100644
--- a/public/catalogue.php
+++ b/public/catalogue.php
@@ -17,7 +17,7 @@ $page = max(intval($_GET['p'] ?? '1') - 1, 0);
$limit = 20;
// counting max pages
-$stmt = $db->query('SELECT COUNT(id) AS all_files FROM files');
+$stmt = $db->query('SELECT COUNT(id) AS all_files FROM files WHERE id NOT IN (SELECT id FROM file_bans)');
$stmt->execute();
$max_pages = ceil(($stmt->fetch(PDO::FETCH_ASSOC)['all_files'] ?: 0) / $limit);
@@ -28,6 +28,7 @@ $offset = $page * $limit;
$stmt = $db->query("SELECT f.id, f.mime, f.extension
FROM files f
+ WHERE f.id NOT IN (SELECT id FROM file_bans)
ORDER BY f.uploaded_at DESC
LIMIT $limit OFFSET $offset
");
diff --git a/public/index.php b/public/index.php
index 7788bbe..b03b063 100644
--- a/public/index.php
+++ b/public/index.php
@@ -40,16 +40,13 @@ if (FILE_CATALOG_FANCY_VIEW && $file_id) {
exit();
}
- $file_path = FILE_UPLOAD_DIRECTORY . "/{$file_id}.{$file_ext}";
-
- if (!file_exists($file_path)) {
- http_response_code(404);
- exit();
- }
-
- $stmt = $db->prepare('SELECT fm.*, f.*
+ $stmt = $db->prepare('SELECT fm.*, f.*,
+ hb.reason AS ban_reason,
+ CASE WHEN fb.hash_ban IS NOT NULL THEN 1 ELSE 0 END AS is_banned
FROM files f
LEFT JOIN file_metadata fm ON fm.id = f.id
+ LEFT JOIN file_bans fb ON fb.id = f.id
+ LEFT JOIN hash_bans hb ON hb.sha256 = fb.hash_ban
WHERE f.id = ? AND f.extension = ?
');
$stmt->execute([$file_id, $file_ext]);
@@ -60,6 +57,8 @@ if (FILE_CATALOG_FANCY_VIEW && $file_id) {
exit();
}
+ $file_exists = is_file(FILE_UPLOAD_DIRECTORY . "/$file_id.$file_ext");
+
// counting views
$viewed_file_ids = $_SESSION['viewed_file_ids'] ?? [];
if (!in_array($file['id'], $viewed_file_ids)) {
@@ -153,54 +152,75 @@ $privacy_exists = is_file($_SERVER['DOCUMENT_ROOT'] . '/static/PRIVACY.txt');
<?php display_alert() ?>
- <section class="file-preview-wrapper">
- <section class="box">
- <div class="tab row gap-8">
- <div class="grow">
- <?php if (isset($file['title'])): ?>
- <p><i><?= $file['title'] ?></i></p>
- <?php else: ?>
- <p>File <?= sprintf('%s.%s', $file['id'], $file['extension']) ?></p>
- <?php endif; ?>
- </div>
- <div class="grow row gap-8 justify-end align-center" id="file-tab-buttons">
- <?php if (isset($_SESSION['is_moderator'])): ?>
- <a href="/delete.php?f=<?= $file['id'] ?>.<?= $file['extension'] ?>">
- <button>Delete</button>
+ <?php if ($file['is_banned']): ?>
+ <section class="box red">
+ <p>Sorry&comma; you cannot access this file as it violated the TOS and was banned from the
+ <?= INSTANCE_NAME ?> servers.
+ </p>
+ <?php if (isset($file['ban_reason'])): ?>
+ <p>Reason: <b><?= $file['ban_reason'] ?></b></p>
+ <?php endif; ?>
+ </section>
+ <?php endif; ?>
+
+ <?php if ($file_exists): ?>
+ <section class="file-preview-wrapper">
+ <section class="box">
+ <div class="tab row gap-8">
+ <div class="grow">
+ <?php if (isset($file['title'])): ?>
+ <p><i><?= $file['title'] ?></i></p>
+ <?php else: ?>
+ <p>File <?= sprintf('%s.%s', $file['id'], $file['extension']) ?></p>
+ <?php endif; ?>
+ </div>
+ <div class="grow row gap-8 justify-end align-center" id="file-tab-buttons">
+ <?php if (isset($_SESSION['is_moderator'])): ?>
+ <a href="/delete.php?f=<?= $file['id'] ?>.<?= $file['extension'] ?>">
+ <button>Delete</button>
+ </a>
+ <?php if (MOD_BAN_FILES): ?>
+ <form action="/ban.php" method="post" class="row gap-4">
+ <input type="text" name="f" value="<?= $file['id'] ?>.<?= $file['extension'] ?>"
+ style="display:none">
+ <input type="text" name="reason" placeholder="Ban reason">
+ <button type="submit">Ban</button>
+ </form>
+ <?php endif; ?>
+ <?php endif; ?>
+ <?php if (FILE_REPORT): ?>
+ <a href="/report.php?f=<?= $file['id'] ?>.<?= $file['extension'] ?>">
+ <button>Report</button>
+ </a>
+ <?php endif; ?>
+ <a href="<?= $file['full_url'] ?>">
+ <button>Full size</button>
</a>
- <?php endif; ?>
- <?php if (FILE_REPORT): ?>
- <a href="/report.php?f=<?= $file['id'] ?>.<?= $file['extension'] ?>">
- <button>Report</button>
+ <a href="<?= $file['full_url'] ?>" download="<?= $file['name'] ?>">
+ <button>Download</button>
</a>
+ </div>
+ </div>
+ <div class="content column file-preview">
+ <?php if (str_starts_with($file['mime'], 'image/')): ?>
+ <img src="<?= $file['full_url'] ?>" alt="Image file.">
+ <?php elseif (str_starts_with($file['mime'], 'video/')): ?>
+ <video controls autoplay>
+ <source src="<?= $file['full_url'] ?>" type="<?= $file['mime'] ?>">
+ </video>
+ <?php elseif (str_starts_with($file['mime'], 'audio/')): ?>
+ <audio controls autoplay>
+ <source src="<?= $file['full_url'] ?>" type="<?= $file['mime'] ?>">
+ </audio>
+ <?php elseif (str_starts_with($file['mime'], 'text/')): ?>
+ <pre><?= file_get_contents(FILE_UPLOAD_DIRECTORY . "/{$file['id']}.{$file['extension']}") ?></pre>
+ <?php else: ?>
+ <p><i>This file cannot be displayed.</i></p>
<?php endif; ?>
- <a href="<?= $file['full_url'] ?>">
- <button>Full size</button>
- </a>
- <a href="<?= $file['full_url'] ?>" download="<?= $file['name'] ?>">
- <button>Download</button>
- </a>
</div>
- </div>
- <div class="content column file-preview">
- <?php if (str_starts_with($file['mime'], 'image/')): ?>
- <img src="<?= $file['full_url'] ?>" alt="Image file.">
- <?php elseif (str_starts_with($file['mime'], 'video/')): ?>
- <video controls autoplay>
- <source src="<?= $file['full_url'] ?>" type="<?= $file['mime'] ?>">
- </video>
- <?php elseif (str_starts_with($file['mime'], 'audio/')): ?>
- <audio controls autoplay>
- <source src="<?= $file['full_url'] ?>" type="<?= $file['mime'] ?>">
- </audio>
- <?php elseif (str_starts_with($file['mime'], 'text/')): ?>
- <pre><?= file_get_contents(FILE_UPLOAD_DIRECTORY . "/{$file['id']}.{$file['extension']}") ?></pre>
- <?php else: ?>
- <p><i>This file cannot be displayed.</i></p>
- <?php endif; ?>
- </div>
+ </section>
</section>
- </section>
+ <?php endif; ?>
<?php else: ?>
<?php html_big_navbar() ?>
@@ -324,7 +344,7 @@ $privacy_exists = is_file($_SERVER['DOCUMENT_ROOT'] . '/static/PRIVACY.txt');
</tr>
<?php endif; ?>
</table>
- <button type="submit">Upload</button>
+ <button type="submit" class="fancy">Upload</button>
</form>
</div>
</div>
diff --git a/public/mod.php b/public/mod.php
index de789ce..728222e 100644
--- a/public/mod.php
+++ b/public/mod.php
@@ -66,7 +66,7 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
<td><input type="password" name="password" required></td>
</tr>
</table>
- <button type="submit">Log in</button>
+ <button type="submit" class="fancy">Log in</button>
</form>
<?php endif; ?>
</main>
diff --git a/public/static/style.css b/public/static/style.css
index 7298fcb..2194b28 100644
--- a/public/static/style.css
+++ b/public/static/style.css
@@ -29,12 +29,12 @@
--anchor-color-hovered: #ff9696;
}
- button[type=submit] {
+ button[type=submit].fancy {
background: var(--box-tab-background);
color: var(--box-tab-foreground);
}
- button[type=submit]:hover {
+ button[type=submit].fancy:hover {
background: var(--box-tab-background);
}
@@ -139,14 +139,14 @@ table.left td {
}
/** FORM */
-button[type=submit] {
+button[type=submit].fancy {
background: linear-gradient(0deg, var(--box-tab-background), var(--background));
padding: 8px;
font-size: 18px;
border: 1px solid var(--box-border);
}
-button[type=submit]:hover {
+button[type=submit].fancy:hover {
background: linear-gradient(180deg, var(--box-tab-background), var(--background));
cursor: pointer;
}
@@ -173,6 +173,12 @@ button[type=submit]:hover {
.box {
background: var(--box-content-background);
border: 2px solid var(--box-border);
+ padding: 8px;
+}
+
+.box.red {
+ background: var(--box-tab-foreground);
+ color: var(--background);
}
.box>.tabs {
@@ -186,6 +192,7 @@ button[type=submit]:hover {
.box:has(.tabs),
.box:has(.tab) {
+ padding: 0;
background: none;
border: none;
}
diff --git a/public/upload.php b/public/upload.php
index 0a6be1d..8ad01e1 100644
--- a/public/upload.php
+++ b/public/upload.php
@@ -172,6 +172,15 @@ try {
throw new RuntimeException("Failed to save the file. Try again later.");
}
+ // checking if this is a banned file
+ $file_sha = hash_file('sha256', $file_path);
+ $stmt = $db->prepare('SELECT reason FROM hash_bans WHERE sha256 = ?');
+ $stmt->execute([$file_sha]);
+ if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ delete_file($file_id, $file_data['extension']);
+ throw new RuntimeException('This file is not allowed for upload.' . (isset($row['reason']) ? ' Reason: ' . $row['reason'] : ''));
+ }
+
$file_data['size'] = filesize($file_path);
if (FILE_THUMBNAILS && !is_dir(FILE_THUMBNAIL_DIRECTORY) && !mkdir(FILE_THUMBNAIL_DIRECTORY, 0777, true)) {