• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

google / recaptcha / 23508296109

24 Mar 2026 07:24PM UTC coverage: 98.718% (-1.3%) from 100.0%
23508296109

Pull #606

github

web-flow
Merge 24d61226c into c665d185c
Pull Request #606: Type hints and more with PHPStan

17 of 19 new or added lines in 5 files covered. (89.47%)

154 of 156 relevant lines covered (98.72%)

15.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.1
/src/ReCaptcha/RequestMethod/SocketPost.php
1
<?php
2

3
/**
4
 * This is a PHP library that handles calling reCAPTCHA.
5
 *
6
 * BSD 3-Clause License
7
 *
8
 * @copyright (c) 2019, Google Inc.
9
 *
10
 * @see https://www.google.com/recaptcha
11
 * All rights reserved.
12
 *
13
 * Redistribution and use in source and binary forms, with or without
14
 * modification, are permitted provided that the following conditions are met:
15
 * 1. Redistributions of source code must retain the above copyright notice, this
16
 *    list of conditions and the following disclaimer.
17
 *
18
 * 2. Redistributions in binary form must reproduce the above copyright notice,
19
 *    this list of conditions and the following disclaimer in the documentation
20
 *    and/or other materials provided with the distribution.
21
 *
22
 * 3. Neither the name of the copyright holder nor the names of its
23
 *    contributors may be used to endorse or promote products derived from
24
 *    this software without specific prior written permission.
25
 *
26
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
30
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
 */
37

38
namespace ReCaptcha\RequestMethod;
39

40
use ReCaptcha\ReCaptcha;
41
use ReCaptcha\RequestMethod;
42
use ReCaptcha\RequestParameters;
43

44
/**
45
 * Sends a POST request to the reCAPTCHA service, but makes use of fsockopen()
46
 * instead of get_file_contents(). This is to account for people who may be on
47
 * servers where allow_url_open is disabled.
48
 */
49
class SocketPost implements RequestMethod
50
{
51
    private string $siteVerifyUrl;
52

53
    /**
54
     * Only needed if you want to override the defaults.
55
     *
56
     * @param null|string $siteVerifyUrl URL for reCAPTCHA siteverify API
57
     */
58
    public function __construct(?string $siteVerifyUrl = null)
59
    {
60
        $this->siteVerifyUrl = (is_null($siteVerifyUrl)) ? ReCaptcha::SITE_VERIFY_URL : $siteVerifyUrl;
6✔
61
    }
62

63
    /**
64
     * Submit the POST request with the specified parameters.
65
     *
66
     * @param RequestParameters $params Request parameters
67
     *
68
     * @return string Body of the reCAPTCHA response
69
     */
70
    public function submit(RequestParameters $params): string
71
    {
72
        $errno = 0;
6✔
73
        $errstr = '';
6✔
74
        $urlParsed = parse_url($this->siteVerifyUrl);
6✔
75

76
        if (false === $urlParsed || !isset($urlParsed['host']) || !isset($urlParsed['path'])) {
6✔
NEW
77
            return '{"success": false, "error-codes": ["'.ReCaptcha::E_CONNECTION_FAILED.'"]}';
×
78
        }
79

80
        $handle = fsockopen('ssl://'.$urlParsed['host'], 443, $errno, $errstr, 30);
6✔
81

82
        if (false === $handle || 0 !== $errno || '' !== $errstr) {
6✔
83
            return '{"success": false, "error-codes": ["'.ReCaptcha::E_CONNECTION_FAILED.'"]}';
2✔
84
        }
85

86
        $content = $params->toQueryString();
4✔
87

88
        $request = 'POST '.$urlParsed['path']." HTTP/1.0\r\n";
4✔
89
        $request .= 'Host: '.$urlParsed['host']."\r\n";
4✔
90
        $request .= "Content-Type: application/x-www-form-urlencoded\r\n";
4✔
91
        $request .= 'Content-length: '.strlen($content)."\r\n";
4✔
92
        $request .= "Connection: close\r\n\r\n";
4✔
93
        $request .= $content."\r\n\r\n";
4✔
94

95
        fwrite($handle, $request);
4✔
96
        $response = '';
4✔
97

98
        while (!feof($handle)) {
4✔
99
            $line = fgets($handle, 4096);
4✔
100
            if (is_string($line)) {
4✔
101
                $response .= $line;
4✔
102
            }
103
        }
104

105
        fclose($handle);
4✔
106

107
        if (0 !== strpos($response, 'HTTP/1.0 200 OK')) {
4✔
108
            return '{"success": false, "error-codes": ["'.ReCaptcha::E_BAD_RESPONSE.'"]}';
2✔
109
        }
110

111
        $parts = preg_split("#\n\\s*\n#Uis", $response);
2✔
112

113
        if (!is_array($parts) || !isset($parts[1])) {
2✔
NEW
114
            return '{"success": false, "error-codes": ["'.ReCaptcha::E_BAD_RESPONSE.'"]}';
×
115
        }
116

117
        return $parts[1];
2✔
118
    }
119
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc