[ Index ]

PHP Cross Reference of MyBB 1.8.40

title

Body

[close]

/inc/ -> class_captcha.php (source)

   1  <?php
   2  /**
   3   * MyBB 1.8
   4   * Copyright 2014 MyBB Group, All Rights Reserved
   5   *
   6   * Website: http://www.mybb.com
   7   * License: http://www.mybb.com/about/license
   8   *
   9   * This class is based from reCAPTCHA's PHP library, adapted for use in MyBB.
  10   *
  11   * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
  12   * AUTHORS:
  13   *   Mike Crawford
  14   *   Ben Maurer
  15   *
  16   * Permission is hereby granted, free of charge, to any person obtaining a copy
  17   * of this software and associated documentation files (the "Software"), to deal
  18   * in the Software without restriction, including without limitation the rights
  19   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  20   * copies of the Software, and to permit persons to whom the Software is
  21   * furnished to do so, subject to the following conditions:
  22   *
  23   * The above copyright notice and this permission notice shall be included in
  24   * all copies or substantial portions of the Software.
  25   *
  26   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  27   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  28   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  29   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  30   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  31   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  32   * THE SOFTWARE.
  33   *
  34   */
  35  
  36  class captcha
  37  {
  38      /**
  39       * Type of CAPTCHA.
  40       *
  41       * 1 = Default CAPTCHA
  42       * 4 = NoCATPCHA reCAPTCHA
  43       * 5 = reCAPTCHA invisible
  44       * 6 = hCaptcha
  45       * 7 = hCaptcha invisible
  46       * 8 = reCAPTCHA v3
  47       * 9 = CF Turnstile
  48       *
  49       * @var int
  50       */
  51      public $type = 0;
  52  
  53      /**
  54       * CAPTCHA constants declaration
  55       * 
  56       * @var int
  57       */
  58      const DEFAULT_CAPTCHA = 1;
  59      const NOCAPTCHA_RECAPTCHA = 4;
  60      const RECAPTCHA_INVISIBLE = 5;
  61      const HCAPTCHA = 6;
  62      const HCAPTCHA_INVISIBLE = 7;
  63      const RECAPTCHA_V3 = 8;
  64      const CFTURNSTILE = 9;
  65  
  66      /**
  67       * The template to display the CAPTCHA in
  68       *
  69       * @var string
  70       */
  71       public $captcha_template = '';
  72  
  73      /**
  74       * CAPTCHA Server URL
  75       *
  76       * @var string
  77       */
  78      public $server = '';
  79  
  80      /**
  81       * CAPTCHA Verify Server
  82       *
  83       * @var string
  84       */
  85      public $verify_server = '';
  86  
  87      /**
  88       * HTML of the built CAPTCHA
  89       *
  90       * @var string
  91       */
  92      public $html = '';
  93  
  94      /**
  95       * The errors that occurred when handling data.
  96       *
  97       * @var array
  98       */
  99      public $errors = array();
 100  
 101      /**
 102       * @param bool   $build
 103       * @param string $template
 104       */
 105  	function __construct($build = false, $template = "")
 106      {
 107          global $mybb, $plugins;
 108  
 109          $this->type = (int)$mybb->settings['captchaimage'];
 110  
 111          $args = array(
 112              'this' => &$this,
 113              'build' => &$build,
 114              'template' => &$template,
 115          );
 116  
 117          $plugins->run_hooks('captcha_build_start', $args);
 118  
 119          // Prepare the build template
 120          if($template)
 121          {
 122              $this->captcha_template = $template;
 123  
 124              if($this->type == captcha::NOCAPTCHA_RECAPTCHA)
 125              {
 126                  $this->captcha_template .= "_nocaptcha";
 127              }
 128              elseif($this->type == captcha::RECAPTCHA_INVISIBLE)
 129              {
 130                  $this->captcha_template .= "_recaptcha_invisible";
 131              }
 132              elseif($this->type == captcha::HCAPTCHA)
 133              {
 134                  $this->captcha_template .= "_hcaptcha";
 135              }
 136              elseif($this->type == captcha::HCAPTCHA_INVISIBLE)
 137              {
 138                  $this->captcha_template .= "_hcaptcha_invisible";
 139              }
 140              elseif($this->type == captcha::RECAPTCHA_V3)
 141              {
 142                  $this->captcha_template .= "_recaptcha_invisible";
 143              }
 144              elseif($this->type == captcha::CFTURNSTILE)
 145              {
 146                  $this->captcha_template .= "_cfturnstile";
 147              }
 148          }
 149  
 150          // Work on which CAPTCHA we've got installed
 151          if(in_array($this->type, array(captcha::NOCAPTCHA_RECAPTCHA, captcha::RECAPTCHA_INVISIBLE, captcha::RECAPTCHA_V3)) && $mybb->settings['recaptchapublickey'] && $mybb->settings['recaptchaprivatekey'])
 152          {
 153              // We want to use noCAPTCHA or reCAPTCHA invisible, set the server options
 154              $this->server = "//www.google.com/recaptcha/api.js";
 155              $this->verify_server = "https://www.google.com/recaptcha/api/siteverify";
 156  
 157              if($build == true)
 158              {
 159                  $this->build_recaptcha();
 160              }
 161          }
 162          elseif(in_array($this->type, array(captcha::HCAPTCHA, captcha::HCAPTCHA_INVISIBLE)) && $mybb->settings['hcaptchapublickey'] && $mybb->settings['hcaptchaprivatekey'])
 163          {
 164              // We want to use hCaptcha or hCaptcha invisible, set the server options
 165              $this->server = "//js.hcaptcha.com/1/api.js";
 166              $this->verify_server = "https://hcaptcha.com/siteverify";
 167  
 168              if($build == true)
 169              {
 170                  $this->build_hcaptcha();
 171              }
 172          }
 173          elseif($this->type == captcha::CFTURNSTILE && $mybb->settings['cfturnstilepublickey'] && $mybb->settings['cfturnstileprivatekey'])
 174          {
 175              // JS and backend server validation
 176              $this->server = "//challenges.cloudflare.com/turnstile/v0/api.js";
 177              $this->verify_server = "https://challenges.cloudflare.com/turnstile/v0/siteverify";
 178  
 179              if($build == true)
 180              {
 181                  $this->build_cfturnstile();
 182              }
 183          }
 184          elseif($this->type == captcha::DEFAULT_CAPTCHA)
 185          {
 186              if(!function_exists("imagecreatefrompng"))
 187              {
 188                  // We want to use the default CAPTCHA, but it's not installed
 189                  return;
 190              }
 191              elseif($build == true)
 192              {
 193                  $this->build_captcha();
 194              }
 195          }
 196  
 197          $plugins->run_hooks('captcha_build_end', $args);
 198      }
 199  
 200      /**
 201       * @param bool $return Not used
 202       */
 203  	function build_captcha($return = false)
 204      {
 205          global $db, $lang, $templates, $theme, $mybb;
 206  
 207          // This will build a MyBB CAPTCHA
 208          $randomstr = random_str(5);
 209          $imagehash = md5(random_str(12));
 210  
 211          $insert_array = array(
 212              "imagehash" => $imagehash,
 213              "imagestring" => $randomstr,
 214              "dateline" => TIME_NOW
 215          );
 216  
 217          $db->insert_query("captcha", $insert_array);
 218          eval("\$this->html = \"".$templates->get($this->captcha_template)."\";");
 219          //eval("\$this->html = \"".$templates->get("member_register_regimage")."\";");
 220      }
 221  
 222  	function build_recaptcha()
 223      {
 224          global $lang, $mybb, $templates;
 225  
 226          // This will build a reCAPTCHA
 227          $server = $this->server;
 228          $public_key = $mybb->settings['recaptchapublickey'];
 229  
 230          eval("\$this->html = \"".$templates->get($this->captcha_template, 1, 0)."\";");
 231          //eval("\$this->html = \"".$templates->get("member_register_regimage_recaptcha")."\";");
 232      }
 233  
 234  	function build_hcaptcha()
 235      {
 236          global $lang, $mybb, $templates, $theme;
 237  
 238          // This will build a hCaptcha
 239          $server = $this->server;
 240          $public_key = $mybb->settings['hcaptchapublickey'];
 241          $captcha_theme = $mybb->settings['hcaptchatheme'];
 242          $captcha_size = $mybb->settings['hcaptchasize'];
 243          
 244          eval("\$this->html = \"".$templates->get($this->captcha_template, 1, 0)."\";");
 245      }
 246  
 247  	function build_cfturnstile()
 248      {
 249          global $lang, $mybb, $templates, $theme;
 250  
 251          // This will build a hCaptcha
 252          $server = $this->server;
 253          $public_key = $mybb->settings['cfturnstilepublickey'];
 254          $captcha_theme = $mybb->settings['cfturnstiletheme'];
 255          $captcha_size = $mybb->settings['cfturnstilesize'];
 256  
 257          eval("\$this->html = \"".$templates->get($this->captcha_template, 1, 0)."\";");
 258      }
 259  
 260      /**
 261       * @return string
 262       */
 263  	function build_hidden_captcha()
 264      {
 265          global $db, $mybb, $templates;
 266  
 267          $field = array();
 268  
 269          if($this->type == captcha::DEFAULT_CAPTCHA)
 270          {
 271              // Names
 272              $hash = "imagehash";
 273              $string = "imagestring";
 274  
 275              // Values
 276              $field['hash'] = $db->escape_string($mybb->get_input('imagehash'));
 277              $field['string'] = $db->escape_string($mybb->get_input('imagestring'));
 278          }
 279          elseif($this->type == 3)
 280          {
 281              // Are You a Human can't be built as a hidden captcha
 282              return '';
 283          }
 284  
 285          eval("\$this->html = \"".$templates->get("post_captcha_hidden")."\";");
 286          return $this->html;
 287      }
 288  
 289      /**
 290       * @return bool
 291       */
 292  	function validate_captcha()
 293      {
 294          global $db, $lang, $mybb, $session, $plugins;
 295  
 296          $plugins->run_hooks('captcha_validate_start', $this);
 297  
 298          if($this->type == captcha::DEFAULT_CAPTCHA)
 299          {
 300              // We have a normal CAPTCHA to handle
 301              $imagehash = $db->escape_string($mybb->get_input('imagehash'));
 302              $imagestring = $db->escape_string(my_strtolower($mybb->get_input('imagestring')));
 303  
 304              switch($db->type)
 305              {
 306                  case 'mysql':
 307                  case 'mysqli':
 308                      $field = 'imagestring';
 309                      break;
 310                  default:
 311                      $field = 'LOWER(imagestring)';
 312                      break;
 313              }
 314  
 315              $query = $db->simple_select("captcha", "*", "imagehash = '{$imagehash}' AND {$field} = '{$imagestring}'");
 316              $imgcheck = $db->fetch_array($query);
 317  
 318              if(!$imgcheck)
 319              {
 320                  $this->set_error($lang->invalid_captcha_verify);
 321                  $db->delete_query("captcha", "imagehash = '{$imagehash}'");
 322              }
 323          }
 324          elseif(in_array($this->type, array(captcha::NOCAPTCHA_RECAPTCHA, captcha::RECAPTCHA_INVISIBLE)))
 325          {
 326              $response = $mybb->get_input('g-recaptcha-response');
 327              if(!$response || strlen($response) == 0)
 328              {
 329                  $this->set_error($lang->invalid_nocaptcha);
 330              }
 331              else
 332              {
 333                  // We have a noCAPTCHA or reCAPTCHA invisible to handle
 334                  // Contact Google and see if our reCAPTCHA was successful
 335                  $response = fetch_remote_file($this->verify_server, array(
 336                      'secret' => $mybb->settings['recaptchaprivatekey'],
 337                      'remoteip' => $session->ipaddress,
 338                      'response' => $response
 339                  ));
 340  
 341                  if($response == false)
 342                  {
 343                      $this->set_error($lang->invalid_nocaptcha_transmit);
 344                  }
 345                  else
 346                  {
 347                      $answer = json_decode($response, true);
 348  
 349                      if($answer['success'] != 'true')
 350                      {
 351                          // We got it wrong! Oh no...
 352                          $this->set_error($lang->invalid_nocaptcha);
 353                      }
 354                  }
 355              }
 356          }
 357          elseif($this->type == captcha::RECAPTCHA_V3)
 358          {
 359              $response = $mybb->get_input('g-recaptcha-response');
 360              if(!$response || strlen($response) == 0)
 361              {
 362                  $this->set_error($lang->invalid_nocaptcha);
 363              }
 364              else
 365              {
 366                  // We have a reCAPTCHA invisible to handle
 367                  // Contact Google and see if our reCAPTCHA was successful
 368                  $response = fetch_remote_file($this->verify_server, array(
 369                      'secret' => $mybb->settings['recaptchaprivatekey'],
 370                      'score' => $mybb->settings['recaptchascore'],
 371                      'remoteip' => $session->ipaddress,
 372                      'response' => $response
 373                  ));
 374  
 375                  if($response === false)
 376                  {
 377                      $this->set_error($lang->invalid_nocaptcha_transmit);
 378                  }
 379                  else
 380                  {
 381                      $answer = json_decode($response, true);
 382  
 383                      if($answer['success'] != 'true' || $answer['score'] < $mybb->settings['recaptchascore'])
 384                      {
 385                          // We got it wrong! Oh no...
 386                          $this->set_error($lang->invalid_nocaptcha);
 387                      }
 388                  }
 389              }
 390          }
 391          elseif(in_array($this->type, array(captcha::HCAPTCHA, captcha::HCAPTCHA_INVISIBLE)))
 392          {
 393              $response = $mybb->get_input('h-captcha-response');
 394              if(!$response || strlen($response) == 0)
 395              {
 396                  $this->set_error($lang->invalid_hcaptcha);
 397              }
 398              else
 399              {
 400                  // We have an hCaptcha or hCaptcha invisible to handle
 401                  // Contact hCaptcha and see if our hCaptcha was successful
 402                  $response = fetch_remote_file($this->verify_server, array(
 403                      'secret' => $mybb->settings['hcaptchaprivatekey'],
 404                      'remoteip' => $session->ipaddress,
 405                      'response' => $response
 406                  ));
 407  
 408                  if($response == false)
 409                  {
 410                      $this->set_error($lang->invalid_hcaptcha_transmit);
 411                  }
 412                  else
 413                  {
 414                      $answer = json_decode($response, true);
 415                      if($answer['success'] != 'true')
 416                      {
 417                          // We got it wrong! Oh no...
 418                          $this->set_error($lang->invalid_hcaptcha);
 419                      }
 420                  }
 421              }
 422          }
 423          elseif($this->type === self::CFTURNSTILE)
 424          {
 425              $response = $mybb->get_input('cf-turnstile-response');
 426              if(!$response || strlen($response) == 0)
 427              {
 428                  $this->set_error($lang->invalid_cfturnstile);
 429              }
 430              else
 431              {
 432                  // Contact CF-Turnstile and see if our CF-Turnstile request was successful
 433                  $response = fetch_remote_file($this->verify_server, array(
 434                      'secret' => $mybb->settings['cfturnstileprivatekey'],
 435                      'remoteip' => $session->ipaddress,
 436                      'response' => $response
 437                  ));
 438  
 439                  if($response == false)
 440                  {
 441                      $this->set_error($lang->invalid_cfturnstile_transmit);
 442                  }
 443                  else
 444                  {
 445                      $answer = json_decode($response, true);
 446                      if($answer['success'] != 'true')
 447                      {
 448                          // We got it wrong! Oh no...
 449                          $this->set_error($lang->invalid_cfturnstile);
 450                      }
 451                  }
 452              }
 453          }
 454  
 455          $plugins->run_hooks('captcha_validate_end', $this);
 456  
 457          if(count($this->errors) > 0)
 458          {
 459              return false;
 460          }
 461          else
 462          {
 463              return true;
 464          }
 465      }
 466  
 467  	function invalidate_captcha()
 468      {
 469          global $db, $mybb, $plugins;
 470  
 471          if($this->type == captcha::DEFAULT_CAPTCHA)
 472          {
 473              // We have a normal CAPTCHA to handle
 474              $imagehash = $db->escape_string($mybb->get_input('imagehash'));
 475              if($imagehash)
 476              {
 477                  $db->delete_query("captcha", "imagehash = '{$imagehash}'");
 478              }
 479          }
 480          // Not necessary for reCAPTCHA or Are You a Human
 481  
 482          $plugins->run_hooks('captcha_invalidate_end', $this);
 483      }
 484  
 485      /**
 486       * Add an error to the error array.
 487       *
 488       * @param string $error
 489       * @param string $data
 490       */
 491  	function set_error($error, $data='')
 492      {
 493          $this->errors[$error] = array(
 494              "error_code" => $error,
 495              "data" => $data
 496          );
 497      }
 498  
 499      /**
 500       * Returns the error(s) that occurred when handling data
 501       * in a format that MyBB can handle.
 502       *
 503       * @return array An array of errors in a MyBB format.
 504       */
 505  	function get_errors()
 506      {
 507          global $lang;
 508  
 509          $errors = array();
 510          foreach($this->errors as $error)
 511          {
 512              $lang_string = $error['error_code'];
 513  
 514              if(!$lang_string)
 515              {
 516                  if($lang->invalid_captcha_verify)
 517                  {
 518                      $lang_string = 'invalid_captcha_verify';
 519                  }
 520                  else
 521                  {
 522                      $lang_string = 'unknown_error';
 523                  }
 524              }
 525  
 526              if(!isset($lang->$lang_string))
 527              {
 528                  $errors[] = $error['error_code'];
 529                  continue;
 530              }
 531  
 532              if(!empty($error['data']) && !is_array($error['data']))
 533              {
 534                  $error['data'] = array($error['data']);
 535              }
 536  
 537              if(is_array($error['data']))
 538              {
 539                  array_unshift($error['data'], $lang->$lang_string);
 540                  $errors[] = call_user_func_array(array($lang, "sprintf"), $error['data']);
 541              }
 542              else
 543              {
 544                  $errors[] = $lang->$lang_string;
 545              }
 546          }
 547  
 548          return $errors;
 549      }
 550  
 551      /**
 552       * @param array $data
 553       *
 554       * @return string
 555       */
 556  	private function _qsencode($data)
 557      {
 558          $req = '';
 559          foreach($data as $key => $value)
 560          {
 561              $req .= $key.'='.urlencode(stripslashes($value)).'&';
 562          }
 563  
 564          $req = substr($req, 0, (strlen($req) - 1));
 565  
 566          return $req;
 567      }
 568  }


2005 - 2021 © MyBB.de | Alle Rechte vorbehalten! | Sponsor: netcup Cross-referenced by PHPXref