first commit

This commit is contained in:
2026-02-03 09:01:55 +01:00
commit 52e26e3989
114 changed files with 94751 additions and 0 deletions

261
forms/contact.php Normal file
View 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()
]);
}