xref: /webtrees/app/Services/CaptchaService.php (revision 89f7189b61a494347591c99bdb92afb7d8b66e1b)
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