170ca9c90SGreg Roach<?php 270ca9c90SGreg Roach 370ca9c90SGreg Roach/** 470ca9c90SGreg Roach * webtrees: online genealogy 5*5bfc6897SGreg Roach * Copyright (C) 2022 webtrees development team 670ca9c90SGreg Roach * This program is free software: you can redistribute it and/or modify 770ca9c90SGreg Roach * it under the terms of the GNU General Public License as published by 870ca9c90SGreg Roach * the Free Software Foundation, either version 3 of the License, or 970ca9c90SGreg Roach * (at your option) any later version. 1070ca9c90SGreg Roach * This program is distributed in the hope that it will be useful, 1170ca9c90SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 1270ca9c90SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1370ca9c90SGreg Roach * GNU General Public License for more details. 1470ca9c90SGreg Roach * You should have received a copy of the GNU General Public License 1589f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>. 1670ca9c90SGreg Roach */ 1770ca9c90SGreg Roach 1870ca9c90SGreg Roachdeclare(strict_types=1); 1970ca9c90SGreg Roach 2070ca9c90SGreg Roachnamespace Fisharebest\Webtrees\Services; 2170ca9c90SGreg Roach 2270ca9c90SGreg Roachuse Fisharebest\Webtrees\Session; 23b55cbc6bSGreg Roachuse Fisharebest\Webtrees\Validator; 2470ca9c90SGreg Roachuse Psr\Http\Message\ServerRequestInterface; 2570ca9c90SGreg Roachuse Ramsey\Uuid\Uuid; 2670ca9c90SGreg Roach 2770ca9c90SGreg Roachuse function view; 2870ca9c90SGreg Roach 2970ca9c90SGreg Roach/** 3070ca9c90SGreg Roach * Completely Automated Public Turing test to tell Computers and Humans Apart. 3170ca9c90SGreg Roach */ 3270ca9c90SGreg Roachclass CaptchaService 3370ca9c90SGreg Roach{ 3470ca9c90SGreg Roach // If the form is completed faster than this, then suspect a robot. 3570ca9c90SGreg Roach private const MINIMUM_FORM_TIME = 3.0; 3670ca9c90SGreg Roach 3770ca9c90SGreg Roach /** 3870ca9c90SGreg Roach * Create the captcha 3970ca9c90SGreg Roach * 4070ca9c90SGreg Roach * @return string 4170ca9c90SGreg Roach */ 4270ca9c90SGreg Roach public function createCaptcha(): string 4370ca9c90SGreg Roach { 4470ca9c90SGreg Roach $x = Uuid::uuid4()->toString(); 4570ca9c90SGreg Roach $y = Uuid::uuid4()->toString(); 4670ca9c90SGreg Roach $z = Uuid::uuid4()->toString(); 4770ca9c90SGreg Roach 4870ca9c90SGreg Roach Session::put('captcha-t', microtime(true)); 4970ca9c90SGreg Roach Session::put('captcha-x', $x); 5070ca9c90SGreg Roach Session::put('captcha-y', $y); 5170ca9c90SGreg Roach Session::put('captcha-z', $z); 5270ca9c90SGreg Roach 5370ca9c90SGreg Roach return view('captcha', [ 5470ca9c90SGreg Roach 'x' => $x, 5570ca9c90SGreg Roach 'y' => $y, 5670ca9c90SGreg Roach 'z' => $z, 5770ca9c90SGreg Roach ]); 5870ca9c90SGreg Roach } 5970ca9c90SGreg Roach 6070ca9c90SGreg Roach /** 6170ca9c90SGreg Roach * Check the user's response. 6270ca9c90SGreg Roach * 6370ca9c90SGreg Roach * @param ServerRequestInterface $request 6470ca9c90SGreg Roach * 6570ca9c90SGreg Roach * @return bool 6670ca9c90SGreg Roach */ 6770ca9c90SGreg Roach public function isRobot(ServerRequestInterface $request): bool 6870ca9c90SGreg Roach { 69d8809d62SGreg Roach $t = Session::pull('captcha-t'); 70d8809d62SGreg Roach $x = Session::pull('captcha-x'); 71d8809d62SGreg Roach $y = Session::pull('captcha-y'); 72d8809d62SGreg Roach $z = Session::pull('captcha-z'); 7370ca9c90SGreg Roach 74b55cbc6bSGreg Roach assert(is_int($t)); 75b55cbc6bSGreg Roach assert(is_string($x)); 76b55cbc6bSGreg Roach assert(is_string($y)); 77b55cbc6bSGreg Roach assert(is_string($z)); 78b55cbc6bSGreg Roach 79b55cbc6bSGreg Roach $value_x = Validator::parsedBody($request)->string($x, ''); 80b55cbc6bSGreg Roach $value_y = Validator::parsedBody($request)->string($y, ''); 8170ca9c90SGreg Roach 8270ca9c90SGreg Roach // The captcha uses javascript to copy value z from field y to field x. 8370ca9c90SGreg Roach // Expect it in both fields. 8470ca9c90SGreg Roach if ($value_x !== $z || $value_y !== $z) { 8570ca9c90SGreg Roach return true; 8670ca9c90SGreg Roach } 8770ca9c90SGreg Roach 8870ca9c90SGreg Roach // If the form was returned too quickly, the probably a robot. 8970ca9c90SGreg Roach return microtime(true) < $t + self::MINIMUM_FORM_TIME; 9070ca9c90SGreg Roach } 9170ca9c90SGreg Roach} 92