ReCaptcha::response()   B
last analyzed

Complexity

Conditions 9
Paths 15

Size

Total Lines 61
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 28
CRAP Score 9.0033

Importance

Changes 0
Metric Value
eloc 32
c 0
b 0
f 0
dl 0
loc 61
ccs 28
cts 29
cp 0.9655
rs 8.0555
cc 9
nc 15
nop 0
crap 9.0033

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * This file is part of the Shieldon package.
4
 *
5
 * (c) Terry L. <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * php version 7.1.0
11
 *
12
 * @category  Web-security
13
 * @package   Shieldon
14
 * @author    Terry Lin <[email protected]>
15
 * @copyright 2019 terrylinooo
16
 * @license   https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT
17
 * @link      https://github.com/terrylinooo/shieldon
18
 * @see       https://shieldon.io
19
 */
20
21
declare(strict_types=1);
22
23
namespace Shieldon\Firewall\Captcha;
24
25
use Shieldon\Firewall\Captcha\CaptchaProvider;
26
27
use function Shieldon\Firewall\get_request;
28
use function Shieldon\Firewall\unset_superglobal;
29
use CurlHandle; // PHP 8
30
use function curl_error;
31
use function curl_exec;
32
use function curl_init;
33
use function curl_setopt;
34
use function is_string;
35
use function json_decode;
36
37
/**
38
 * Google reCaptcha.
39
 */
40
class ReCaptcha extends CaptchaProvider
41
{
42
    /**
43
     * The site key.
44
     *
45
     * @var string
46
     */
47
    protected $key = '';
48
49
    /**
50
     * The secret key.
51
     *
52
     * @var string
53
     */
54
    protected $secret = '';
55
56
    /**
57
     * The version.
58
     *
59
     * @var string
60
     */
61
    protected $version = 'v2';
62
63
    /**
64
     * The language code of the UI.
65
     *
66
     * @var string
67
     */
68
    protected $lang = 'en';
69
70
    /**
71
     * The URL of Google ReCaptcha API.
72
     *
73
     * @var string
74
     */
75
    protected $googleServiceUrl = 'https://www.google.com/recaptcha/api/siteverify';
76
77
    /**
78
     * Constructor.
79
     *
80
     * It will implement default configuration settings here.
81
     *
82
     * @param array $config The settings of Google ReCpatcha.
83
     *
84
     * @return void
85
     */
86 19
    public function __construct(array $config = [])
87
    {
88 19
        parent::__construct();
89
        
90 19
        foreach ($config as $k => $v) {
91 19
            if (isset($this->{$k})) {
92 19
                $this->{$k} = $v;
93
            }
94
        }
95
    }
96
97
    /**
98
     * Response the result from Google service server.
99
     *
100
     * @return bool
101
     */
102 1
    public function response(): bool
103
    {
104 1
        $postParams = get_request()->getParsedBody();
105
106 1
        if (empty($postParams['g-recaptcha-response'])) {
107 1
            return false;
108
        }
109
110 1
        $flag = false;
111 1
        $reCaptchaToken = str_replace(["'", '"'], '', $postParams['g-recaptcha-response']);
112
113 1
        $postData = [
114 1
            'secret' => $this->secret,
115 1
            'response' => $reCaptchaToken,
116 1
        ];
117
118 1
        $ch = curl_init();
119
120 1
        if (version_compare(phpversion(), '8.0.0', '>=')) {
121
            if (!$ch instanceof CurlHandle) {
122
                // @codeCoverageIgnoreStart
123
                return false;
124
                // @codeCoverageIgnoreEnd
125
            }
126
        } else {
127 1
            if (!is_resource($ch)) {
128
                // @codeCoverageIgnoreStart
129
                return false;
130
                // @codeCoverageIgnoreEnd
131
            }
132
        }
133
134 1
        curl_setopt($ch, CURLOPT_URL, $this->googleServiceUrl);
135 1
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
136 1
        curl_setopt($ch, CURLOPT_POST, 2);
137 1
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
138 1
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
139 1
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
140 1
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
141
142 1
        $ret = curl_exec($ch);
143
144
        // @codeCoverageIgnoreStart
145
        if (curl_errno($ch)) {
146
            echo 'error:' . curl_error($ch);
147
        }
148
        // @codeCoverageIgnoreEnd
149
150 1
        if (isset($ret) && is_string($ret)) {
151 1
            $tmp = json_decode($ret);
152 1
            if ($tmp->success == true) {
153 1
                $flag = true;
154
            }
155
        }
156
157 1
        curl_close($ch);
158
159
        // Prevent detecting POST method on RESTful frameworks.
160 1
        unset_superglobal('g-recaptcha-response', 'post');
161
162 1
        return $flag;
163
    }
164
165
    /**
166
     * Output a required HTML for reCaptcha v2.
167
     *
168
     * @return string
169
     */
170 3
    public function form(): string
171
    {
172 3
        $html = '<div>';
173 3
        $html .= '<div style="display: inline-block">';
174 3
        if ('v3' !== $this->version) {
175 3
            $html .= '<script src="https://www.google.com/recaptcha/api.js?hl=' . $this->lang . '"></script>';
176 3
            $html .= '<div class="g-recaptcha" data-sitekey="' . $this->key . '"></div>';
177
        } else {
178 1
            $html .= '<input type="hidden" name="g-recaptcha-response" id="g-recaptcha-response" value="">';
179 1
            $html .= '<script src="https://www.google.com/recaptcha/api.js?render=' .
180 1
                $this->key .'&hl=' . $this->lang . '"></script>';
181 1
            $html .= '<script>';
182 1
            $html .= '    grecaptcha.ready(function() {';
183 1
            $html .= '        grecaptcha.execute("' . $this->key . '", {action: "homepage"}).then(function(token) {';
184 1
            $html .= '            document.getElementById("g-recaptcha-response").value = token;';
185 1
            $html .= '        }); ';
186 1
            $html .= '    });';
187
            $html .= '</script>';
188 3
        }
189 3
        $html .= '</div>';
190
        $html .= '</div>';
191 3
192
        return $html;
193
    }
194
}
195