Initial commit — Superfice.de website
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
112
api/helpers.php
Normal file
112
api/helpers.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
/**
|
||||
* Superfice – API Helpers
|
||||
*
|
||||
* Shared utility functions for API endpoints.
|
||||
* Not directly accessible (no public entry point).
|
||||
*/
|
||||
|
||||
// -------------------------------------------------------
|
||||
// CORS
|
||||
// -------------------------------------------------------
|
||||
function cors_headers(): void {
|
||||
$allowed = defined('SITE_ORIGIN') ? SITE_ORIGIN : '*';
|
||||
header('Access-Control-Allow-Origin: ' . $allowed);
|
||||
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
|
||||
header('Access-Control-Allow-Headers: Content-Type');
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
// JSON error response
|
||||
// -------------------------------------------------------
|
||||
function json_error(string $msg, int $code = 400): never {
|
||||
http_response_code($code);
|
||||
echo json_encode(['error' => $msg]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Client IP (respects proxy headers cautiously)
|
||||
// -------------------------------------------------------
|
||||
function client_ip(): string {
|
||||
// Only trust X-Forwarded-For if behind a known proxy
|
||||
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
|
||||
return trim($ips[0]);
|
||||
}
|
||||
return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
// File-based rate limiting
|
||||
// -------------------------------------------------------
|
||||
function rate_limit(string $key, int $maxRequests, int $window): void {
|
||||
$dir = defined('RATE_LIMIT_DIR') ? RATE_LIMIT_DIR : sys_get_temp_dir() . '/sf_rl';
|
||||
if (!is_dir($dir)) {
|
||||
@mkdir($dir, 0700, true);
|
||||
}
|
||||
|
||||
$file = $dir . '/' . hash('sha256', $key) . '.json';
|
||||
$now = time();
|
||||
$data = ['count' => 0, 'reset' => $now + $window];
|
||||
|
||||
if (file_exists($file)) {
|
||||
$stored = json_decode(file_get_contents($file), true);
|
||||
if (is_array($stored) && $stored['reset'] > $now) {
|
||||
$data = $stored;
|
||||
}
|
||||
}
|
||||
|
||||
$data['count']++;
|
||||
file_put_contents($file, json_encode($data), LOCK_EX);
|
||||
|
||||
if ($data['count'] > $maxRequests) {
|
||||
http_response_code(429);
|
||||
echo json_encode(['error' => 'Zu viele Anfragen. Bitte versuchen Sie es später erneut.']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Haversine distance (km)
|
||||
// -------------------------------------------------------
|
||||
function haversine(float $lat1, float $lon1, float $lat2, float $lon2): int {
|
||||
$R = 6371;
|
||||
$dLat = deg2rad($lat2 - $lat1);
|
||||
$dLon = deg2rad($lon2 - $lon1);
|
||||
$a = sin($dLat / 2) ** 2
|
||||
+ cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLon / 2) ** 2;
|
||||
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
|
||||
return (int) round($R * $c);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
// SMTP send (basic, without PHPMailer)
|
||||
// For production, install PHPMailer via Composer and
|
||||
// replace this function body accordingly.
|
||||
// -------------------------------------------------------
|
||||
function send_smtp(string $subject, string $body, string $headers): void {
|
||||
// Placeholder – integrate PHPMailer here:
|
||||
//
|
||||
// require __DIR__ . '/../vendor/autoload.php';
|
||||
// $mail = new PHPMailer\PHPMailer\PHPMailer(true);
|
||||
// $mail->isSMTP();
|
||||
// $mail->Host = SMTP_HOST;
|
||||
// $mail->SMTPAuth = true;
|
||||
// $mail->Username = SMTP_USER;
|
||||
// $mail->Password = SMTP_PASS;
|
||||
// $mail->SMTPSecure = SMTP_SECURE;
|
||||
// $mail->Port = SMTP_PORT;
|
||||
// $mail->setFrom(MAIL_FROM, MAIL_FROM_NAME);
|
||||
// $mail->addAddress(MAIL_TO);
|
||||
// $mail->Subject = $subject;
|
||||
// $mail->Body = $body;
|
||||
// $mail->send();
|
||||
|
||||
// Fallback to mail() until PHPMailer is integrated
|
||||
$sent = @mail(MAIL_TO, $subject, $body, $headers);
|
||||
if (!$sent) {
|
||||
error_log('Superfice SMTP fallback mail() failed');
|
||||
json_error('Beim Senden ist ein Fehler aufgetreten. Bitte schreiben Sie uns direkt.');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user