Source for file recaptcha.php

Documentation is available at recaptcha.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Plugin
  4.  * @subpackage  Captcha
  5.  *
  6.  * @copyright   Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7.  * @license     GNU General Public License version 2 or later; see LICENSE.txt
  8.  */
  9.  
  10. defined('_JEXEC'or die;
  11.  
  12. /**
  13.  * Recaptcha Plugin.
  14.  * Based on the official recaptcha library( https://developers.google.com/recaptcha/docs/php )
  15.  *
  16.  * @package     Joomla.Plugin
  17.  * @subpackage  Captcha
  18.  * @since       2.5
  19.  */
  20. class PlgCaptchaRecaptcha extends JPlugin
  21. {
  22.     const RECAPTCHA_API_SERVER = "http://api.recaptcha.net";
  23.     const RECAPTCHA_API_SECURE_SERVER = "https://www.google.com/recaptcha/api";
  24.     const RECAPTCHA_VERIFY_SERVER = "api-verify.recaptcha.net";
  25.  
  26.     /**
  27.      * Load the language file on instantiation.
  28.      *
  29.      * @var    boolean 
  30.      * @since  3.1
  31.      */
  32.     protected $autoloadLanguage = true;
  33.  
  34.     /**
  35.      * Initialise the captcha
  36.      *
  37.      * @param   string  $id  The id of the field.
  38.      *
  39.      * @return  Boolean    True on success, false otherwise
  40.      *
  41.      * @since  2.5
  42.      */
  43.     public function onInit($id)
  44.     {
  45.         $document JFactory::getDocument();
  46.         $app      JFactory::getApplication();
  47.  
  48.         $lang   $this->_getLanguage();
  49.         $pubkey $this->params->get('public_key''');
  50.         $theme  $this->params->get('theme''clean');
  51.  
  52.         if ($pubkey == null || $pubkey == '')
  53.         {
  54.             throw new Exception(JText::_('PLG_RECAPTCHA_ERROR_NO_PUBLIC_KEY'));
  55.         }
  56.  
  57.         $server self::RECAPTCHA_API_SERVER;
  58.  
  59.         if ($app->isSSLConnection())
  60.         {
  61.             $server self::RECAPTCHA_API_SECURE_SERVER;
  62.         }
  63.  
  64.         JHtml::_('script'$server '/js/recaptcha_ajax.js');
  65.         $document->addScriptDeclaration('window.addEvent(\'domready\', function()
  66.         {
  67.             Recaptcha.create("' $pubkey '", "dynamic_recaptcha_1", {theme: "' $theme '",' $lang 'tabindex: 0});});'
  68.         );
  69.  
  70.         return true;
  71.     }
  72.  
  73.     /**
  74.      * Gets the challenge HTML
  75.      *
  76.      * @param   string  $name   The name of the field.
  77.      * @param   string  $id     The id of the field.
  78.      * @param   string  $class  The class of the field.
  79.      *
  80.      * @return  string  The HTML to be embedded in the form.
  81.      *
  82.      * @since  2.5
  83.      */
  84.     public function onDisplay($name$id$class)
  85.     {
  86.         return '<div id="dynamic_recaptcha_1"></div>';
  87.     }
  88.  
  89.     /**
  90.       * Calls an HTTP POST function to verify if the user's guess was correct
  91.       *
  92.       * @return  True if the answer is correct, false otherwise
  93.       *
  94.       * @since  2.5
  95.       */
  96.     public function onCheckAnswer($code)
  97.     {
  98.         $input      JFactory::getApplication()->input;
  99.         $privatekey $this->params->get('private_key');
  100.         $remoteip   $input->server->get('REMOTE_ADDR''''string');
  101.         $challenge  $input->get('recaptcha_challenge_field''''string');
  102.         $response   $input->get('recaptcha_response_field''''string');
  103.  
  104.         // Check for Private Key
  105.         if (empty($privatekey))
  106.         {
  107.             $this->_subject->setError(JText::_('PLG_RECAPTCHA_ERROR_NO_PRIVATE_KEY'));
  108.  
  109.             return false;
  110.         }
  111.  
  112.         // Check for IP
  113.         if (empty($remoteip))
  114.         {
  115.             $this->_subject->setError(JText::_('PLG_RECAPTCHA_ERROR_NO_IP'));
  116.  
  117.             return false;
  118.         }
  119.  
  120.         // Discard spam submissions
  121.         if ($challenge == null || strlen($challenge== || $response == null || strlen($response== 0)
  122.         {
  123.             $this->_subject->setError(JText::_('PLG_RECAPTCHA_ERROR_EMPTY_SOLUTION'));
  124.  
  125.             return false;
  126.         }
  127.  
  128.         $response $this->_recaptcha_http_post(
  129.             self::RECAPTCHA_VERIFY_SERVER"/verify",
  130.             array(
  131.                 'privatekey' => $privatekey,
  132.                 'remoteip'   => $remoteip,
  133.                 'challenge'  => $challenge,
  134.                 'response'   => $response
  135.             )
  136.     );
  137.  
  138.         $answers explode("\n"$response[1]);
  139.  
  140.         if (trim($answers[0]== 'true')
  141.             {
  142.                 return true;
  143.         }
  144.         else
  145.         {
  146.             // @todo use exceptions here
  147.             $this->_subject->setError(JText::_('PLG_RECAPTCHA_ERROR_' strtoupper(str_replace('-''_'$answers[1]))));
  148.  
  149.             return false;
  150.         }
  151.     }
  152.  
  153.     /**
  154.      * Encodes the given data into a query string format.
  155.      *
  156.      * @param   array  $data  Array of string elements to be encoded
  157.      *
  158.      * @return  string  Encoded request
  159.      *
  160.      * @since  2.5
  161.      */
  162.     private function _recaptcha_qsencode($data)
  163.     {
  164.         $req "";
  165.  
  166.         foreach ($data as $key => $value)
  167.         {
  168.             $req .= $key '=' urlencode(stripslashes($value)) '&';
  169.         }
  170.  
  171.         // Cut the last '&'
  172.         $req rtrim($req'&');
  173.  
  174.         return $req;
  175.     }
  176.  
  177.     /**
  178.      * Submits an HTTP POST to a reCAPTCHA server.
  179.      *
  180.      * @param   string  $host 
  181.      * @param   string  $path 
  182.      * @param   array   $data 
  183.      * @param   int     $port 
  184.      *
  185.      * @return  array   Response
  186.      *
  187.      * @since  2.5
  188.      */
  189.     private function _recaptcha_http_post($host$path$data$port 80)
  190.     {
  191.         $req $this->_recaptcha_qsencode($data);
  192.  
  193.         $http_request  "POST $path HTTP/1.0\r\n";
  194.         $http_request .= "Host: $host\r\n";
  195.         $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
  196.         $http_request .= "Content-Length: " strlen($req"\r\n";
  197.         $http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
  198.         $http_request .= "\r\n";
  199.         $http_request .= $req;
  200.  
  201.         $response '';
  202.  
  203.         if (($fs @fsockopen($host$port$errno$errstr10)) == false )
  204.         {
  205.             die('Could not open socket');
  206.         }
  207.  
  208.         fwrite($fs$http_request);
  209.  
  210.         while (!feof($fs))
  211.         {
  212.             // One TCP-IP packet
  213.             $response .= fgets($fs1160);
  214.         }
  215.  
  216.         fclose($fs);
  217.         $response explode("\r\n\r\n"$response2);
  218.  
  219.         return $response;
  220.     }
  221.  
  222.     /**
  223.      * Get the language tag or a custom translation
  224.      *
  225.      * @return  string 
  226.      *
  227.      * @since  2.5
  228.      */
  229.     private function _getLanguage()
  230.     {
  231.         $language JFactory::getLanguage();
  232.  
  233.         $tag explode('-'$language->getTag());
  234.         $tag $tag[0];
  235.         $available array('en''pt''fr''de''nl''ru''es''tr');
  236.  
  237.         if (in_array($tag$available))
  238.         {
  239.             return "lang : '" $tag "',";
  240.         }
  241.  
  242.         // If the default language is not available, let's search for a custom translation
  243.         if ($language->hasKey('PLG_RECAPTCHA_CUSTOM_LANG'))
  244.         {
  245.             $custom['custom_translations : {';
  246.             $custom["\t" 'instructions_visual : "' JText::_('PLG_RECAPTCHA_INSTRUCTIONS_VISUAL''",';
  247.             $custom["\t" 'instructions_audio : "' JText::_('PLG_RECAPTCHA_INSTRUCTIONS_AUDIO''",';
  248.             $custom["\t" 'play_again : "' JText::_('PLG_RECAPTCHA_PLAY_AGAIN''",';
  249.             $custom["\t" 'cant_hear_this : "' JText::_('PLG_RECAPTCHA_CANT_HEAR_THIS''",';
  250.             $custom["\t" 'visual_challenge : "' JText::_('PLG_RECAPTCHA_VISUAL_CHALLENGE''",';
  251.             $custom["\t" 'audio_challenge : "' JText::_('PLG_RECAPTCHA_AUDIO_CHALLENGE''",';
  252.             $custom["\t" 'refresh_btn : "' JText::_('PLG_RECAPTCHA_REFRESH_BTN''",';
  253.             $custom["\t" 'help_btn : "' JText::_('PLG_RECAPTCHA_HELP_BTN''",';
  254.             $custom["\t" 'incorrect_try_again : "' JText::_('PLG_RECAPTCHA_INCORRECT_TRY_AGAIN''",';
  255.             $custom['},';
  256.             $custom["lang : '" $tag "',";
  257.  
  258.             return implode("\n"$custom);
  259.         }
  260.  
  261.         // If nothing helps fall back to english
  262.         return '';
  263.     }
  264. }

Documentation generated on Tue, 19 Nov 2013 15:11:37 +0100 by phpDocumentor 1.4.3