chore(release): obfuscate and hash production assets [skip ci]
This commit is contained in:
@@ -1,21 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* HexaDNS - DNS Lookup API
|
||||
*
|
||||
* Führt echte DNS-Abfragen durch und gibt die Ergebnisse als JSON zurück.
|
||||
*
|
||||
* Verwendung: GET /api/dns-lookup.php?domain=example.com
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
require_once __DIR__ . '/../includes/api-helpers.php';
|
||||
|
||||
// CORS Headers für Frontend-Zugriff
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
header('Access-Control-Allow-Methods: GET, OPTIONS');
|
||||
header('Access-Control-Allow-Headers: Content-Type');
|
||||
|
||||
// Preflight request handling
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
||||
http_response_code(200);
|
||||
exit;
|
||||
@@ -39,12 +39,12 @@ if ($domain === null) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// DNS-Abfrage durchführen
|
||||
|
||||
$startTime = microtime(true);
|
||||
$result = performDnsLookup($domain);
|
||||
$queryTime = round((microtime(true) - $startTime) * 1000, 2);
|
||||
|
||||
// Ergebnis zurückgeben
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'domain' => $domain,
|
||||
@@ -53,9 +53,9 @@ echo json_encode([
|
||||
'records' => $result
|
||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
/**
|
||||
* Führt DNS-Lookup für verschiedene Record-Typen durch
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function performDnsLookup(string $domain): array {
|
||||
$records = [
|
||||
'A' => [],
|
||||
@@ -67,7 +67,7 @@ function performDnsLookup(string $domain): array {
|
||||
'SOA' => []
|
||||
];
|
||||
|
||||
// A-Records (IPv4)
|
||||
|
||||
$aRecords = @dns_get_record($domain, DNS_A);
|
||||
if ($aRecords) {
|
||||
foreach ($aRecords as $record) {
|
||||
@@ -78,7 +78,7 @@ function performDnsLookup(string $domain): array {
|
||||
}
|
||||
}
|
||||
|
||||
// AAAA-Records (IPv6)
|
||||
|
||||
$aaaaRecords = @dns_get_record($domain, DNS_AAAA);
|
||||
if ($aaaaRecords) {
|
||||
foreach ($aaaaRecords as $record) {
|
||||
@@ -89,7 +89,7 @@ function performDnsLookup(string $domain): array {
|
||||
}
|
||||
}
|
||||
|
||||
// MX-Records (Mail)
|
||||
|
||||
$mxRecords = @dns_get_record($domain, DNS_MX);
|
||||
if ($mxRecords) {
|
||||
foreach ($mxRecords as $record) {
|
||||
@@ -99,11 +99,11 @@ function performDnsLookup(string $domain): array {
|
||||
'ttl' => $record['ttl']
|
||||
];
|
||||
}
|
||||
// Nach Priorität sortieren
|
||||
|
||||
usort($records['MX'], fn($a, $b) => $a['priority'] <=> $b['priority']);
|
||||
}
|
||||
|
||||
// NS-Records (Nameserver)
|
||||
|
||||
$nsRecords = @dns_get_record($domain, DNS_NS);
|
||||
if ($nsRecords) {
|
||||
foreach ($nsRecords as $record) {
|
||||
@@ -114,7 +114,7 @@ function performDnsLookup(string $domain): array {
|
||||
}
|
||||
}
|
||||
|
||||
// TXT-Records
|
||||
|
||||
$txtRecords = @dns_get_record($domain, DNS_TXT);
|
||||
if ($txtRecords) {
|
||||
foreach ($txtRecords as $record) {
|
||||
@@ -125,7 +125,7 @@ function performDnsLookup(string $domain): array {
|
||||
}
|
||||
}
|
||||
|
||||
// CNAME-Records
|
||||
|
||||
$cnameRecords = @dns_get_record($domain, DNS_CNAME);
|
||||
if ($cnameRecords) {
|
||||
foreach ($cnameRecords as $record) {
|
||||
@@ -136,7 +136,7 @@ function performDnsLookup(string $domain): array {
|
||||
}
|
||||
}
|
||||
|
||||
// SOA-Record (Start of Authority)
|
||||
|
||||
$soaRecords = @dns_get_record($domain, DNS_SOA);
|
||||
if ($soaRecords) {
|
||||
foreach ($soaRecords as $record) {
|
||||
@@ -153,6 +153,6 @@ function performDnsLookup(string $domain): array {
|
||||
}
|
||||
}
|
||||
|
||||
// Leere Arrays entfernen
|
||||
|
||||
return array_filter($records, fn($arr) => !empty($arr));
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* HexaDNS - DNS Propagation Check API
|
||||
*
|
||||
* Prüft DNS-Records bei verschiedenen öffentlichen DNS-Servern
|
||||
*
|
||||
* Verwendung: GET /api/dns-propagation.php?domain=example.com&type=A
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
require_once __DIR__ . '/../includes/api-helpers.php';
|
||||
|
||||
@@ -23,7 +23,7 @@ if (!checkApiRateLimit('dns-propagation')) {
|
||||
rejectApiRateLimit();
|
||||
}
|
||||
|
||||
// Öffentliche DNS-Server für Propagation-Check
|
||||
|
||||
$dnsServers = [
|
||||
['name' => 'Google', 'ip' => '8.8.8.8', 'location' => 'Global'],
|
||||
['name' => 'Google Secondary', 'ip' => '8.8.4.4', 'location' => 'Global'],
|
||||
@@ -44,7 +44,7 @@ if ($domain === null) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Erlaubte Record-Typen
|
||||
|
||||
$allowedTypes = ['A', 'AAAA', 'MX', 'NS', 'TXT', 'CNAME'];
|
||||
if (!in_array($type, $allowedTypes)) {
|
||||
$type = 'A';
|
||||
@@ -65,7 +65,7 @@ foreach ($dnsServers as $server) {
|
||||
|
||||
$queryStart = microtime(true);
|
||||
|
||||
// DNS-Abfrage mit spezifischem Server via dig (falls verfügbar) oder dns_get_record
|
||||
|
||||
$records = queryDnsServer($domain, $type, $server['ip']);
|
||||
|
||||
$serverResult['response_time'] = round((microtime(true) - $queryStart) * 1000, 2);
|
||||
@@ -80,7 +80,7 @@ foreach ($dnsServers as $server) {
|
||||
|
||||
$totalTime = round((microtime(true) - $startTime) * 1000, 2);
|
||||
|
||||
// Propagation-Status berechnen
|
||||
|
||||
$propagationStatus = calculatePropagationStatus($results);
|
||||
|
||||
echo json_encode([
|
||||
@@ -93,13 +93,13 @@ echo json_encode([
|
||||
'servers' => $results
|
||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
/**
|
||||
* DNS-Abfrage bei spezifischem Server
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function queryDnsServer(string $domain, string $type, string $server): array {
|
||||
$records = [];
|
||||
|
||||
// Versuche zuerst dig zu verwenden (genauer)
|
||||
|
||||
$digResult = @shell_exec(
|
||||
'dig @' . escapeshellarg($server) . ' '
|
||||
. escapeshellarg($domain) . ' '
|
||||
@@ -115,7 +115,7 @@ function queryDnsServer(string $domain, string $type, string $server): array {
|
||||
return $records;
|
||||
}
|
||||
|
||||
// Fallback auf PHP dns_get_record (verwendet System-DNS)
|
||||
|
||||
$dnsType = constant('DNS_' . $type);
|
||||
$result = @dns_get_record($domain, $dnsType);
|
||||
|
||||
@@ -145,9 +145,9 @@ function queryDnsServer(string $domain, string $type, string $server): array {
|
||||
return array_filter($records);
|
||||
}
|
||||
|
||||
/**
|
||||
* Berechnet den Propagation-Status
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function calculatePropagationStatus(array $results): array {
|
||||
$totalServers = count($results);
|
||||
$serversWithRecords = 0;
|
||||
@@ -162,10 +162,10 @@ function calculatePropagationStatus(array $results): array {
|
||||
}
|
||||
}
|
||||
|
||||
// Einzigartige Records
|
||||
|
||||
$uniqueRecords = array_unique($allRecords);
|
||||
|
||||
// Konsistenz prüfen (haben alle Server die gleichen Records?)
|
||||
|
||||
$isConsistent = count($uniqueRecords) <= 1 || $serversWithRecords === 0;
|
||||
|
||||
$percentage = $totalServers > 0 ? round(($serversWithRecords / $totalServers) * 100) : 0;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* HexaDNS - Ping/Verfügbarkeitstest API
|
||||
*
|
||||
* Prüft die Erreichbarkeit einer Domain
|
||||
*
|
||||
* Verwendung: GET /api/ping-check.php?domain=example.com
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
require_once __DIR__ . '/../includes/api-helpers.php';
|
||||
|
||||
@@ -43,9 +43,9 @@ echo json_encode([
|
||||
'results' => $results
|
||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
/**
|
||||
* Führt verschiedene Erreichbarkeitstests durch
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function performConnectivityCheck(string $domain): array {
|
||||
$results = [
|
||||
'dns_resolution' => checkDnsResolution($domain),
|
||||
@@ -55,7 +55,7 @@ function performConnectivityCheck(string $domain): array {
|
||||
'overall_status' => 'offline'
|
||||
];
|
||||
|
||||
// Overall-Status bestimmen
|
||||
|
||||
if ($results['https']['reachable'] || $results['http']['reachable']) {
|
||||
$results['overall_status'] = 'online';
|
||||
} elseif ($results['icmp_ping']['reachable']) {
|
||||
@@ -67,9 +67,9 @@ function performConnectivityCheck(string $domain): array {
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* DNS-Auflösung prüfen
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function checkDnsResolution(string $domain): array {
|
||||
$start = microtime(true);
|
||||
$ip = gethostbyname($domain);
|
||||
@@ -84,9 +84,9 @@ function checkDnsResolution(string $domain): array {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* ICMP Ping (falls verfügbar)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function checkIcmpPing(string $domain): array {
|
||||
$result = [
|
||||
'reachable' => false,
|
||||
@@ -94,18 +94,18 @@ function checkIcmpPing(string $domain): array {
|
||||
'packet_loss' => null
|
||||
];
|
||||
|
||||
// Versuche ping-Kommando
|
||||
|
||||
$safeDomain = escapeshellarg($domain);
|
||||
$pingResult = @shell_exec("ping -c 3 -W 2 {$safeDomain} 2>/dev/null");
|
||||
|
||||
if ($pingResult) {
|
||||
// Prüfe auf erfolgreiche Antworten
|
||||
|
||||
if (preg_match('/(\d+)% packet loss/', $pingResult, $lossMatch)) {
|
||||
$result['packet_loss'] = (int)$lossMatch[1];
|
||||
$result['reachable'] = $result['packet_loss'] < 100;
|
||||
}
|
||||
|
||||
// Durchschnittliche Zeit extrahieren
|
||||
|
||||
if (preg_match('/avg.*?=.*?[\d.]+\/([\d.]+)\//', $pingResult, $timeMatch)) {
|
||||
$result['response_time_ms'] = (float)$timeMatch[1];
|
||||
} elseif (preg_match('/time[=<]([\d.]+)\s*ms/', $pingResult, $timeMatch)) {
|
||||
@@ -116,9 +116,9 @@ function checkIcmpPing(string $domain): array {
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP(S)-Verbindung prüfen
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function checkHttpConnection(string $domain, bool $https = false): array {
|
||||
$protocol = $https ? 'https' : 'http';
|
||||
$port = $https ? 443 : 80;
|
||||
@@ -134,7 +134,7 @@ function checkHttpConnection(string $domain, bool $https = false): array {
|
||||
|
||||
$start = microtime(true);
|
||||
|
||||
// cURL verwenden
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_URL => $url,
|
||||
@@ -156,13 +156,13 @@ function checkHttpConnection(string $domain, bool $https = false): array {
|
||||
$result['status_code'] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$result['reachable'] = $result['status_code'] > 0;
|
||||
|
||||
// Redirect-URL
|
||||
|
||||
$redirectUrl = curl_getinfo($ch, CURLINFO_REDIRECT_URL);
|
||||
if (!empty($redirectUrl)) {
|
||||
$result['redirect_url'] = $redirectUrl;
|
||||
}
|
||||
|
||||
// Server-Header
|
||||
|
||||
if (preg_match('/Server:\s*([^\r\n]+)/i', $response, $serverMatch)) {
|
||||
$result['server'] = trim($serverMatch[1]);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* HexaDNS - Reverse DNS Lookup API
|
||||
*
|
||||
* Löst eine IP-Adresse zu einem Hostnamen auf
|
||||
*
|
||||
* Verwendung: GET /api/reverse-dns.php?ip=8.8.8.8
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
require_once __DIR__ . '/../includes/api-helpers.php';
|
||||
|
||||
@@ -31,7 +31,7 @@ if (empty($ip)) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// IPv4 oder IPv6 validieren
|
||||
|
||||
$isIPv4 = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
|
||||
$isIPv6 = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
|
||||
|
||||
@@ -54,9 +54,9 @@ echo json_encode([
|
||||
'result' => $result
|
||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
/**
|
||||
* Führt Reverse DNS Lookup durch
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function performReverseLookup(string $ip, string $version): array {
|
||||
$result = [
|
||||
'hostname' => null,
|
||||
@@ -64,44 +64,44 @@ function performReverseLookup(string $ip, string $version): array {
|
||||
'additional_info' => []
|
||||
];
|
||||
|
||||
// PHP gethostbyaddr
|
||||
|
||||
$hostname = @gethostbyaddr($ip);
|
||||
|
||||
if ($hostname && $hostname !== $ip) {
|
||||
$result['hostname'] = $hostname;
|
||||
|
||||
// Verifizieren durch Forward-Lookup
|
||||
|
||||
$forwardIp = gethostbyname($hostname);
|
||||
$result['forward_verified'] = ($forwardIp === $ip);
|
||||
|
||||
// Zusätzliche Infos über den Host sammeln
|
||||
|
||||
$result['additional_info'] = getHostInfo($hostname);
|
||||
} else {
|
||||
$result['error'] = 'Kein PTR-Record gefunden';
|
||||
}
|
||||
|
||||
// PTR-Record direkt abfragen
|
||||
|
||||
$ptrRecord = getPtrRecord($ip, $version);
|
||||
if ($ptrRecord) {
|
||||
$result['ptr_record'] = $ptrRecord;
|
||||
}
|
||||
|
||||
// IP-Info (GeoIP wenn verfügbar, sonst Basic-Infos)
|
||||
|
||||
$result['ip_info'] = getIpInfo($ip);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* PTR-Record direkt abfragen
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function getPtrRecord(string $ip, string $version): ?string {
|
||||
if ($version === 'IPv4') {
|
||||
// IPv4: Reverse die Oktette
|
||||
|
||||
$parts = array_reverse(explode('.', $ip));
|
||||
$ptrDomain = implode('.', $parts) . '.in-addr.arpa';
|
||||
} else {
|
||||
// IPv6: Komplexer - jedes Nibble umkehren
|
||||
|
||||
$expanded = expandIPv6($ip);
|
||||
$nibbles = str_replace(':', '', $expanded);
|
||||
$reversed = implode('.', array_reverse(str_split($nibbles)));
|
||||
@@ -117,11 +117,11 @@ function getPtrRecord(string $ip, string $version): ?string {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expandiert eine IPv6-Adresse
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function expandIPv6(string $ip): string {
|
||||
// Ersetze :: mit der richtigen Anzahl von 0000
|
||||
|
||||
if (strpos($ip, '::') !== false) {
|
||||
$parts = explode('::', $ip);
|
||||
$left = $parts[0] ? explode(':', $parts[0]) : [];
|
||||
@@ -133,7 +133,7 @@ function expandIPv6(string $ip): string {
|
||||
$all = explode(':', $ip);
|
||||
}
|
||||
|
||||
// Jedes Segment auf 4 Zeichen auffüllen
|
||||
|
||||
$all = array_map(function($segment) {
|
||||
return str_pad($segment, 4, '0', STR_PAD_LEFT);
|
||||
}, $all);
|
||||
@@ -141,19 +141,19 @@ function expandIPv6(string $ip): string {
|
||||
return implode(':', $all);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sammelt Infos über einen Hostnamen
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function getHostInfo(string $hostname): array {
|
||||
$info = [];
|
||||
|
||||
// Domain-Teile analysieren
|
||||
|
||||
$parts = explode('.', $hostname);
|
||||
$tld = end($parts);
|
||||
|
||||
$info['tld'] = $tld;
|
||||
|
||||
// Bekannte Hosting-Provider erkennen
|
||||
|
||||
$providerPatterns = [
|
||||
'amazonaws.com' => 'Amazon AWS',
|
||||
'googleusercontent.com' => 'Google Cloud',
|
||||
@@ -183,15 +183,15 @@ function getHostInfo(string $hostname): array {
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Basis-Infos zur IP
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function getIpInfo(string $ip): array {
|
||||
$info = [
|
||||
'type' => 'unknown'
|
||||
];
|
||||
|
||||
// Private IP-Bereiche prüfen
|
||||
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
|
||||
if (preg_match('/^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)/', $ip)) {
|
||||
$info['type'] = 'private';
|
||||
@@ -201,7 +201,7 @@ function getIpInfo(string $ip): array {
|
||||
$info['type'] = 'public';
|
||||
}
|
||||
} else {
|
||||
// IPv6
|
||||
|
||||
if (preg_match('/^(fc|fd)/i', $ip)) {
|
||||
$info['type'] = 'private';
|
||||
} elseif (preg_match('/^::1$/', $ip) || preg_match('/^fe80:/i', $ip)) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* HexaDNS - SSL Certificate Check API
|
||||
*
|
||||
* Prüft SSL-Zertifikat-Informationen einer Domain
|
||||
*
|
||||
* Verwendung: GET /api/ssl-check.php?domain=example.com
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
require_once __DIR__ . '/../includes/api-helpers.php';
|
||||
|
||||
@@ -43,9 +43,9 @@ echo json_encode([
|
||||
'ssl' => $sslData
|
||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
/**
|
||||
* Prüft SSL-Zertifikat einer Domain
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function checkSslCertificate(string $domain): array {
|
||||
$result = [
|
||||
'success' => false,
|
||||
@@ -55,7 +55,7 @@ function checkSslCertificate(string $domain): array {
|
||||
'certificate' => null
|
||||
];
|
||||
|
||||
// Stream Context für SSL
|
||||
|
||||
$context = stream_context_create([
|
||||
'ssl' => [
|
||||
'capture_peer_cert' => true,
|
||||
@@ -64,18 +64,18 @@ function checkSslCertificate(string $domain): array {
|
||||
]
|
||||
]);
|
||||
|
||||
// Verbindung herstellen
|
||||
|
||||
$socket = @stream_socket_client(
|
||||
"ssl://{$domain}:443",
|
||||
$errno,
|
||||
$errstr,
|
||||
10, // Timeout
|
||||
10,
|
||||
STREAM_CLIENT_CONNECT,
|
||||
$context
|
||||
);
|
||||
|
||||
if (!$socket) {
|
||||
// Versuche ohne SSL (um zu prüfen ob Server erreichbar)
|
||||
|
||||
$httpSocket = @fsockopen($domain, 80, $errno, $errstr, 5);
|
||||
if ($httpSocket) {
|
||||
fclose($httpSocket);
|
||||
@@ -89,7 +89,7 @@ function checkSslCertificate(string $domain): array {
|
||||
$result['has_ssl'] = true;
|
||||
$result['success'] = true;
|
||||
|
||||
// Zertifikat extrahieren
|
||||
|
||||
$params = stream_context_get_params($socket);
|
||||
$cert = $params['options']['ssl']['peer_certificate'] ?? null;
|
||||
|
||||
@@ -105,10 +105,10 @@ function checkSslCertificate(string $domain): array {
|
||||
$isNotYetValid = $now < $validFrom;
|
||||
$result['is_valid'] = !$isExpired && !$isNotYetValid;
|
||||
|
||||
// Tage bis Ablauf
|
||||
|
||||
$daysUntilExpiry = floor(($validTo - $now) / 86400);
|
||||
|
||||
// Subject Alternative Names (SANs)
|
||||
|
||||
$sans = [];
|
||||
if (isset($certInfo['extensions']['subjectAltName'])) {
|
||||
$sanStr = $certInfo['extensions']['subjectAltName'];
|
||||
@@ -116,7 +116,7 @@ function checkSslCertificate(string $domain): array {
|
||||
$sans = $matches[1] ?? [];
|
||||
}
|
||||
|
||||
// Issuer aufbereiten
|
||||
|
||||
$issuer = [];
|
||||
if (isset($certInfo['issuer'])) {
|
||||
if (isset($certInfo['issuer']['O'])) $issuer['organization'] = $certInfo['issuer']['O'];
|
||||
@@ -124,7 +124,7 @@ function checkSslCertificate(string $domain): array {
|
||||
if (isset($certInfo['issuer']['C'])) $issuer['country'] = $certInfo['issuer']['C'];
|
||||
}
|
||||
|
||||
// Subject aufbereiten
|
||||
|
||||
$subject = [];
|
||||
if (isset($certInfo['subject'])) {
|
||||
if (isset($certInfo['subject']['CN'])) $subject['common_name'] = $certInfo['subject']['CN'];
|
||||
@@ -144,7 +144,7 @@ function checkSslCertificate(string $domain): array {
|
||||
'version' => $certInfo['version'] ?? null,
|
||||
];
|
||||
|
||||
// Warnung wenn bald ablaufend
|
||||
|
||||
if ($daysUntilExpiry <= 30 && $daysUntilExpiry > 0) {
|
||||
$result['warning'] = "Zertifikat läuft in {$daysUntilExpiry} Tagen ab!";
|
||||
} elseif ($isExpired) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* HexaDNS - WHOIS Lookup API
|
||||
*
|
||||
* Ruft WHOIS-Informationen für eine Domain ab
|
||||
*
|
||||
* Verwendung: GET /api/whois-lookup.php?domain=example.com
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
require_once __DIR__ . '/../includes/api-helpers.php';
|
||||
|
||||
@@ -31,7 +31,7 @@ if (empty($domain)) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Nur Root-Domain extrahieren
|
||||
|
||||
$domain = extractRootDomain($domain);
|
||||
|
||||
if (!preg_match('/^[a-zA-Z0-9][a-zA-Z0-9\-]*\.[a-zA-Z]{2,}$/', $domain)) {
|
||||
@@ -58,9 +58,9 @@ echo json_encode([
|
||||
'whois' => $whoisData
|
||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
/**
|
||||
* Extrahiert die Root-Domain (ohne Subdomain)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function extractRootDomain(string $domain): string {
|
||||
$domain = strtolower($domain);
|
||||
$domain = preg_replace('/^(https?:\/\/)?(www\.)?/', '', $domain);
|
||||
@@ -68,22 +68,22 @@ function extractRootDomain(string $domain): string {
|
||||
|
||||
$parts = explode('.', $domain);
|
||||
if (count($parts) > 2) {
|
||||
// Einfache Logik: nimm die letzten 2 Teile
|
||||
// (funktioniert nicht perfekt für .co.uk etc., aber gut genug)
|
||||
|
||||
|
||||
return implode('.', array_slice($parts, -2));
|
||||
}
|
||||
|
||||
return $domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Führt WHOIS-Lookup durch
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function performWhoisLookup(string $domain): ?array {
|
||||
// Primär: Socket-basierte Abfrage (funktioniert ohne shell_exec)
|
||||
|
||||
$whoisRaw = whoisViaSocket($domain);
|
||||
|
||||
// Fallback: Shell-Kommando (sicher escaped)
|
||||
|
||||
if (empty($whoisRaw) && function_exists('shell_exec')) {
|
||||
$escapedDomain = escapeshellarg($domain);
|
||||
$whoisRaw = @shell_exec("whois {$escapedDomain} 2>/dev/null");
|
||||
@@ -93,13 +93,13 @@ function performWhoisLookup(string $domain): ?array {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Parse WHOIS-Daten
|
||||
|
||||
return parseWhoisData($whoisRaw, $domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* WHOIS-Abfrage über Socket (unabhängig von shell_exec)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function whoisViaSocket(string $domain): ?string {
|
||||
$whoisServer = getWhoisServer($domain);
|
||||
|
||||
@@ -109,7 +109,7 @@ function whoisViaSocket(string $domain): ?string {
|
||||
|
||||
$result = queryWhoisServer($whoisServer, $domain);
|
||||
|
||||
// Prüfe auf Weiterleitungen zu anderen WHOIS-Servern
|
||||
|
||||
if ($result && preg_match('/Registrar WHOIS Server:\s*(\S+)/i', $result, $matches)) {
|
||||
$referralServer = trim($matches[1]);
|
||||
if ($referralServer && $referralServer !== $whoisServer) {
|
||||
@@ -123,9 +123,9 @@ function whoisViaSocket(string $domain): ?string {
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abfrage an einen spezifischen WHOIS-Server
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function queryWhoisServer(string $server, string $domain): ?string {
|
||||
$port = 43;
|
||||
$timeout = 10;
|
||||
@@ -136,13 +136,13 @@ function queryWhoisServer(string $server, string $domain): ?string {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Setze Stream-Timeout
|
||||
|
||||
stream_set_timeout($socket, $timeout);
|
||||
|
||||
// Sende Anfrage
|
||||
|
||||
fwrite($socket, $domain . "\r\n");
|
||||
|
||||
// Lese Antwort
|
||||
|
||||
$response = '';
|
||||
while (!feof($socket)) {
|
||||
$response .= fread($socket, 8192);
|
||||
@@ -153,16 +153,16 @@ function queryWhoisServer(string $server, string $domain): ?string {
|
||||
return !empty($response) ? $response : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ermittelt den zuständigen WHOIS-Server für eine TLD
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function getWhoisServer(string $domain): ?string {
|
||||
$parts = explode('.', $domain);
|
||||
$tld = strtolower(end($parts));
|
||||
|
||||
// Bekannte WHOIS-Server nach TLD
|
||||
|
||||
$whoisServers = [
|
||||
// Generische TLDs
|
||||
|
||||
'com' => 'whois.verisign-grs.com',
|
||||
'net' => 'whois.verisign-grs.com',
|
||||
'org' => 'whois.pir.org',
|
||||
@@ -186,7 +186,7 @@ function getWhoisServer(string $domain): ?string {
|
||||
'travel' => 'whois.nic.travel',
|
||||
'xxx' => 'whois.nic.xxx',
|
||||
|
||||
// Neue gTLDs
|
||||
|
||||
'app' => 'whois.nic.google',
|
||||
'dev' => 'whois.nic.google',
|
||||
'page' => 'whois.nic.google',
|
||||
@@ -205,7 +205,7 @@ function getWhoisServer(string $domain): ?string {
|
||||
'cc' => 'ccwhois.verisign-grs.com',
|
||||
'ws' => 'whois.website.ws',
|
||||
|
||||
// Europäische ccTLDs
|
||||
|
||||
'de' => 'whois.denic.de',
|
||||
'at' => 'whois.nic.at',
|
||||
'ch' => 'whois.nic.ch',
|
||||
@@ -235,7 +235,7 @@ function getWhoisServer(string $domain): ?string {
|
||||
'eu' => 'whois.eu',
|
||||
'lu' => 'whois.dns.lu',
|
||||
|
||||
// Andere ccTLDs
|
||||
|
||||
'ru' => 'whois.tcinet.ru',
|
||||
'ua' => 'whois.ua',
|
||||
'us' => 'whois.nic.us',
|
||||
@@ -255,7 +255,7 @@ function getWhoisServer(string $domain): ?string {
|
||||
'za' => 'whois.registry.net.za',
|
||||
];
|
||||
|
||||
// Spezielle Behandlung für .co.uk, .com.au etc.
|
||||
|
||||
if (count($parts) >= 2) {
|
||||
$sld = $parts[count($parts) - 2];
|
||||
$combinedTld = $sld . '.' . $tld;
|
||||
@@ -279,9 +279,9 @@ function getWhoisServer(string $domain): ?string {
|
||||
return $whoisServers[$tld] ?? 'whois.iana.org';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parsed WHOIS-Rohdaten in strukturiertes Format
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function parseWhoisData(string $raw, string $domain): array {
|
||||
$data = [
|
||||
'raw' => $raw,
|
||||
@@ -306,50 +306,50 @@ function parseWhoisData(string $raw, string $domain): array {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Key: Value Format
|
||||
|
||||
if (strpos($line, ':') !== false) {
|
||||
list($key, $value) = array_map('trim', explode(':', $line, 2));
|
||||
$keyLower = strtolower($key);
|
||||
|
||||
// Registrar
|
||||
|
||||
if (strpos($keyLower, 'registrar') !== false && strpos($keyLower, 'abuse') === false && strpos($keyLower, 'url') === false) {
|
||||
if (empty($data['parsed']['registrar'])) {
|
||||
$data['parsed']['registrar'] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// Registrar URL
|
||||
|
||||
if (strpos($keyLower, 'registrar') !== false && strpos($keyLower, 'url') !== false) {
|
||||
$data['parsed']['registrar_url'] = $value;
|
||||
}
|
||||
|
||||
// Erstellungsdatum
|
||||
|
||||
if (preg_match('/(creation|created|registered)/i', $keyLower) && strpos($keyLower, 'registrar') === false) {
|
||||
if (empty($data['parsed']['creation_date'])) {
|
||||
$data['parsed']['creation_date'] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// Ablaufdatum
|
||||
|
||||
if (preg_match('/(expir|paid-till)/i', $keyLower)) {
|
||||
if (empty($data['parsed']['expiration_date'])) {
|
||||
$data['parsed']['expiration_date'] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// Aktualisierungsdatum
|
||||
|
||||
if (preg_match('/(updated|modified|changed)/i', $keyLower) && strpos($keyLower, 'registrar') === false) {
|
||||
if (empty($data['parsed']['updated_date'])) {
|
||||
$data['parsed']['updated_date'] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// Status
|
||||
|
||||
if (preg_match('/(status|state)/i', $keyLower) && !empty($value)) {
|
||||
$data['parsed']['status'][] = $value;
|
||||
}
|
||||
|
||||
// Nameserver
|
||||
|
||||
if (preg_match('/^(name.?server|nserver)/i', $keyLower) && !empty($value)) {
|
||||
$ns = strtolower(explode(' ', $value)[0]);
|
||||
if (!in_array($ns, $data['parsed']['nameservers'])) {
|
||||
@@ -357,14 +357,14 @@ function parseWhoisData(string $raw, string $domain): array {
|
||||
}
|
||||
}
|
||||
|
||||
// DNSSEC
|
||||
|
||||
if (strpos($keyLower, 'dnssec') !== false) {
|
||||
$data['parsed']['dnssec'] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Status einzigartig machen
|
||||
|
||||
$data['parsed']['status'] = array_unique($data['parsed']['status']);
|
||||
|
||||
return $data;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* HexaHost.de Konfiguration
|
||||
*
|
||||
* HINWEIS: Diese Datei ist veraltet!
|
||||
*
|
||||
* Die Konfiguration wurde nach mail-config.php verschoben.
|
||||
* Bitte verwenden Sie stattdessen:
|
||||
*
|
||||
* require_once 'config/mail-config.php';
|
||||
*
|
||||
* Diese Datei wird nur aus Kompatibilitätsgründen beibehalten.
|
||||
*/
|
||||
|
||||
// Lade die neue Konfiguration
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
require_once __DIR__ . '/mail-config.php';
|
||||
?>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* Zentrale Betreff-Konfiguration für das Kontaktformular
|
||||
*/
|
||||
|
||||
/**
|
||||
* @return array<string, string> Betreff-Schlüssel => Anzeigename
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function getContactSubjectMap(): array {
|
||||
return [
|
||||
'allgemeine-anfrage' => 'Allgemeine Anfrage',
|
||||
@@ -26,16 +26,16 @@ function getContactSubjectMap(): array {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $subjectKey
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function isAllowedContactSubject(string $subjectKey): bool {
|
||||
return array_key_exists($subjectKey, getContactSubjectMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* Betreff aus ?product= oder ?package= für die Kontaktseite ableiten
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function getPreselectedContactSubject(): string {
|
||||
$productMap = [
|
||||
'vpc' => 'vpc-anfrage',
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* HexaHost.de Mail Configuration
|
||||
*
|
||||
* Dieses Projekt versendet E-Mails nativ über PHP mail().
|
||||
* Es sind keine externen Bibliotheken oder Composer-Installationen erforderlich.
|
||||
*/
|
||||
|
||||
// E-Mail Adressen
|
||||
define('SMTP_FROM_EMAIL', 'kontakt@hexahost.de'); // Absender-E-Mail
|
||||
define('SMTP_TO_EMAIL', 'info@hexahost.de'); // Empfänger-E-Mail für Kontaktformular
|
||||
|
||||
// Sicherheitseinstellungen
|
||||
define('ENABLE_CSRF_PROTECTION', true); // CSRF-Schutz aktivieren
|
||||
define('ENABLE_RATE_LIMITING', true); // Rate-Limiting aktivieren
|
||||
define('MAX_REQUESTS_PER_HOUR', 10); // Max. Anfragen pro Stunde
|
||||
|
||||
// Spam-Schutz Einstellungen
|
||||
define('ENABLE_SPAM_PROTECTION', true); // Spam-Schutz aktivieren
|
||||
define('MAX_MESSAGE_LENGTH', 5000); // Max. Nachrichtenlänge
|
||||
define('MIN_MESSAGE_LENGTH', 10); // Min. Nachrichtenlänge
|
||||
|
||||
// Debug-Einstellungen (nur für Entwicklung)
|
||||
define('DEBUG_MODE', false); // Debug-Modus (true/false)
|
||||
define('LOG_EMAILS', true); // E-Mails loggen (true/false)
|
||||
|
||||
// Zusätzliche Sicherheitsheader
|
||||
|
||||
|
||||
|
||||
define('SMTP_FROM_EMAIL', 'kontakt@hexahost.de');
|
||||
define('SMTP_TO_EMAIL', 'info@hexahost.de');
|
||||
|
||||
|
||||
define('ENABLE_CSRF_PROTECTION', true);
|
||||
define('ENABLE_RATE_LIMITING', true);
|
||||
define('MAX_REQUESTS_PER_HOUR', 10);
|
||||
|
||||
|
||||
define('ENABLE_SPAM_PROTECTION', true);
|
||||
define('MAX_MESSAGE_LENGTH', 5000);
|
||||
define('MIN_MESSAGE_LENGTH', 10);
|
||||
|
||||
|
||||
define('DEBUG_MODE', false);
|
||||
define('LOG_EMAILS', true);
|
||||
|
||||
|
||||
define('ADDITIONAL_HEADERS', [
|
||||
'X-Mailer' => 'HexaHost.de Contact Form',
|
||||
'X-Priority' => '3',
|
||||
@@ -35,22 +35,22 @@ define('ADDITIONAL_HEADERS', [
|
||||
'Precedence' => 'bulk'
|
||||
]);
|
||||
|
||||
// Erlaubte Domains für E-Mail-Adressen (optional)
|
||||
|
||||
define('ALLOWED_EMAIL_DOMAINS', [
|
||||
// Leer lassen für alle Domains zu erlauben
|
||||
// 'gmail.com',
|
||||
// 'outlook.com',
|
||||
// 'web.de',
|
||||
// 'gmx.de'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
]);
|
||||
|
||||
// Blacklist für E-Mail-Adressen (optional)
|
||||
|
||||
define('BLACKLISTED_EMAILS', [
|
||||
// 'spam@example.com',
|
||||
// 'test@test.com'
|
||||
|
||||
|
||||
]);
|
||||
|
||||
// Überprüfung der E-Mail-Adressen
|
||||
|
||||
if (!filter_var(SMTP_FROM_EMAIL, FILTER_VALIDATE_EMAIL)) {
|
||||
die('Ungültige SMTP_FROM_EMAIL Adresse');
|
||||
}
|
||||
@@ -59,7 +59,7 @@ if (!filter_var(SMTP_TO_EMAIL, FILTER_VALIDATE_EMAIL)) {
|
||||
die('Ungültige SMTP_TO_EMAIL Adresse');
|
||||
}
|
||||
|
||||
// Logging-Funktion
|
||||
|
||||
function logEmail($type, $data) {
|
||||
if (!LOG_EMAILS) return;
|
||||
|
||||
@@ -76,18 +76,18 @@ function logEmail($type, $data) {
|
||||
file_put_contents($logFile, $logEntry, FILE_APPEND | LOCK_EX);
|
||||
}
|
||||
|
||||
// Hilfsfunktion für E-Mail-Validierung
|
||||
|
||||
function isValidEmail($email) {
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prüfe Blacklist
|
||||
|
||||
if (in_array($email, BLACKLISTED_EMAILS)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prüfe Domain-Whitelist (falls gesetzt)
|
||||
|
||||
if (!empty(ALLOWED_EMAIL_DOMAINS)) {
|
||||
$domain = substr(strrchr($email, "@"), 1);
|
||||
if (!in_array($domain, ALLOWED_EMAIL_DOMAINS)) {
|
||||
@@ -98,29 +98,29 @@ function isValidEmail($email) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hilfsfunktion zum Abrufen der Konfiguration als Array
|
||||
* Kompatibilität mit contact-handler.php
|
||||
*
|
||||
* @param string|null $key Optional: einzelner Schlüssel
|
||||
* @return mixed Konfigurationsarray oder einzelner Wert
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function getHexaHostConfig($key = null) {
|
||||
$config = [
|
||||
// Absender/Empfänger
|
||||
|
||||
'from_email' => SMTP_FROM_EMAIL,
|
||||
'from_name' => 'HexaHost.de Kontaktformular',
|
||||
'to_email' => SMTP_TO_EMAIL,
|
||||
'to_name' => 'HexaHost Support',
|
||||
|
||||
// Sicherheit
|
||||
|
||||
'max_requests_per_hour' => MAX_REQUESTS_PER_HOUR,
|
||||
'honeypot_field' => 'website',
|
||||
'enable_csrf' => ENABLE_CSRF_PROTECTION,
|
||||
'min_message_length' => MIN_MESSAGE_LENGTH,
|
||||
'max_message_length' => MAX_MESSAGE_LENGTH,
|
||||
|
||||
// Debug
|
||||
|
||||
'debug_mode' => DEBUG_MODE,
|
||||
'log_errors' => LOG_EMAILS,
|
||||
];
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* HexaHost.de Produkt-Konfiguration
|
||||
*
|
||||
* Hier können Sie alle Preise, Shop-Links und Produktinformationen zentral verwalten.
|
||||
* Pro Paket: shop_url (WHMCS/Warenkorb-Link, z. B. https://shop.hexahost.de/cart.php?a=add&pid=123)
|
||||
* Nach Änderungen: npm run build && npm run deploy
|
||||
*
|
||||
* Verwendung in PHP-Seiten:
|
||||
* require_once 'config/products-config.php';
|
||||
* $packages = getProductPackages('vpc');
|
||||
*/
|
||||
|
||||
// ============================================================================
|
||||
// VIRTUAL PRIVATE CONTAINER (VPC)
|
||||
// ============================================================================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$PRODUCTS['vpc'] = [
|
||||
'name' => 'Virtual Private Container',
|
||||
'short_name' => 'VPC',
|
||||
@@ -117,9 +117,9 @@ $PRODUCTS['vpc'] = [
|
||||
],
|
||||
];
|
||||
|
||||
// ============================================================================
|
||||
// VIRTUAL PRIVATE SERVER (VPS)
|
||||
// ============================================================================
|
||||
|
||||
|
||||
|
||||
$PRODUCTS['vps'] = [
|
||||
'name' => 'Virtual Private Server',
|
||||
'short_name' => 'VPS',
|
||||
@@ -223,9 +223,9 @@ $PRODUCTS['vps'] = [
|
||||
],
|
||||
];
|
||||
|
||||
// ============================================================================
|
||||
// MAIL GATEWAY
|
||||
// ============================================================================
|
||||
|
||||
|
||||
|
||||
$PRODUCTS['mail-gateway'] = [
|
||||
'name' => 'Mail Gateway',
|
||||
'short_name' => 'Mail',
|
||||
@@ -329,9 +329,9 @@ $PRODUCTS['mail-gateway'] = [
|
||||
],
|
||||
];
|
||||
|
||||
// ============================================================================
|
||||
// WEBHOSTING
|
||||
// ============================================================================
|
||||
|
||||
|
||||
|
||||
$PRODUCTS['webhosting'] = [
|
||||
'name' => 'Webhosting',
|
||||
'short_name' => 'Webhosting',
|
||||
@@ -443,68 +443,68 @@ $PRODUCTS['webhosting'] = [
|
||||
],
|
||||
];
|
||||
|
||||
// ============================================================================
|
||||
// HILFSFUNKTIONEN
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Alle Produkte abrufen
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function getAllProducts() {
|
||||
global $PRODUCTS;
|
||||
return $PRODUCTS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ein Produkt abrufen
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function getProduct($productId) {
|
||||
global $PRODUCTS;
|
||||
return $PRODUCTS[$productId] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alle Pakete eines Produkts abrufen
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function getProductPackages($productId) {
|
||||
global $PRODUCTS;
|
||||
return $PRODUCTS[$productId]['packages'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ein bestimmtes Paket abrufen
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function getPackage($productId, $packageId) {
|
||||
global $PRODUCTS;
|
||||
return $PRODUCTS[$productId]['packages'][$packageId] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preis eines Pakets abrufen
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function getPackagePrice($productId, $packageId) {
|
||||
$package = getPackage($productId, $packageId);
|
||||
return $package['price'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimalen Preis eines Produkts abrufen
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function getMinPrice($productId) {
|
||||
global $PRODUCTS;
|
||||
return $PRODUCTS[$productId]['min_price'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preis formatiert ausgeben
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function formatPrice($price, $withCurrency = true) {
|
||||
return $withCurrency ? $price . '€' : $price;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bestell-Link für ein Paket (Online-Shop oder Kontaktformular)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function getOrderUrl($productId, $packageId) {
|
||||
$package = getPackage($productId, $packageId);
|
||||
if ($package && !empty($package['shop_url'])) {
|
||||
@@ -514,9 +514,9 @@ function getOrderUrl($productId, $packageId) {
|
||||
return sprintf('contact.php?package=%s-%s', $productId, $packageId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bestell-Link für CTA (beliebtes Paket oder erstes Paket)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function getProductOrderUrl($productId) {
|
||||
$packages = getProductPackages($productId);
|
||||
|
||||
@@ -534,9 +534,9 @@ function getProductOrderUrl($productId) {
|
||||
return sprintf('contact.php?product=%s', $productId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generiert HTML für eine Paket-Karte
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function renderPackageCard($productId, $packageId, $package) {
|
||||
$featuredClass = $package['featured'] ? ' featured' : '';
|
||||
$featuredBadge = $package['featured'] ? '<div class="featured-badge">Beliebt</div>' : '';
|
||||
@@ -583,9 +583,9 @@ function renderPackageCard($productId, $packageId, $package) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generiert HTML für alle Pakete eines Produkts
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function renderAllPackages($productId) {
|
||||
$packages = getProductPackages($productId);
|
||||
$html = '';
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* Gemeinsame Hilfsfunktionen für öffentliche DNS/API-Endpunkte
|
||||
*/
|
||||
|
||||
/**
|
||||
* Client-IP für Rate-Limiting (Cloudflare-sicher, kein blindes X-Forwarded-For)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function getApiClientIp(): string {
|
||||
if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])
|
||||
&& filter_var($_SERVER['HTTP_CF_CONNECTING_IP'], FILTER_VALIDATE_IP)) {
|
||||
@@ -34,9 +34,9 @@ function getApiClientIp(): string {
|
||||
return $remoteAddr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Einfaches Rate-Limiting pro Endpunkt und IP
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function checkApiRateLimit(string $endpoint, int $maxPerHour = 120): bool {
|
||||
$ip = getApiClientIp();
|
||||
$cacheFile = sys_get_temp_dir() . '/hexahost_api_' . md5($endpoint . '_' . $ip) . '.txt';
|
||||
@@ -82,9 +82,9 @@ function checkApiRateLimit(string $endpoint, int $maxPerHour = 120): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Domain aus GET-Parameter normalisieren und validieren
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function getValidatedDomainParam(string $param = 'domain'): ?string {
|
||||
if (empty($_GET[$param])) {
|
||||
return null;
|
||||
@@ -102,9 +102,9 @@ function getValidatedDomainParam(string $param = 'domain'): ?string {
|
||||
return $domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rate-Limit-JSON-Antwort senden und beenden
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function rejectApiRateLimit(): void {
|
||||
http_response_code(429);
|
||||
echo json_encode(['error' => 'Zu viele Anfragen. Bitte versuchen Sie es später erneut.']);
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
|
||||
// Standard: keine Analyse/Marketing-Cookies bis zur Einwilligung
|
||||
|
||||
gtag('consent', 'default', {
|
||||
analytics_storage: 'denied',
|
||||
ad_storage: 'denied',
|
||||
@@ -139,7 +139,7 @@
|
||||
anonymize_ip: true
|
||||
});
|
||||
|
||||
// Übergibt Consent-Änderungen aus dem eigenen Cookie-Banner an GA
|
||||
|
||||
window.addEventListener('cookieConsentUpdated', function (event) {
|
||||
var payload = event && event.detail ? event.detail : {};
|
||||
var consent = payload.consent ? payload.consent : payload;
|
||||
@@ -156,8 +156,8 @@
|
||||
</script>
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-EF0E9VPMTD"></script>
|
||||
|
||||
<script src="/assets/js/main.js" defer></script>
|
||||
<script src="/assets/js/cookie-consent.js" defer></script>
|
||||
<script src="/assets/js/main.915e0206c30f.js" defer></script>
|
||||
<script src="/assets/js/cookie-consent.de9e404f0700.js" defer></script>
|
||||
<?php if (isset($additional_scripts)): ?>
|
||||
<?php foreach ($additional_scripts as $script): ?>
|
||||
<script src="<?php echo htmlspecialchars($script, ENT_QUOTES, 'UTF-8'); ?>" defer></script>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* Helper functions for HexaHost.de
|
||||
*/
|
||||
|
||||
// Sichere Session-Konfiguration
|
||||
|
||||
|
||||
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
// Session-Cookie-Sicherheit
|
||||
|
||||
ini_set('session.cookie_httponly', 1);
|
||||
ini_set('session.cookie_secure', isset($_SERVER['HTTPS']) ? 1 : 0);
|
||||
ini_set('session.cookie_samesite', 'Strict');
|
||||
@@ -14,14 +14,14 @@ if (session_status() === PHP_SESSION_NONE) {
|
||||
|
||||
session_start();
|
||||
|
||||
// Session-ID regenerieren bei Login/wichtigen Aktionen (Schutz vor Session Fixation)
|
||||
|
||||
if (!isset($_SESSION['initiated'])) {
|
||||
session_regenerate_id(true);
|
||||
$_SESSION['initiated'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// PHP Error Display in Produktion deaktivieren
|
||||
|
||||
if (!defined('DEBUG_MODE') || !DEBUG_MODE) {
|
||||
ini_set('display_errors', 0);
|
||||
ini_set('display_startup_errors', 0);
|
||||
@@ -29,18 +29,18 @@ if (!defined('DEBUG_MODE') || !DEBUG_MODE) {
|
||||
ini_set('log_errors', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set page configuration and include header
|
||||
*
|
||||
* @param string $title The page title
|
||||
* @param string $description The page description
|
||||
* @param string $page The current page identifier
|
||||
* @param array $scripts Additional scripts to include
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function includeHeader($title = '', $description = '', $page = '', $scripts = []) {
|
||||
global $page_title, $page_description, $current_page, $additional_scripts;
|
||||
|
||||
// Set page configuration from parameters
|
||||
|
||||
$page_title = !empty($title)
|
||||
? $title
|
||||
: 'HexaHost.de - Zuverlässiges Hosting aus Niederbayern';
|
||||
@@ -55,28 +55,28 @@ function includeHeader($title = '', $description = '', $page = '', $scripts = []
|
||||
include __DIR__ . '/header.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Include footer
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function includeFooter() {
|
||||
include __DIR__ . '/footer.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate breadcrumb navigation
|
||||
*
|
||||
* @param array $breadcrumbs Array of breadcrumb items [['title' => 'Home', 'url' => 'index.html'], ...]
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function generateBreadcrumbs($breadcrumbs) {
|
||||
echo '<div class="breadcrumb">';
|
||||
$last_index = count($breadcrumbs) - 1;
|
||||
|
||||
foreach ($breadcrumbs as $index => $item) {
|
||||
if ($index === $last_index) {
|
||||
// Last item (current page)
|
||||
|
||||
echo '<span>' . htmlspecialchars($item['title']) . '</span>';
|
||||
} else {
|
||||
// Link to other pages
|
||||
|
||||
echo '<a href="' . htmlspecialchars($item['url']) . '">' . htmlspecialchars($item['title']) . '</a>';
|
||||
echo '<span>/</span>';
|
||||
}
|
||||
@@ -84,11 +84,11 @@ function generateBreadcrumbs($breadcrumbs) {
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate CSRF token for form security
|
||||
*
|
||||
* @return string CSRF token
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function generateCSRFToken() {
|
||||
if (!isset($_SESSION['csrf_token'])) {
|
||||
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
||||
@@ -96,9 +96,9 @@ function generateCSRFToken() {
|
||||
return $_SESSION['csrf_token'];
|
||||
}
|
||||
|
||||
/**
|
||||
* CSRF-Token prüfen und nach Erfolg invalidieren (Replay-Schutz)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function validateCSRFToken($token) {
|
||||
if (!isset($_SESSION['csrf_token']) || !is_string($token)) {
|
||||
return false;
|
||||
@@ -110,16 +110,16 @@ function validateCSRFToken($token) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Werte für E-Mail-Header bereinigen (Header-Injection verhindern)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function sanitizeHeaderValue(string $value): string {
|
||||
return str_replace(["\r", "\n", "\0"], '', trim($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Client-IP für Logging (Cloudflare / vertrauenswürdiger Reverse-Proxy)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function getClientIP(): string {
|
||||
if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])
|
||||
&& filter_var($_SERVER['HTTP_CF_CONNECTING_IP'], FILTER_VALIDATE_IP)) {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<link rel="preconnect" href="https://cdn.hexahost.de" crossorigin>
|
||||
|
||||
<!-- Performance: Preload kritischer Ressourcen -->
|
||||
<link rel="preload" href="/assets/css/style.css" as="style">
|
||||
<link rel="preload" href="/assets/css/style.d01979e8c871.css" as="style">
|
||||
<link rel="preload" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" as="style">
|
||||
|
||||
<title><?php echo isset($page_title) ? htmlspecialchars($page_title) : 'HexaHost.de - Zuverlässiges Hosting aus Niederbayern'; ?></title>
|
||||
@@ -32,8 +32,8 @@
|
||||
<meta property="og:locale" content="de_DE">
|
||||
|
||||
<!-- Main Stylesheets -->
|
||||
<link rel="stylesheet" href="/assets/css/style.css">
|
||||
<link rel="stylesheet" href="/assets/css/custom.css">
|
||||
<link rel="stylesheet" href="/assets/css/style.d01979e8c871.css">
|
||||
<link rel="stylesheet" href="/assets/css/custom.0bc6a878fec2.css">
|
||||
|
||||
<!-- Fonts -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Russo+One&family=Source+Sans+Pro:wght@300;400;600;700&display=swap" rel="stylesheet">
|
||||
|
||||
Reference in New Issue
Block a user