first commit
This commit is contained in:
261
forms/contact.php
Normal file
261
forms/contact.php
Normal file
@@ -0,0 +1,261 @@
|
||||
<?php
|
||||
// Fehlerausgabe komplett deaktivieren
|
||||
error_reporting(0);
|
||||
ini_set('display_errors', 0);
|
||||
ini_set('log_errors', 1);
|
||||
ini_set('error_log', '/path/to/error.log'); // Optional: Fehler in Log-Datei schreiben
|
||||
|
||||
// Buffer starten
|
||||
ob_start();
|
||||
|
||||
// Sicherheitskonstante setzen
|
||||
define('CONFIG_LOADED', true);
|
||||
|
||||
// Config laden (prüfe zuerst außerhalb des webroot)
|
||||
if (file_exists(__DIR__ . '/../config.php')) {
|
||||
require_once __DIR__ . '/../config.php';
|
||||
} elseif (file_exists(__DIR__ . '/config.php')) {
|
||||
require_once __DIR__ . '/config.php';
|
||||
} else {
|
||||
die('Configuration file not found');
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../assets/vendor/php-email-form/php-email-form.php';
|
||||
|
||||
// Rate Limiting mit Konstanten aus Config
|
||||
function checkRateLimit() {
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
$file = sys_get_temp_dir() . '/email_' . hash('sha256', $ip . date('Y-m-d-H'));
|
||||
|
||||
if (file_exists($file)) {
|
||||
$data = json_decode(file_get_contents($file), true);
|
||||
$now = time();
|
||||
|
||||
// Max RATE_LIMIT_MAX E-Mails pro RATE_LIMIT_WINDOW
|
||||
if ($data['count'] >= RATE_LIMIT_MAX && ($now - $data['timestamp']) < RATE_LIMIT_WINDOW) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (($now - $data['timestamp']) >= RATE_LIMIT_WINDOW) {
|
||||
$data = ['count' => 1, 'timestamp' => $now];
|
||||
} else {
|
||||
$data['count']++;
|
||||
}
|
||||
} else {
|
||||
$data = ['count' => 1, 'timestamp' => time()];
|
||||
}
|
||||
|
||||
file_put_contents($file, json_encode($data), LOCK_EX);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Erweiterte Validierung mit XSS-Schutz
|
||||
function validateInput($data) {
|
||||
// Leere Felder prüfen
|
||||
if (empty($data['name']) || empty($data['email']) || empty($data['message'])) {
|
||||
return ['valid' => false, 'message' => 'Bitte füllen Sie alle Pflichtfelder aus.'];
|
||||
}
|
||||
|
||||
// E-Mail-Format prüfen
|
||||
if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
return ['valid' => false, 'message' => 'Bitte geben Sie eine gültige E-Mail-Adresse ein.'];
|
||||
}
|
||||
|
||||
// Zusätzliche E-Mail-Validierung (keine Header-Injection)
|
||||
if (preg_match('/[\r\n]/', $data['email']) || preg_match('/[\r\n]/', $data['name'])) {
|
||||
return ['valid' => false, 'message' => 'Ungültige Zeichen erkannt.'];
|
||||
}
|
||||
|
||||
// Längenbeschränkungen
|
||||
if (strlen($data['name']) > 100) {
|
||||
return ['valid' => false, 'message' => 'Der Name ist zu lang.'];
|
||||
}
|
||||
|
||||
if (strlen($data['message']) < 10) {
|
||||
return ['valid' => false, 'message' => 'Ihre Nachricht ist zu kurz.'];
|
||||
}
|
||||
|
||||
if (strlen($data['message']) > 5000) {
|
||||
return ['valid' => false, 'message' => 'Ihre Nachricht ist zu lang.'];
|
||||
}
|
||||
|
||||
// Spam-Wörter aus Config prüfen
|
||||
foreach (SPAM_WORDS as $word) {
|
||||
if (stripos($data['message'], $word) !== false || stripos($data['name'], $word) !== false) {
|
||||
return ['valid' => false, 'message' => 'Ihre Nachricht wurde als Spam erkannt.'];
|
||||
}
|
||||
}
|
||||
|
||||
return ['valid' => true];
|
||||
}
|
||||
|
||||
// XSS-Schutz für Ausgaben
|
||||
function sanitizeOutput($string) {
|
||||
return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
// reCAPTCHA Validierung mit Config-Konstante
|
||||
function validateRecaptcha($recaptchaResponse) {
|
||||
if (empty($recaptchaResponse)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$secret = RECAPTCHA_SECRET;
|
||||
$url = 'https://www.google.com/recaptcha/api/siteverify';
|
||||
$data = [
|
||||
'secret' => $secret,
|
||||
'response' => $recaptchaResponse,
|
||||
'remoteip' => $_SERVER['REMOTE_ADDR']
|
||||
];
|
||||
|
||||
$options = [
|
||||
'http' => [
|
||||
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
|
||||
'method' => 'POST',
|
||||
'content' => http_build_query($data),
|
||||
'timeout' => 10
|
||||
],
|
||||
'ssl' => [
|
||||
'verify_peer' => true,
|
||||
'verify_peer_name' => true,
|
||||
]
|
||||
];
|
||||
|
||||
$context = stream_context_create($options);
|
||||
$result = @file_get_contents($url, false, $context);
|
||||
|
||||
if ($result === false) {
|
||||
error_log('reCAPTCHA API request failed');
|
||||
return false;
|
||||
}
|
||||
|
||||
$responseData = json_decode($result);
|
||||
return isset($responseData->success) && $responseData->success === true;
|
||||
}
|
||||
|
||||
// Honeypot-Feld prüfen
|
||||
if (!empty($_POST['website'])) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Spam erkannt.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Zeitbasierte Validierung mit Config-Konstante
|
||||
if (isset($_POST['form_start'])) {
|
||||
$delta = time() - intval($_POST['form_start'] / 1000);
|
||||
if ($delta < MIN_FORM_TIME) { // Zu schnell ausgefüllt
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Zu schnell abgesendet. Bitte versuchen Sie es erneut.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Hauptlogik
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
echo json_encode(['success' => false, 'message' => 'Nur POST-Requests erlaubt']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
// Rate Limit prüfen
|
||||
if (!checkRateLimit()) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Aus Sicherheitsgründen können Sie nur 5 Nachrichten pro Stunde senden. Bitte versuchen Sie es später erneut.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// reCAPTCHA prüfen
|
||||
$recaptchaResponse = $_POST['g-recaptcha-response'] ?? '';
|
||||
if (!validateRecaptcha($recaptchaResponse)) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Bitte bestätigen Sie, dass Sie kein Robot sind.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Formulardaten sammeln und bereinigen
|
||||
$formData = [
|
||||
'name' => trim($_POST['name'] ?? ''),
|
||||
'email' => trim($_POST['email'] ?? ''),
|
||||
'mobile' => trim($_POST['mobilenumber'] ?? ''),
|
||||
'message' => trim($_POST['message'] ?? '')
|
||||
];
|
||||
|
||||
|
||||
// E-Mail-Domain-Blacklist aus Config
|
||||
foreach (SPAM_DOMAINS as $domain) {
|
||||
if (stripos($formData['email'], $domain) !== false) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Bitte verwenden Sie eine echte E-Mail-Adresse.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Eingaben validieren
|
||||
$validation = validateInput($formData);
|
||||
if (!$validation['valid']) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => $validation['message']
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// E-Mail erstellen
|
||||
$contact = new PHP_Email_Form;
|
||||
$contact->ajax = true;
|
||||
$contact->to = RECEIVING_EMAIL;
|
||||
$contact->from_name = $formData['name'];
|
||||
$contact->from_email = 'hkw@webfarben.net';
|
||||
$contact->reply_to = $formData['email'];
|
||||
$contact->subject = "Neue Kontaktanfrage von " . $formData['name'];
|
||||
$contact->smtp = SMTP_CONFIG;
|
||||
|
||||
// Nachricht zusammenbauen
|
||||
$contact->add_message($formData['name'], 'Name');
|
||||
$contact->add_message($formData['email'], 'E-Mail');
|
||||
$contact->add_message($formData['mobile'], 'Telefon');
|
||||
$contact->add_message($formData['message'], 'Nachricht');
|
||||
|
||||
// Dateianhang verarbeiten mit Sicherheitschecks
|
||||
if (isset($_FILES['resume']) && $_FILES['resume']['error'] == UPLOAD_ERR_OK) {
|
||||
// Dateigröße prüfen
|
||||
if ($_FILES['resume']['size'] > MAX_FILE_SIZE) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Die Datei ist zu groß (max. 20 MB).'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$contact->add_attachment('resume', 20, ALLOWED_FILE_TYPES);
|
||||
}
|
||||
|
||||
// E-Mail senden
|
||||
$result = $contact->send();
|
||||
|
||||
echo json_encode([
|
||||
'success' => ($result === 'OK'),
|
||||
'message' => ($result === 'OK')
|
||||
? "Ihre Nachricht wurde erfolgreich gesendet an: " . RECEIVING_EMAIL
|
||||
: "Fehler beim Senden: " . $result
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log("Mailer Error: " . $e->getMessage());
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "Ein Fehler ist aufgetreten: " . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
Reference in New Issue
Block a user