Passed
Push — master ( 8246ff...70ca9c )
by Greg
05:43
created

CaptchaService::createCaptcha()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 11
c 1
b 0
f 1
nc 1
nop 0
dl 0
loc 15
rs 9.9
1
<?php
2
3
/**
4
 * webtrees: online genealogy
5
 * Copyright (C) 2019 webtrees development team
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16
 */
17
18
declare(strict_types=1);
19
20
namespace Fisharebest\Webtrees\Services;
21
22
use Fisharebest\Webtrees\Session;
23
use Psr\Http\Message\ServerRequestInterface;
24
use Ramsey\Uuid\Uuid;
25
26
use function view;
27
28
/**
29
 * Completely Automated Public Turing test to tell Computers and Humans Apart.
30
 */
31
class CaptchaService
32
{
33
    // If the form is completed faster than this, then suspect a robot.
34
    private const MINIMUM_FORM_TIME = 3.0;
35
36
    /**
37
     * Create the captcha
38
     *
39
     * @return string
40
     */
41
    public function createCaptcha(): string
42
    {
43
        $x = Uuid::uuid4()->toString();
44
        $y = Uuid::uuid4()->toString();
45
        $z = Uuid::uuid4()->toString();
46
47
        Session::put('captcha-t', microtime(true));
48
        Session::put('captcha-x', $x);
49
        Session::put('captcha-y', $y);
50
        Session::put('captcha-z', $z);
51
52
        return view('captcha', [
53
            'x' => $x,
54
            'y' => $y,
55
            'z' => $z,
56
        ]);
57
    }
58
59
    /**
60
     * Check the user's response.
61
     *
62
     * @param ServerRequestInterface $request
63
     *
64
     * @return bool
65
     */
66
    public function isRobot(ServerRequestInterface $request): bool
67
    {
68
        $t = Session::pull('captcha-t', '');
69
        $x = Session::pull('captcha-x', '');
70
        $y = Session::pull('captcha-y', '');
71
        $z = Session::pull('captcha-z', '');
72
73
        $value_x = $request->getParsedBody()[$x] ?? '';
74
        $value_y = $request->getParsedBody()[$y] ?? '';
75
76
        // The captcha uses javascript to copy value z from field y to field x.
77
        // Expect it in both fields.
78
        if ($value_x !== $z || $value_y !== $z) {
79
            return true;
80
        }
81
82
        // If the form was returned too quickly, the probably a robot.
83
        return microtime(true) < $t + self::MINIMUM_FORM_TIME;
84
    }
85
}
86