Files
2026-11-08 20:09:19 +00:00

121 lines
4.1 KiB
PHP

<?php
/**
* Gemeinsame Hilfsfunktionen: Einstellungen lesen, Besucher erkennen, Signaturen für Formularangaben.
*/
if (!defined('ABSPATH')) {
exit;
}
/** Standardwerte aller Einstellungen. */
function deskhub_tickets_defaults(): array
{
return [
'server_url' => '',
'api_key' => '',
'department_id' => 0,
'topic_id' => 0,
'priority_id' => 0,
'consent_text' => '',
'accent_color' => '',
'attachments' => 1,
'success_text' => '',
'status_page_url' => '',
'min_seconds' => 3,
'rate_limit_per_hour' => 5,
'turnstile_site' => '',
'turnstile_secret' => '',
];
}
/** Alle Einstellungen (mit Standardwerten). Server-Adresse und Schlüssel lassen sich zusätzlich in der wp-config.php festlegen. */
function deskhub_tickets_options(): array
{
$saved = get_option('deskhub_tickets_options', []);
$opts = array_merge(deskhub_tickets_defaults(), is_array($saved) ? $saved : []);
if (defined('DESKHUB_TICKETS_SERVER') && DESKHUB_TICKETS_SERVER !== '') {
$opts['server_url'] = (string) DESKHUB_TICKETS_SERVER;
}
if (defined('DESKHUB_TICKETS_API_KEY') && DESKHUB_TICKETS_API_KEY !== '') {
$opts['api_key'] = (string) DESKHUB_TICKETS_API_KEY;
}
return $opts;
}
function deskhub_tickets_option(string $key)
{
$opts = deskhub_tickets_options();
return $opts[$key] ?? null;
}
/** Wird der API-Schlüssel aus der wp-config.php genommen (dann ist das Feld in den Einstellungen gesperrt)? */
function deskhub_tickets_key_from_config(): bool
{
return defined('DESKHUB_TICKETS_API_KEY') && DESKHUB_TICKETS_API_KEY !== '';
}
/**
* Erkennt den Besucher für die Mengenbegrenzung. Es zählt nur REMOTE_ADDR: Header wie X-Forwarded-For kann jeder selbst setzen.
* Steht die Seite hinter einem Proxy, liefert der Filter "deskhub_tickets_client_ip" die richtige Adresse.
*/
function deskhub_tickets_client_ip(): string
{
$ip = isset($_SERVER['REMOTE_ADDR']) ? (string) $_SERVER['REMOTE_ADDR'] : '';
$ip = apply_filters('deskhub_tickets_client_ip', $ip);
return filter_var($ip, FILTER_VALIDATE_IP) ? (string) $ip : 'unknown';
}
/** Kurzer Schlüssel für einen Besucher (nicht umkehrbar, damit keine IP-Adressen in der Datenbank stehen). */
function deskhub_tickets_visitor_key(string $scope): string
{
return 'dht_' . substr(hash_hmac('sha256', $scope . '|' . deskhub_tickets_client_ip(), wp_salt('auth')), 0, 32);
}
/**
* Zählt einen Vorgang für den Besucher und sagt, ob er noch erlaubt ist.
* $max Vorgänge je $window Sekunden; false = Grenze erreicht (der Vorgang wird dann nicht mehr gezählt).
*/
function deskhub_tickets_rate_allow(string $scope, int $max, int $window): bool
{
if ($max <= 0) {
return true;
}
$key = deskhub_tickets_visitor_key($scope);
$count = (int) get_transient($key);
if ($count >= $max) {
return false;
}
set_transient($key, $count + 1, $window);
return true;
}
/** Unterschreibt Angaben, die durchs Formular laufen (Abteilung, Thema, Priorität), damit Besucher sie nicht ändern können. */
function deskhub_tickets_sign(string $payload): string
{
return hash_hmac('sha256', $payload, wp_salt('auth'));
}
function deskhub_tickets_verify_signature(string $payload, string $signature): bool
{
return $signature !== '' && hash_equals(deskhub_tickets_sign($payload), $signature);
}
/** Zeitstempel mit Unterschrift: beweist, wann das Formular angezeigt wurde (Schutz vor Robotern, die sofort absenden). */
function deskhub_tickets_timestamp_token(): string
{
$t = (string) time();
return $t . '.' . deskhub_tickets_sign('ts|' . $t);
}
/** Alter des Formulars in Sekunden; null, wenn der Wert fehlt oder gefälscht ist. */
function deskhub_tickets_timestamp_age(string $token): ?int
{
if (!preg_match('/^(\d{9,11})\.([a-f0-9]{64})$/', $token, $m)) {
return null;
}
if (!deskhub_tickets_verify_signature('ts|' . $m[1], $m[2])) {
return null;
}
return time() - (int) $m[1];
}