<?php declare(strict_types=1); namespace Plugin\fp_altcha_spamschutz\src\Handler; use Plugin\fp_altcha_spamschutz\src\Service\AltchaService; /** * Prueft die ALTCHA-Loesung bei Registrierung und Newsletter-Anmeldung. * * Registrierung: nutzt den dokumentierten Hook HOOK_REGISTRIEREN_PAGE_REGISTRIEREN_PLAUSI (41), * der genau fuer diesen Zweck (Plausibilitaetspruefung nach Formularabsendung) vorgesehen ist. * Bei fehlender/ungueltiger Pruefung wird ein Eintrag zu "fehlendeAngaben" hinzugefuegt -- das ist * derselbe Mechanismus, den JTL-Shop fuer "Pflichtfeld nicht ausgefuellt" nutzt, der Kunde bekommt * also die normale, vertraute Fehlermeldung des Shops. * * Newsletter: die Dokumentation zum passenden Hook (HOOK_NEWSLETTER_PAGE_EMPFAENGEREINTRAGEN) ist * nicht eindeutig genug, um sich allein darauf zu verlassen. Deshalb wird zusaetzlich ganz frueh * (direkt in Bootstrap::boot(), vor jeder Shop-Verarbeitung) geprueft: schlaegt die Pruefung fehl, * wird das POST-Feld "abonnieren" entfernt, sodass JTL-Shop die Anmeldung erst gar nicht verarbeitet. * Der Hook-Handler unten ist eine zusaetzliche Absicherung ("defense in depth"), falls dieser fruehe * Filter aus irgendeinem Grund nicht greift. */ class ValidationHandler { private AltchaService $altchaService; public function __construct(AltchaService $altchaService) { $this->altchaService = $altchaService; } /** * @param array<string, mixed> $args */ public function checkRegistrationPlausibility(array $args): void { try { if (!$this->altchaService->isEnabledForRegistration()) { return; } if ($this->altchaService->verifyPost()) { return; } if (isset($args['fehlendeAngaben']) && \is_array($args['fehlendeAngaben'])) { $args['fehlendeAngaben'][] = 'Sicherheitspruefung'; } if (\array_key_exists('nReturnValue', $args)) { $args['nReturnValue'] = 0; } } catch (\Throwable $e) { // Bewusste Entscheidung: bei einem unerwarteten Fehler (z. B. Plugin nicht vollstaendig // konfiguriert) lieber die Registrierung durchlassen, als die komplette Registrierungs- // seite fuer echte Kunden zu blockieren. Ein Bot mehr ist besser als ein Shop, bei dem // sich niemand mehr registrieren kann. if ($this->altchaService->isDebug()) { error_log('[fp_altcha_spamschutz] Fehler bei Registrierungspruefung: ' . $e->getMessage()); } } } /** * Fruehe Pruefung fuer die Newsletter-Anmeldung. Wird direkt aus Bootstrap::boot() aufgerufen, * nicht ueber einen Hook, damit sie garantiert vor der Verarbeitung durch newsletter.php laeuft. */ public function guardNewsletterSubmission(): void { try { if (!$this->altchaService->isEnabledForNewsletter()) { return; } $isNewsletterSubscribeSubmit = ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST' && isset($_POST['abonnieren']); if (!$isNewsletterSubscribeSubmit) { return; } if ($this->altchaService->verifyPost()) { return; } // Feld entfernen, damit JTL-Shop die Anmeldung nicht als "abonnieren"-Request erkennt // und stattdessen nur das (leere) Formular erneut anzeigt. unset($_POST['abonnieren']); $_SESSION['fp_altcha_newsletter_error'] = true; } catch (\Throwable $e) { // Wird direkt in Bootstrap::boot() aufgerufen (nicht ueber einen Hook) -- ein // Fehler hier darf auf keinen Fall den kompletten Seitenaufbau verhindern. if ($this->altchaService->isDebug()) { error_log('[fp_altcha_spamschutz] Fehler bei Newsletter-Fruehpruefung: ' . $e->getMessage()); } } } /** * Zusaetzliche Absicherung ueber HOOK_NEWSLETTER_PAGE_EMPFAENGEREINTRAGEN, falls die fruehe * Pruefung in guardNewsletterSubmission() aus irgendeinem Grund nicht gegriffen hat. * * @param array<string, mixed> $args Enthaelt 'oNewsletterEmpfaenger' (stdClass, per Referenz). */ public function checkNewsletterRecipient(array $args): void { try { if (!$this->altchaService->isEnabledForNewsletter()) { return; } if (!empty($_SESSION['fp_altcha_newsletter_error'])) { // Bereits in guardNewsletterSubmission() als ungueltig erkannt: Empfaenger-E-Mail // leeren, damit JTL-Shops eigene Pflichtfeld-Pruefung den Insert verhindert. if (isset($args['oNewsletterEmpfaenger']) && \is_object($args['oNewsletterEmpfaenger'])) { $args['oNewsletterEmpfaenger']->cEmail = ''; } } } catch (\Throwable $e) { if ($this->altchaService->isDebug()) { error_log('[fp_altcha_spamschutz] Fehler bei Newsletter-Absicherung: ' . $e->getMessage()); } } } }