113 lines
3.9 KiB
PHP
113 lines
3.9 KiB
PHP
<?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.');
|
||
}
|
||
}
|