diff --git a/fp_altcha_spamschutz/src/Service/AltchaService.php b/fp_altcha_spamschutz/src/Service/AltchaService.php new file mode 100644 index 0000000..f365924 --- /dev/null +++ b/fp_altcha_spamschutz/src/Service/AltchaService.php @@ -0,0 +1,141 @@ +plugin = $plugin; + $this->altcha = new Altcha($this->getHmacSecret()); + } + + public function isConfigured(): bool + { + return $this->getHmacSecret() !== ''; + } + + public function isEnabledForRegistration(): bool + { + return $this->getConfigValue('fp_altcha_protect_register', 'on') === 'on'; + } + + public function isEnabledForNewsletter(): bool + { + return $this->getConfigValue('fp_altcha_protect_newsletter', 'on') === 'on'; + } + + public function isDebug(): bool + { + return $this->getConfigValue('fp_altcha_debug', '') === 'on'; + } + + /** + * Erzeugt eine neue Pruefung und liefert sie als Array, das 1:1 als JSON in die Seite + * eingebettet werden kann (siehe TemplateHandler). + * + * @return array + */ + public function createChallengeArray(): array + { + $maxNumber = (int) $this->getConfigValue('fp_altcha_max_number', '150000'); + if ($maxNumber < 1000) { + $maxNumber = 150000; + } + + $expirySeconds = (int) $this->getConfigValue('fp_altcha_expiry_seconds', '600'); + if ($expirySeconds < 30) { + $expirySeconds = 600; + } + + $expires = new \DateTimeImmutable('+' . $expirySeconds . ' seconds'); + + $challenge = $this->altcha->createChallenge(new ChallengeOptions( + algorithm: Algorithm::SHA256, + maxNumber: $maxNumber, + expires: $expires, + )); + + return [ + 'algorithm' => $challenge->algorithm, + 'challenge' => $challenge->challenge, + 'maxnumber' => $challenge->maxNumber, + 'salt' => $challenge->salt, + 'signature' => $challenge->signature, + ]; + } + + /** + * Prueft das per POST["altcha"] gesendete, base64-kodierte Loesungs-Payload. + */ + public function verifyPost(): bool + { + $field = $_POST['altcha'] ?? null; + + if (!\is_string($field) || $field === '') { + $this->log('kein altcha Feld im POST gefunden'); + + return false; + } + + if (!$this->isConfigured()) { + // Kein HMAC-Secret hinterlegt -> Plugin ist nicht korrekt eingerichtet. + // Sicherheitshalber ablehnen statt durchzulassen. + $this->log('kein HMAC-Secret konfiguriert, Pruefung wird abgelehnt'); + + return false; + } + + $verified = $this->altcha->verifySolution($field, true); + $this->log('Pruefungsergebnis: ' . ($verified ? 'erfolgreich' : 'fehlgeschlagen')); + + return $verified; + } + + private function getHmacSecret(): string + { + return $this->getConfigValue('fp_altcha_hmac_secret', ''); + } + + private function getConfigValue(string $name, string $default): string + { + $value = $this->plugin->getConfig()->getValue($name); + + if (!\is_string($value) || $value === '') { + return $default; + } + + return $value; + } + + private function log(string $message): void + { + if (!$this->isDebug()) { + return; + } + + error_log('[fp_altcha_spamschutz] ' . $message); + } +}