Files
provoc-website/contact.php
kutesir fe5f232c6a Initial commit — Provoc Group website
Full website with security hardening:
- Redesigned sections: hero, services, capabilities, clients, partners, stats, about, workflow, contact
- Contact form fixed (variable names, XSS sanitisation, rate limiting, open redirect removed)
- .htaccess with security headers (CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy)
- error_log blocked from public access
- Robots.txt corrected to allow JS/CSS for SEO rendering
2026-05-16 21:26:49 +03:00

127 lines
3.7 KiB
PHP

<?php
// Only handle POST requests
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit('Method Not Allowed');
}
// Basic rate limiting via session (max 3 submissions per hour per IP)
session_start();
$ip = $_SERVER['REMOTE_ADDR'];
$key = 'cf_submissions_' . md5($ip);
$now = time();
if (!isset($_SESSION[$key])) {
$_SESSION[$key] = [];
}
// Keep only submissions within the last hour
$_SESSION[$key] = array_filter($_SESSION[$key], fn($t) => $now - $t < 3600);
if (count($_SESSION[$key]) >= 3) {
if ($this_is_ajax()) {
http_response_code(429);
echo json_encode(['form_ok' => false, 'errors' => ['Too many submissions. Please try again later.']]);
} else {
header('Location: /');
exit;
}
}
function this_is_ajax(): bool {
return !empty($_SERVER['HTTP_X_REQUESTED_WITH'])
&& strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
}
function h(string $str): string {
return htmlspecialchars($str, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
$formok = true;
$errors = [];
$date = date('d/m/Y');
$time = date('H:i:s');
// Read and sanitise inputs
$name = trim($_POST['Name'] ?? '');
$email = trim($_POST['Email'] ?? '');
$telephone = trim($_POST['Phone'] ?? '');
$message = trim($_POST['message'] ?? '');
// Validate name
if ($name === '') {
$formok = false;
$errors[] = 'You have not entered a name';
}
// Validate email
if ($email === '') {
$formok = false;
$errors[] = 'You have not entered an email address';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$formok = false;
$errors[] = 'You have not entered a valid email address';
}
// Validate message
if ($message === '') {
$formok = false;
$errors[] = 'You have not entered a message';
} elseif (strlen($message) < 20) {
$formok = false;
$errors[] = 'Your message must be at least 20 characters';
}
// Strip newlines from header-injectable fields (mail header injection defence)
$name = str_replace(["\r", "\n"], ' ', $name);
$email = str_replace(["\r", "\n"], ' ', $email);
$telephone = str_replace(["\r", "\n"], ' ', $telephone);
if ($formok) {
// Record this submission in the rate-limit bucket
$_SESSION[$key][] = $now;
$to = 'info@provoc.ug';
$subject = 'New Enquiry from Website';
$headers = "From: noreply@provocgroup.com\r\n";
$headers .= "Reply-To: " . h($email) . "\r\n";
$headers .= "Content-Type: text/html; charset=UTF-8\r\n";
$headers .= "X-Mailer: PHP/" . phpversion() . "\r\n";
$emailbody = "
<html><body style=\"font-family:Arial,sans-serif;font-size:14px;color:#333\">
<p>You have received a new enquiry from the website contact form.</p>
<table cellpadding=\"6\" cellspacing=\"0\" border=\"0\">
<tr><td><strong>Name:</strong></td><td>" . h($name) . "</td></tr>
<tr><td><strong>Email:</strong></td><td>" . h($email) . "</td></tr>
<tr><td><strong>Phone:</strong></td><td>" . h($telephone) . "</td></tr>
<tr><td><strong>Message:</strong></td><td>" . nl2br(h($message)) . "</td></tr>
<tr><td><strong>IP:</strong></td><td>" . h($ip) . "</td></tr>
<tr><td><strong>Date/Time:</strong></td><td>" . h($date) . " " . h($time) . "</td></tr>
</table>
</body></html>";
mail($to, $subject, $emailbody, $headers);
}
$returndata = [
'posted_form_data' => [
'name' => $name,
'email' => $email,
'phone' => $telephone,
'message' => $message,
],
'form_ok' => $formok,
'errors' => $errors,
];
if (this_is_ajax()) {
header('Content-Type: application/json');
echo json_encode($returndata);
exit;
}
// Non-AJAX: redirect back to homepage (never to user-supplied Referer)
$_SESSION['cf_returndata'] = $returndata;
header('Location: /');
exit;