170ca9c90SGreg Roach<?php 270ca9c90SGreg Roach 370ca9c90SGreg Roach/** 470ca9c90SGreg Roach * webtrees: online genealogy 5*89f7189bSGreg Roach * Copyright (C) 2021 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 15*89f7189bSGreg 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; 2370ca9c90SGreg Roachuse Psr\Http\Message\ServerRequestInterface; 2470ca9c90SGreg Roachuse Ramsey\Uuid\Uuid; 2570ca9c90SGreg Roach 2670ca9c90SGreg Roachuse function view; 2770ca9c90SGreg Roach 2870ca9c90SGreg Roach/** 2970ca9c90SGreg Roach * Completely Automated Public Turing test to tell Computers and Humans Apart. 3070ca9c90SGreg Roach */ 3170ca9c90SGreg Roachclass CaptchaService 3270ca9c90SGreg Roach{ 3370ca9c90SGreg Roach // If the form is completed faster than this, then suspect a robot. 3470ca9c90SGreg Roach private const MINIMUM_FORM_TIME = 3.0; 3570ca9c90SGreg Roach 3670ca9c90SGreg Roach /** 3770ca9c90SGreg Roach * Create the captcha 3870ca9c90SGreg Roach * 3970ca9c90SGreg Roach * @return string 4070ca9c90SGreg Roach */ 4170ca9c90SGreg Roach public function createCaptcha(): string 4270ca9c90SGreg Roach { 4370ca9c90SGreg Roach $x = Uuid::uuid4()->toString(); 4470ca9c90SGreg Roach $y = Uuid::uuid4()->toString(); 4570ca9c90SGreg Roach $z = Uuid::uuid4()->toString(); 4670ca9c90SGreg Roach 4770ca9c90SGreg Roach Session::put('captcha-t', microtime(true)); 4870ca9c90SGreg Roach Session::put('captcha-x', $x); 4970ca9c90SGreg Roach Session::put('captcha-y', $y); 5070ca9c90SGreg Roach Session::put('captcha-z', $z); 5170ca9c90SGreg Roach 5270ca9c90SGreg Roach return view('captcha', [ 5370ca9c90SGreg Roach 'x' => $x, 5470ca9c90SGreg Roach 'y' => $y, 5570ca9c90SGreg Roach 'z' => $z, 5670ca9c90SGreg Roach ]); 5770ca9c90SGreg Roach } 5870ca9c90SGreg Roach 5970ca9c90SGreg Roach /** 6070ca9c90SGreg Roach * Check the user's response. 6170ca9c90SGreg Roach * 6270ca9c90SGreg Roach * @param ServerRequestInterface $request 6370ca9c90SGreg Roach * 6470ca9c90SGreg Roach * @return bool 6570ca9c90SGreg Roach */ 6670ca9c90SGreg Roach public function isRobot(ServerRequestInterface $request): bool 6770ca9c90SGreg Roach { 6870ca9c90SGreg Roach $t = Session::pull('captcha-t', ''); 6970ca9c90SGreg Roach $x = Session::pull('captcha-x', ''); 7070ca9c90SGreg Roach $y = Session::pull('captcha-y', ''); 7170ca9c90SGreg Roach $z = Session::pull('captcha-z', ''); 7270ca9c90SGreg Roach 7370ca9c90SGreg Roach $value_x = $request->getParsedBody()[$x] ?? ''; 7470ca9c90SGreg Roach $value_y = $request->getParsedBody()[$y] ?? ''; 7570ca9c90SGreg Roach 7670ca9c90SGreg Roach // The captcha uses javascript to copy value z from field y to field x. 7770ca9c90SGreg Roach // Expect it in both fields. 7870ca9c90SGreg Roach if ($value_x !== $z || $value_y !== $z) { 7970ca9c90SGreg Roach return true; 8070ca9c90SGreg Roach } 8170ca9c90SGreg Roach 8270ca9c90SGreg Roach // If the form was returned too quickly, the probably a robot. 8370ca9c90SGreg Roach return microtime(true) < $t + self::MINIMUM_FORM_TIME; 8470ca9c90SGreg Roach } 8570ca9c90SGreg Roach} 86