feat: add rate limiting and input validation to contact form

- Rate limit: 5 req/min per IP (file-based)
- Email format validation via filter_var
- Field length limits: name 100, email 254, phone 30, message 5000

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-15 07:29:27 +03:00
parent 7decd512c9
commit a42007e0a5

View File

@@ -10,6 +10,25 @@ if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
exit;
}
// ─── Rate limiting (5 requests per minute per IP) ────────────────────────────
$ip = $_SERVER['HTTP_X_FORWARDED_FOR']
? explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0]
: ($_SERVER['REMOTE_ADDR'] ?? 'unknown');
$ip = trim($ip);
$rate_file = sys_get_temp_dir() . '/rl_' . md5($ip) . '.json';
$now = time();
$window = 60;
$max_req = 5;
$rate_data = file_exists($rate_file) ? json_decode(file_get_contents($rate_file), true) : [];
$rate_data = array_filter($rate_data ?? [], fn($t) => $t > $now - $window);
if (count($rate_data) >= $max_req) {
http_response_code(429);
echo json_encode(['error' => 'Too many requests. Please try again later.']);
exit;
}
$rate_data[] = $now;
file_put_contents($rate_file, json_encode(array_values($rate_data)));
$data = json_decode(file_get_contents('php://input'), true);
if (!$data) {
http_response_code(400);
@@ -28,6 +47,17 @@ if (!$name || !$message) {
exit;
}
// ─── Validation ───────────────────────────────────────────────────────────────
if ($email && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
http_response_code(400);
echo json_encode(['error' => 'Invalid email format']);
exit;
}
if (mb_strlen($name) > 100) { http_response_code(400); echo json_encode(['error' => 'Name too long']); exit; }
if (mb_strlen($email) > 254) { http_response_code(400); echo json_encode(['error' => 'Email too long']); exit; }
if (mb_strlen($phone) > 30) { http_response_code(400); echo json_encode(['error' => 'Phone too long']); exit; }
if (mb_strlen($message) > 5000) { http_response_code(400); echo json_encode(['error' => 'Message too long']); exit; }
// ─── Telegram (best-effort, not fatal) ───────────────────────────────────────
$BOT_TOKEN = '8138813013:AAElH2L5NspRLSdiFjDz6Qf32n4G24P_cj8';
$CHAT_ID = '-5230603582';