Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
Interval
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
3 / 3
5
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 verify
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
3
 getErrorMessage
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3/**
4 * Interval CAPTCHA (requires an interval between actions or from start of session).
5 *
6 * PHP version 8
7 *
8 * Copyright (C) The National Library of Finland 2021.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2,
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 *
23 * @category VuFind
24 * @package  CAPTCHA
25 * @author   Ere Maijala <ere.maijala@helsinki.fi>
26 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     https://vufind.org Main Page
28 */
29
30namespace VuFind\Captcha;
31
32use Laminas\Config\Config;
33use Laminas\Mvc\Controller\Plugin\Params;
34use Laminas\Session\Container as SessionContainer;
35use VuFind\I18n\Translator\TranslatorAwareInterface;
36use VuFind\I18n\Translator\TranslatorAwareTrait;
37
38use function intval;
39
40/**
41 * Interval CAPTCHA (requires an interval between actions or from start of session).
42 *
43 * @category VuFind
44 * @package  CAPTCHA
45 * @author   Ere Maijala <ere.maijala@helsinki.fi>
46 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
47 * @link     https://vufind.org/wiki/development Wiki
48 */
49class Interval extends AbstractBase implements TranslatorAwareInterface
50{
51    use TranslatorAwareTrait;
52
53    /**
54     * Session data container
55     *
56     * @var SessionContainer
57     */
58    protected $sessionData;
59
60    /**
61     * Minimum action interval in seconds
62     *
63     * @var int
64     */
65    protected $actionInterval;
66
67    /**
68     * Minimum time from session start to first action
69     *
70     * @var int
71     */
72    protected $timeFromSessionStart;
73
74    /**
75     * Verification error message
76     *
77     * @var string
78     */
79    protected $errorMessage = '';
80
81    /**
82     * Constructor
83     *
84     * @param SessionContainer $sc     Session data container
85     * @param Config           $config VuFind main configuration
86     */
87    public function __construct(SessionContainer $sc, Config $config)
88    {
89        $this->sessionData = $sc;
90        $this->actionInterval = intval($config->Captcha->action_interval ?? 60);
91        $this->timeFromSessionStart = intval(
92            $config->Captcha->time_from_session_start ?? $this->actionInterval
93        );
94    }
95
96    /**
97     * Pull the captcha field from controller params and check them for accuracy
98     *
99     * @param Params $params Controller params
100     *
101     * @return bool
102     *
103     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
104     */
105    public function verify(Params $params): bool
106    {
107        if (isset($this->sessionData->lastProtectedActionTime)) {
108            $timestamp = $this->sessionData->lastProtectedActionTime;
109            $requiredInterval = $this->actionInterval;
110        } else {
111            $timestamp = $this->sessionData->sessionStartTime;
112            $requiredInterval = $this->timeFromSessionStart;
113        }
114        $timePassed = time() - $timestamp;
115        if ($timePassed < $requiredInterval) {
116            $this->errorMessage = $this->translate(
117                'interval_captcha_not_passed',
118                [
119                    '%%delay%%' => max($requiredInterval - $timePassed, 1),
120                ]
121            );
122            return false;
123        }
124        $this->sessionData->lastProtectedActionTime = time();
125        return true;
126    }
127
128    /**
129     * Get any error message after a failed captcha verification. The message can be
130     * displayed to the user.
131     *
132     * @return string
133     */
134    public function getErrorMessage(): string
135    {
136        return $this->errorMessage;
137    }
138}