Add content and translations
This commit is contained in:
parent
a273a7a7a0
commit
f949439ebf
49 changed files with 1192 additions and 346 deletions
7
content/kontakt/00-some.en.md
Normal file
7
content/kontakt/00-some.en.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
## Follow us on social media
|
||||
|
||||
- [Facebook](https://www.facebook.com/StoppLidelsen/)
|
||||
- [Instagram](https://www.instagram.com/stopplidelsen/)
|
||||
- [Mastodon](https://oslo.town/@stopplidelsen)
|
||||
|
||||
<a class="button" href="/en/om-oss">Learn more about us</a>
|
||||
277
content/kontakt/01-kontaktskjema.en.php
Normal file
277
content/kontakt/01-kontaktskjema.en.php
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
<?php
|
||||
// Contact form processing with spam prevention
|
||||
$formSubmitted = false;
|
||||
$formSuccess = false;
|
||||
$formErrors = [];
|
||||
$formData = ['name' => '', 'email' => '', 'message' => ''];
|
||||
|
||||
// Start session for CSRF token and rate limiting
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
// Generate CSRF token if not exists
|
||||
if (empty($_SESSION['csrf_token'])) {
|
||||
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
||||
}
|
||||
|
||||
// Process form submission
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['contact_form_submit'])) {
|
||||
$formSubmitted = true;
|
||||
|
||||
// Security: CSRF Token Validation
|
||||
if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
|
||||
$formErrors[] = 'Invalid security code. Please try again.';
|
||||
}
|
||||
|
||||
// Spam Prevention 1: Honeypot field (should be empty)
|
||||
if (!empty($_POST['website'])) {
|
||||
$formErrors[] = 'Spam detected.';
|
||||
}
|
||||
|
||||
// Spam Prevention 2: Time-based check (form must be visible for at least 3 seconds)
|
||||
$formStartTime = isset($_POST['form_start_time']) ? (int)$_POST['form_start_time'] : 0;
|
||||
$timeDiff = time() - $formStartTime;
|
||||
if ($timeDiff < 3) {
|
||||
$formErrors[] = 'Form submitted too quickly.';
|
||||
}
|
||||
|
||||
// Spam Prevention 3: Referrer check (only if referrer is present and clearly from different domain)
|
||||
if (!empty($_SERVER['HTTP_REFERER'])) {
|
||||
$referrer = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
|
||||
$currentHost = $_SERVER['HTTP_HOST'];
|
||||
// Only block if referrer exists and doesn't match (allows empty referrer for privacy browsers)
|
||||
if ($referrer && $referrer !== $currentHost && $referrer !== 'localhost') {
|
||||
$formErrors[] = 'Invalid form submission.';
|
||||
}
|
||||
}
|
||||
|
||||
// Spam Prevention 4: Rate limiting (session-based)
|
||||
$lastSubmitTime = isset($_SESSION['last_contact_submit']) ? $_SESSION['last_contact_submit'] : 0;
|
||||
if (time() - $lastSubmitTime < 60) {
|
||||
$formErrors[] = 'Please wait a bit before submitting again.';
|
||||
}
|
||||
|
||||
// Get and sanitize form data
|
||||
$formData['name'] = trim($_POST['name'] ?? '');
|
||||
$formData['email'] = trim($_POST['email'] ?? '');
|
||||
// Normalize line endings in message (convert \r\n to \n)
|
||||
$formData['message'] = trim(str_replace("\r\n", "\n", $_POST['message'] ?? ''));
|
||||
|
||||
// Validation
|
||||
if (empty($formData['name'])) {
|
||||
$formErrors[] = 'Please provide your name.';
|
||||
} elseif (strlen($formData['name']) > 100) {
|
||||
$formErrors[] = 'The name is too long.';
|
||||
}
|
||||
|
||||
if (empty($formData['email'])) {
|
||||
$formErrors[] = 'Please provide your email address.';
|
||||
} elseif (!filter_var($formData['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
$formErrors[] = 'Invalid email address.';
|
||||
} elseif (strlen($formData['email']) > 100) {
|
||||
$formErrors[] = 'The email address is too long.';
|
||||
}
|
||||
|
||||
if (empty($formData['message'])) {
|
||||
$formErrors[] = 'Please write a message.';
|
||||
} elseif (strlen($formData['message']) < 10) {
|
||||
$formErrors[] = 'The message is too short (minimum 10 characters).';
|
||||
} elseif (strlen($formData['message']) > 5000) {
|
||||
$formErrors[] = 'The message is too long (maximum 5000 characters).';
|
||||
}
|
||||
|
||||
// Spam Prevention 5: Check for suspicious patterns
|
||||
$spamPatterns = [
|
||||
'/\[url=/i',
|
||||
'/\[link=/i',
|
||||
'/<a href=/i',
|
||||
'/viagra|cialis|casino|poker|lottery/i',
|
||||
'/http.*http.*http/i', // Multiple URLs
|
||||
];
|
||||
|
||||
$fullText = $formData['name'] . ' ' . $formData['email'] . ' ' . $formData['message'];
|
||||
foreach ($spamPatterns as $pattern) {
|
||||
if (preg_match($pattern, $fullText)) {
|
||||
$formErrors[] = 'The message contains non-allowed content.';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no errors, send email
|
||||
if (empty($formErrors)) {
|
||||
// Load SMTP configuration
|
||||
$smtpConfig = require __DIR__ . '/../../custom/smtp-config.php';
|
||||
|
||||
// Prepare email body
|
||||
$emailBody = "New inquiry from the contact form on stopplidelsen.no\n\n";
|
||||
$emailBody .= "Name: " . $formData['name'] . "\n";
|
||||
$emailBody .= "Email: " . $formData['email'] . "\n";
|
||||
$emailBody .= "IP address: " . $_SERVER['REMOTE_ADDR'] . "\n";
|
||||
$emailBody .= "Timestamp: " . date('Y-m-d H:i:s') . "\n\n";
|
||||
$emailBody .= "Message:\n" . $formData['message'] . "\n";
|
||||
|
||||
$mailSent = false;
|
||||
|
||||
// Try PHPMailer.Lite if SMTP is configured
|
||||
if ($smtpConfig['enabled']) {
|
||||
// Pre-flight check: Test SMTP connection before attempting to send
|
||||
$smtpConnectable = false;
|
||||
$fp = @fsockopen($smtpConfig['host'], $smtpConfig['port'], $errno, $errstr, 10);
|
||||
if ($fp) {
|
||||
// Successfully connected
|
||||
$smtpConnectable = true;
|
||||
fclose($fp);
|
||||
} else {
|
||||
error_log("SMTP Pre-flight check failed: Cannot connect to {$smtpConfig['host']}:{$smtpConfig['port']} - Error: $errno - $errstr");
|
||||
$formErrors[] = 'An error occurred while sending the message. Please try again later.';
|
||||
}
|
||||
|
||||
if ($smtpConnectable) {
|
||||
try {
|
||||
require_once __DIR__ . '/../../custom/vendor/PHPMailer.Lite.php';
|
||||
|
||||
$mail = new \codeworxtech\PHPMailerLite\PHPMailerLite();
|
||||
|
||||
// Enable debug output in development
|
||||
// $mail->debug = 1; // Uncomment to see SMTP debug output
|
||||
|
||||
$mail->SetSMTPhost($smtpConfig['host']);
|
||||
$mail->SetSMTPport($smtpConfig['port']);
|
||||
$mail->SetSMTPuser($smtpConfig['username']);
|
||||
$mail->SetSMTPpass($smtpConfig['password']);
|
||||
|
||||
$mail->SetSender([$smtpConfig['from_email'] => $smtpConfig['from_name']]);
|
||||
$mail->AddRecipient([$smtpConfig['to_email'] => $smtpConfig['to_name']]);
|
||||
$mail->AddReplyTo([$formData['email'] => $formData['name']]);
|
||||
$mail->SetSubject('New inquiry from contact form');
|
||||
$mail->SetBodyText($emailBody);
|
||||
|
||||
// Capture any output from PHPMailer.Lite (it might exit() on error)
|
||||
ob_start();
|
||||
$mailSent = @$mail->Send('smtp');
|
||||
$smtpOutput = ob_get_clean();
|
||||
|
||||
// Check if there was an error in the output
|
||||
if (!$mailSent || stripos($smtpOutput, 'error') !== false || stripos($smtpOutput, '✗') !== false) {
|
||||
$mailSent = false;
|
||||
error_log("SMTP Send failed. Output: " . strip_tags($smtpOutput));
|
||||
$formErrors[] = 'An error occurred while sending the message. Please try again later.';
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$mailSent = false;
|
||||
error_log("PHPMailer Exception: " . $e->getMessage());
|
||||
$formErrors[] = 'An error occurred while sending the message. Please try again later.';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Fallback to native mail() function
|
||||
$headers = "From: kontaktskjema@stopplidelsen.no\r\n";
|
||||
$headers .= "Reply-To: " . $formData['email'] . "\r\n";
|
||||
$headers .= "X-Mailer: PHP/" . phpversion() . "\r\n";
|
||||
$headers .= "Content-Type: text/plain; charset=UTF-8\r\n";
|
||||
|
||||
$mailSent = mail('ruben@stopplidelsen.no', 'New inquiry from contact form', $emailBody, $headers);
|
||||
}
|
||||
|
||||
if ($mailSent) {
|
||||
$formSuccess = true;
|
||||
$_SESSION['last_contact_submit'] = time();
|
||||
|
||||
// Clear form data on success
|
||||
$formData = ['name' => '', 'email' => '', 'message' => ''];
|
||||
} else {
|
||||
if (empty($formErrors)) {
|
||||
$formErrors[] = 'An error occurred while sending the message. Please try again later.';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate form start time token
|
||||
$currentTime = time();
|
||||
?>
|
||||
|
||||
<article class="contain">
|
||||
<h2>Contact Form</h2>
|
||||
|
||||
<p>Do you have questions, suggestions or want to participate in our work? Fill out the form below! But remember that it may take time before you get a response, we are not many and run everything on a voluntary basis.</p>
|
||||
|
||||
<section class="contact-form">
|
||||
<?php if ($formSuccess): ?>
|
||||
<div class="form-success">
|
||||
<p><strong>Thank you for your inquiry!</strong></p>
|
||||
<p>We have received your message and will respond as soon as possible.</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($formErrors)): ?>
|
||||
<div class="form-errors">
|
||||
<p><strong>Please correct the following:</strong></p>
|
||||
<ul>
|
||||
<?php foreach ($formErrors as $error): ?>
|
||||
<li><?= htmlspecialchars($error) ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!$formSuccess): ?>
|
||||
<form method="post" action="<?= htmlspecialchars($_SERVER['REQUEST_URI']) ?>" class="contact-form-inner">
|
||||
<!-- Honeypot field (hidden from users, bots will fill it) -->
|
||||
<div class="hp-field" aria-hidden="true">
|
||||
<label for="website">Website</label>
|
||||
<input type="text" id="website" name="website" tabindex="-1" autocomplete="off">
|
||||
</div>
|
||||
|
||||
<!-- CSRF Token -->
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
||||
|
||||
<!-- Time-based token -->
|
||||
<input type="hidden" name="form_start_time" value="<?= $currentTime ?>">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="contact_name">Name <span class="required">*</span></label>
|
||||
<input
|
||||
type="text"
|
||||
id="contact_name"
|
||||
name="name"
|
||||
value="<?= htmlspecialchars($formData['name']) ?>"
|
||||
required
|
||||
maxlength="100"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="contact_email">Email address <span class="required">*</span></label>
|
||||
<input
|
||||
type="email"
|
||||
id="contact_email"
|
||||
name="email"
|
||||
value="<?= htmlspecialchars($formData['email']) ?>"
|
||||
required
|
||||
maxlength="100"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="contact_message">Message <span class="required">*</span></label>
|
||||
<textarea
|
||||
id="contact_message"
|
||||
name="message"
|
||||
rows="8"
|
||||
required
|
||||
minlength="10"
|
||||
maxlength="5000"
|
||||
><?= htmlspecialchars($formData['message']) ?></textarea>
|
||||
<small>Minimum 10 characters, maximum 5000 characters.</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit" name="contact_form_submit" class="button">Send message</button>
|
||||
</div>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
</article>
|
||||
Loading…
Add table
Add a link
Reference in a new issue