[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/ -> recaptchalib.php (source)

   1  <?php
   2  
   3  /**
   4   * This is a PHP library that handles calling reCAPTCHA.
   5   *    - Documentation and latest version
   6   *          {@link http://code.google.com/apis/recaptcha/docs/php.html}
   7   *    - Get a reCAPTCHA API Key
   8   *          {@link https://www.google.com/recaptcha/admin/create}
   9   *    - Discussion group
  10   *          {@link http://groups.google.com/group/recaptcha}
  11   *
  12   * Copyright (c) 2007 reCAPTCHA -- {@link http://www.google.com/recaptcha}
  13   * AUTHORS:
  14   *   Mike Crawford
  15   *   Ben Maurer
  16   *
  17   * Permission is hereby granted, free of charge, to any person obtaining a copy
  18   * of this software and associated documentation files (the "Software"), to deal
  19   * in the Software without restriction, including without limitation the rights
  20   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  21   * copies of the Software, and to permit persons to whom the Software is
  22   * furnished to do so, subject to the following conditions:
  23   *
  24   * The above copyright notice and this permission notice shall be included in
  25   * all copies or substantial portions of the Software.
  26   *
  27   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  28   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  29   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  30   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  31   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  32   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  33   * THE SOFTWARE.
  34   *
  35   * @package moodlecore
  36   * @copyright (c) 2007 reCAPTCHA -- {@link http://www.google.com/recaptcha}
  37   */
  38  
  39  /**
  40   * The reCAPTCHA server URL's
  41   */
  42  define("RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api");
  43  define("RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api");
  44  define("RECAPTCHA_VERIFY_SERVER", "www.google.com");
  45  
  46  /**
  47   * Encodes the given data into a query string format
  48   * @param $data - array of string elements to be encoded
  49   * @return string - encoded request
  50   */
  51  function _recaptcha_qsencode ($data) {
  52          $req = "";
  53          foreach ( $data as $key => $value )
  54                  $req .= $key . '=' . urlencode( $value ) . '&';
  55  
  56          // Cut the last '&'
  57          $req=substr($req,0,strlen($req)-1);
  58          return $req;
  59  }
  60  
  61  
  62  
  63  /**
  64   * Submits an HTTP POST to a reCAPTCHA server
  65   *
  66   * @global object
  67   * @param string $host
  68   * @param string $path
  69   * @param array $data
  70   * @param int port
  71   * @return array response
  72   */
  73  function _recaptcha_http_post($host, $path, $data, $port = 80, $https=false) {
  74          global $CFG;
  75          $protocol = 'http';
  76          if ($https) {
  77              $protocol = 'https';
  78          }
  79  
  80          require_once $CFG->libdir . '/filelib.php';
  81  
  82          $req = _recaptcha_qsencode ($data);
  83  
  84          $headers = array();
  85          $headers['Host'] = $host;
  86          $headers['Content-Type'] = 'application/x-www-form-urlencoded';
  87          $headers['Content-Length'] = strlen($req);
  88          $headers['User-Agent'] = 'reCAPTCHA/PHP';
  89  
  90          $results = download_file_content("$protocol://" . $host . $path, $headers, $data, false, 300, 20, true);
  91  
  92          if ($results) {
  93              return array(1 => $results);
  94          } else {
  95              return false;
  96          }
  97  }
  98  
  99  
 100  
 101  /**
 102   * Gets the challenge HTML (javascript and non-javascript version).
 103   * This is called from the browser, and the resulting reCAPTCHA HTML widget
 104   * is embedded within the HTML form it was called from.
 105   *
 106   * @global object
 107   * @param string $pubkey A public key for reCAPTCHA
 108   * @param string $error The error given by reCAPTCHA (optional, default is null)
 109   * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
 110  
 111   * @return string - The HTML to be embedded in the user's form.
 112   */
 113  function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false) {
 114      global $CFG, $PAGE;
 115  
 116      $recaptchatype = optional_param('recaptcha', 'image', PARAM_TEXT);
 117  
 118      if ($pubkey == null || $pubkey == '') {
 119          die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
 120      }
 121  
 122      if ($use_ssl) {
 123          $server = RECAPTCHA_API_SECURE_SERVER;
 124      } else {
 125          $server = RECAPTCHA_API_SERVER;
 126      }
 127  
 128      $errorpart = "";
 129      if ($error) {
 130         $errorpart = "&amp;error=" . $error;
 131      }
 132  
 133      require_once $CFG->libdir . '/filelib.php';
 134      $html = download_file_content($server . '/noscript?k=' . $pubkey . $errorpart, null, null, false, 300, 20, true);
 135      preg_match('/image\?c\=([A-Za-z0-9\-\_]*)\"/', $html, $matches);
 136      $challenge_hash = $matches[1];
 137      $image_url = $server . '/image?c=' . $challenge_hash;
 138  
 139      $strincorrectpleasetryagain = get_string('incorrectpleasetryagain', 'auth');
 140      $strenterthewordsabove = get_string('enterthewordsabove', 'auth');
 141      $strenterthenumbersyouhear = get_string('enterthenumbersyouhear', 'auth');
 142      $strgetanothercaptcha = get_string('getanothercaptcha', 'auth');
 143      $strgetanaudiocaptcha = get_string('getanaudiocaptcha', 'auth');
 144      $strgetanimagecaptcha = get_string('getanimagecaptcha', 'auth');
 145  
 146      $return = html_writer::script('', $server . '/challenge?k=' . $pubkey . $errorpart);
 147      $return .= '<noscript>
 148          <div id="recaptcha_widget_noscript">
 149          <div id="recaptcha_image_noscript"><img src="' . $image_url . '" alt="reCAPTCHA"/></div>';
 150  
 151      if ($error == 'incorrect-captcha-sol') {
 152          $return .= '<div class="recaptcha_only_if_incorrect_sol" style="color:red">' . $strincorrectpleasetryagain . '</div>';
 153      }
 154  
 155      if ($recaptchatype == 'image') {
 156          $return .= '<span class="recaptcha_only_if_image">' . $strenterthewordsabove . '</span>';
 157      } elseif ($recaptchatype == 'audio') {
 158          $return .= '<span class="recaptcha_only_if_audio">' . $strenterthenumbersyouhear . '</span>'; 
 159      }
 160      
 161      $return .= '<input type="text" id="recaptcha_response_field_noscript" name="recaptcha_response_field" />';
 162      $return .= '<input type="hidden" id="recaptcha_challenge_field_noscript" name="recaptcha_challenge_field" value="' . $challenge_hash . '" />';
 163      $return .= '<div><a href="signup.php">' . $strgetanothercaptcha . '</a></div>';
 164      
 165      // Disabling audio recaptchas for now: not language-independent
 166      /*
 167      if ($recaptchatype == 'image') {
 168          $return .= '<div class="recaptcha_only_if_image"><a href="signup.php?recaptcha=audio">' . $strgetanaudiocaptcha . '</a></div>';
 169      } elseif ($recaptchatype == 'audio') {
 170          $return .= '<div class="recaptcha_only_if_audio"><a href="signup.php?recaptcha=image">' . $strgetanimagecaptcha . '</a></div>';
 171      }
 172      */
 173  
 174      $return .= '
 175          </div>
 176      </noscript>';
 177  
 178      return $return;
 179  }
 180  
 181  
 182  
 183  
 184  /**
 185   * A ReCaptchaResponse is returned from recaptcha_check_answer()
 186   *
 187   * @package moodlecore
 188   * @copyright (c) 2007 reCAPTCHA -- {@link http://www.google.com/recaptcha}
 189   */
 190  class ReCaptchaResponse {
 191          var $is_valid;
 192          var $error;
 193  }
 194  
 195  
 196  /**
 197    * Calls an HTTP POST function to verify if the user's guess was correct
 198    * @param string $privkey
 199    * @param string $remoteip
 200    * @param string $challenge
 201    * @param string $response
 202    * @return ReCaptchaResponse
 203    */
 204  function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $https=false)
 205  {
 206      if ($privkey == null || $privkey == '') {
 207          die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
 208      }
 209  
 210      if ($remoteip == null || $remoteip == '') {
 211          die ("For security reasons, you must pass the remote ip to reCAPTCHA");
 212      }
 213  
 214          //discard spam submissions
 215          if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
 216                  $recaptcha_response = new ReCaptchaResponse();
 217                  $recaptcha_response->is_valid = false;
 218                  $recaptcha_response->error = 'incorrect-captcha-sol';
 219                  return $recaptcha_response;
 220          }
 221  
 222          $response = _recaptcha_http_post(RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify",
 223                                           array (
 224                                                  'privatekey' => $privkey,
 225                                                  'remoteip' => $remoteip,
 226                                                  'challenge' => $challenge,
 227                                                  'response' => $response
 228                                                  ),
 229                                           $https        
 230                                          );
 231  
 232          $answers = explode ("\n", $response [1]);
 233          $recaptcha_response = new ReCaptchaResponse();
 234  
 235          if (trim ($answers [0]) == 'true') {
 236                  $recaptcha_response->is_valid = true;
 237          }
 238          else {
 239                  $recaptcha_response->is_valid = false;
 240                  $recaptcha_response->error = $answers [1];
 241          }
 242          return $recaptcha_response;
 243  
 244  }
 245  
 246  /**
 247   * gets a URL where the user can sign up for reCAPTCHA. If your application
 248   * has a configuration page where you enter a key, you should provide a link
 249   * using this function.
 250   * @param string $domain The domain where the page is hosted
 251   * @param string $appname The name of your application
 252   */
 253  function recaptcha_get_signup_url ($domain = null, $appname = null) {
 254      return "https://www.google.com/recaptcha/admin/create?" .  _recaptcha_qsencode (array ('domains' => $domain, 'app' => $appname));
 255  }
 256  
 257  function _recaptcha_aes_pad($val) {
 258      $block_size = 16;
 259      $numpad = $block_size - (strlen ($val) % $block_size);
 260      return str_pad($val, strlen ($val) + $numpad, chr($numpad));
 261  }
 262  
 263  /* Mailhide related code */
 264  
 265  function _recaptcha_aes_encrypt($val,$ky) {
 266      if (! function_exists ("mcrypt_encrypt")) {
 267          die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
 268      }
 269      $mode=MCRYPT_MODE_CBC;
 270      $enc=MCRYPT_RIJNDAEL_128;
 271      $val=_recaptcha_aes_pad($val);
 272      return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
 273  }
 274  
 275  
 276  function _recaptcha_mailhide_urlbase64 ($x) {
 277      return strtr(base64_encode ($x), '+/', '-_');
 278  }
 279  
 280  /* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
 281  function recaptcha_mailhide_url($pubkey, $privkey, $email) {
 282      if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) {
 283          die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
 284               "you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>");
 285      }
 286  
 287  
 288      $ky = pack('H*', $privkey);
 289      $cryptmail = _recaptcha_aes_encrypt ($email, $ky);
 290  
 291      return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail);
 292  }
 293  
 294  /**
 295   * gets the parts of the email to expose to the user.
 296   * eg, given johndoe@example,com return ["john", "example.com"].
 297   * the email is then displayed as john...@example.com
 298   */
 299  function _recaptcha_mailhide_email_parts ($email) {
 300      $arr = preg_split("/@/", $email );
 301  
 302      if (strlen ($arr[0]) <= 4) {
 303          $arr[0] = substr ($arr[0], 0, 1);
 304      } else if (strlen ($arr[0]) <= 6) {
 305          $arr[0] = substr ($arr[0], 0, 3);
 306      } else {
 307          $arr[0] = substr ($arr[0], 0, 4);
 308      }
 309      return $arr;
 310  }
 311  
 312  /**
 313   * Gets html to display an email address given a public an private key.
 314   * to get a key, go to:
 315   *
 316   * http://www.google.com/recaptcha/mailhide/apikey
 317   */
 318  function recaptcha_mailhide_html($pubkey, $privkey, $email) {
 319      $emailparts = _recaptcha_mailhide_email_parts ($email);
 320      $url = recaptcha_mailhide_url ($pubkey, $privkey, $email);
 321  
 322      return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
 323          "' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
 324  
 325  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1