Subversion Repositories php_guestbook

Rev

Blame | Last modification | View Log | RSS feed

  1. <?php
  2. /**
  3.  * This is a PHP library that handles calling reCAPTCHA.
  4.  *
  5.  * @copyright Copyright (c) 2015, Google Inc.
  6.  * @link      http://www.google.com/recaptcha
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a copy
  9.  * of this software and associated documentation files (the "Software"), to deal
  10.  * in the Software without restriction, including without limitation the rights
  11.  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12.  * copies of the Software, and to permit persons to whom the Software is
  13.  * furnished to do so, subject to the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice shall be included in
  16.  * all copies or substantial portions of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21.  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24.  * THE SOFTWARE.
  25.  */
  26.  
  27. namespace ReCaptcha\RequestMethod;
  28.  
  29. use ReCaptcha\RequestMethod;
  30. use ReCaptcha\RequestParameters;
  31.  
  32. /**
  33.  * Sends a POST request to the reCAPTCHA service, but makes use of fsockopen()
  34.  * instead of get_file_contents(). This is to account for people who may be on
  35.  * servers where allow_url_open is disabled.
  36.  */
  37. class SocketPost implements RequestMethod
  38. {
  39.     /**
  40.      * reCAPTCHA service host.
  41.      * @const string
  42.      */
  43.     const RECAPTCHA_HOST = 'www.google.com';
  44.  
  45.     /**
  46.      * @const string reCAPTCHA service path
  47.      */
  48.     const SITE_VERIFY_PATH = '/recaptcha/api/siteverify';
  49.  
  50.     /**
  51.      * @const string Bad request error
  52.      */
  53.     const BAD_REQUEST = '{"success": false, "error-codes": ["invalid-request"]}';
  54.  
  55.     /**
  56.      * @const string Bad response error
  57.      */
  58.     const BAD_RESPONSE = '{"success": false, "error-codes": ["invalid-response"]}';
  59.  
  60.     /**
  61.      * Socket to the reCAPTCHA service
  62.      * @var Socket
  63.      */
  64.     private $socket;
  65.  
  66.     /**
  67.      * Constructor
  68.      *
  69.      * @param \ReCaptcha\RequestMethod\Socket $socket optional socket, injectable for testing
  70.      */
  71.     public function __construct(Socket $socket = null)
  72.     {
  73.         if (!is_null($socket)) {
  74.             $this->socket = $socket;
  75.         } else {
  76.             $this->socket = new Socket();
  77.         }
  78.     }
  79.  
  80.     /**
  81.      * Submit the POST request with the specified parameters.
  82.      *
  83.      * @param RequestParameters $params Request parameters
  84.      * @return string Body of the reCAPTCHA response
  85.      */
  86.     public function submit(RequestParameters $params)
  87.     {
  88.         $errno = 0;
  89.         $errstr = '';
  90.  
  91.         if (false === $this->socket->fsockopen('ssl://' . self::RECAPTCHA_HOST, 443, $errno, $errstr, 30)) {
  92.             return self::BAD_REQUEST;
  93.         }
  94.  
  95.         $content = $params->toQueryString();
  96.  
  97.         $request = "POST " . self::SITE_VERIFY_PATH . " HTTP/1.1\r\n";
  98.         $request .= "Host: " . self::RECAPTCHA_HOST . "\r\n";
  99.         $request .= "Content-Type: application/x-www-form-urlencoded\r\n";
  100.         $request .= "Content-length: " . strlen($content) . "\r\n";
  101.         $request .= "Connection: close\r\n\r\n";
  102.         $request .= $content . "\r\n\r\n";
  103.  
  104.         $this->socket->fwrite($request);
  105.         $response = '';
  106.  
  107.         while (!$this->socket->feof()) {
  108.             $response .= $this->socket->fgets(4096);
  109.         }
  110.  
  111.         $this->socket->fclose();
  112.  
  113.         if (0 !== strpos($response, 'HTTP/1.1 200 OK')) {
  114.             return self::BAD_RESPONSE;
  115.         }
  116.  
  117.         $parts = preg_split("#\n\s*\n#Uis", $response);
  118.  
  119.         return $parts[1];
  120.     }
  121. }
  122.