mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
fix: session boot on POST path, consolidate rate limiter via checkKey()
This commit is contained in:
@@ -29,6 +29,9 @@ if (!preg_match('#^\d{8}-[A-Z0-9+/]{8}$#', $slug)) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Boot for all requests: starts session, initialises DB, ensures CSRF token.
|
||||
App::boot();
|
||||
|
||||
// ── POST: form submission ─────────────────────────────────────────────────────
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'submit') {
|
||||
handleShareLinkSubmission($slug);
|
||||
@@ -36,7 +39,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'submit') {
|
||||
}
|
||||
|
||||
// ── GET: render form ─────────────────────────────────────────────────────────
|
||||
App::boot(); // boot database + CSRF
|
||||
|
||||
require_once APP_ROOT . '/src/ShareLink.php';
|
||||
$shareLinkModel = new ShareLink(Database::getInstance());
|
||||
@@ -480,7 +482,11 @@ function renderShareLinkForm(string $slug, array $link): void
|
||||
*/
|
||||
function handleShareLinkSubmission(string $slug): void
|
||||
{
|
||||
session_start();
|
||||
// Session already started by App::boot() on the GET path; start here
|
||||
// only if somehow not yet active (e.g. direct POST without prior GET).
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
require_once APP_ROOT . '/src/ShareLink.php';
|
||||
require_once APP_ROOT . '/src/RateLimit.php';
|
||||
@@ -496,33 +502,16 @@ function handleShareLinkSubmission(string $slug): void
|
||||
}
|
||||
|
||||
// ── Rate limiting ────────────────────────────────────────────────────────
|
||||
// Allow max 5 submissions per IP per 10 minutes (per share link)
|
||||
// 5 submissions per IP per 10 minutes, keyed per share link.
|
||||
$rateLimitCacheDir = STORAGE_ROOT . '/cache/rate_limit';
|
||||
if (!is_dir($rateLimitCacheDir)) {
|
||||
@mkdir($rateLimitCacheDir, 0755, true);
|
||||
}
|
||||
$shareRateLimitId = 'share_' . $slug . '_' . ($_SERVER['REMOTE_ADDR'] ?? 'unknown');
|
||||
$rateLimit = new RateLimit(5, 600, $rateLimitCacheDir);
|
||||
$shareRateLimitId = 'share_' . $slug . '_' . ($_SERVER['REMOTE_ADDR'] ?? 'unknown');
|
||||
$rateLimit = new RateLimit(5, 600, $rateLimitCacheDir);
|
||||
|
||||
// Use a custom identifier based on slug + IP so each share link is rate-limited independently
|
||||
$rateLimitFile = $rateLimitCacheDir . '/' . md5($shareRateLimitId) . '.json';
|
||||
$data = [];
|
||||
if (file_exists($rateLimitFile)) {
|
||||
$content = file_get_contents($rateLimitFile);
|
||||
$data = json_decode($content, true) ?? [];
|
||||
}
|
||||
$now = time();
|
||||
$data = array_filter($data, fn($ts) => ($now - $ts) < 600);
|
||||
|
||||
if (count($data) >= 5) {
|
||||
if (!$rateLimit->checkKey($shareRateLimitId)) {
|
||||
$_SESSION['_flash_error'] = 'Trop de tentatives. Veuillez réessayer plus tard.';
|
||||
header('Location: /partage/' . urlencode($slug));
|
||||
exit;
|
||||
}
|
||||
$data[] = $now;
|
||||
if (is_writable($rateLimitCacheDir)) {
|
||||
file_put_contents($rateLimitFile, json_encode($data));
|
||||
}
|
||||
// ── End rate limiting ────────────────────────────────────────────────────
|
||||
|
||||
// Check password verification if link has a password
|
||||
|
||||
Reference in New Issue
Block a user