PageRenderTime 40ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/Upload/inc/class_captcha.php

https://gitlab.com/Conors99/ppm-1.8
PHP | 467 lines | 285 code | 61 blank | 121 comment | 66 complexity | f7806d47631d384dab1544761f262143 MD5 | raw file
  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. class captcha
  36. {
  37. /**
  38. * Type of CAPTCHA.
  39. *
  40. * 1 = Default CAPTCHA
  41. * 2 = reCAPTCHA
  42. * 4 = NoCATPCHA reCAPTCHA
  43. *
  44. * @var int
  45. */
  46. public $type = 0;
  47. /**
  48. * The template to display the CAPTCHA in
  49. *
  50. * @var string
  51. */
  52. public $captcha_template = '';
  53. /**
  54. * CAPTCHA Server URL
  55. *
  56. * @var string
  57. */
  58. public $server = '';
  59. /**
  60. * CAPTCHA Verify Server
  61. *
  62. * @var string
  63. */
  64. public $verify_server = '';
  65. /**
  66. * HTML of the built CAPTCHA
  67. *
  68. * @var string
  69. */
  70. public $html = '';
  71. /**
  72. * The errors that occurred when handling data.
  73. *
  74. * @var array
  75. */
  76. public $errors = array();
  77. /**
  78. * @param bool $build
  79. * @param string $template
  80. */
  81. function __construct($build = false, $template = "")
  82. {
  83. global $mybb, $plugins;
  84. $this->type = $mybb->settings['captchaimage'];
  85. $args = array(
  86. 'this' => &$this,
  87. 'build' => &$build,
  88. 'template' => &$template,
  89. );
  90. $plugins->run_hooks('captcha_build_start', $args);
  91. // Prepare the build template
  92. if($template)
  93. {
  94. $this->captcha_template = $template;
  95. if($this->type == 2)
  96. {
  97. $this->captcha_template .= "_recaptcha";
  98. }
  99. else if($this->type == 4){
  100. $this->captcha_template .= "_nocaptcha";
  101. }
  102. }
  103. // Work on which CAPTCHA we've got installed
  104. if($this->type == 2 && $mybb->settings['captchapublickey'] && $mybb->settings['captchaprivatekey'])
  105. {
  106. // We want to use reCAPTCHA, set the server options
  107. $this->server = "//www.google.com/recaptcha/api";
  108. $this->verify_server = "www.google.com";
  109. if($build == true)
  110. {
  111. $this->build_recaptcha();
  112. }
  113. }
  114. else if($this->type == 4 && $mybb->settings['captchapublickey'] && $mybb->settings['captchaprivatekey'])
  115. {
  116. // We want to use reCAPTCHA, set the server options
  117. $this->server = "//www.google.com/recaptcha/api.js";
  118. $this->verify_server = "https://www.google.com/recaptcha/api/siteverify";
  119. if($build == true)
  120. {
  121. $this->build_recaptcha();
  122. }
  123. }
  124. else if($this->type == 1)
  125. {
  126. if(!function_exists("imagecreatefrompng"))
  127. {
  128. // We want to use the default CAPTCHA, but it's not installed
  129. return;
  130. }
  131. else if($build == true)
  132. {
  133. $this->build_captcha();
  134. }
  135. }
  136. $plugins->run_hooks('captcha_build_end', $args);
  137. }
  138. /**
  139. * @param bool $return Not used
  140. */
  141. function build_captcha($return = false)
  142. {
  143. global $db, $lang, $templates, $theme, $mybb;
  144. // This will build a MyBB CAPTCHA
  145. $randomstr = random_str(5);
  146. $imagehash = md5(random_str(12));
  147. $insert_array = array(
  148. "imagehash" => $imagehash,
  149. "imagestring" => $randomstr,
  150. "dateline" => TIME_NOW
  151. );
  152. $db->insert_query("captcha", $insert_array);
  153. eval("\$this->html = \"".$templates->get($this->captcha_template)."\";");
  154. //eval("\$this->html = \"".$templates->get("member_register_regimage")."\";");
  155. }
  156. function build_recaptcha()
  157. {
  158. global $lang, $mybb, $templates;
  159. // This will build a reCAPTCHA
  160. $server = $this->server;
  161. $public_key = $mybb->settings['captchapublickey'];
  162. eval("\$this->html = \"".$templates->get($this->captcha_template, 1, 0)."\";");
  163. //eval("\$this->html = \"".$templates->get("member_register_regimage_recaptcha")."\";");
  164. }
  165. /**
  166. * @return string
  167. */
  168. function build_hidden_captcha()
  169. {
  170. global $db, $mybb, $templates;
  171. $field = array();
  172. if($this->type == 1)
  173. {
  174. // Names
  175. $hash = "imagehash";
  176. $string = "imagestring";
  177. // Values
  178. $field['hash'] = $db->escape_string($mybb->input['imagehash']);
  179. $field['string'] = $db->escape_string($mybb->input['imagestring']);
  180. }
  181. else if($this->type == 2)
  182. {
  183. // Names
  184. $hash = "recaptcha_challenge_field";
  185. $string = "recaptcha_response_field";
  186. // Values
  187. $field['hash'] = $mybb->input['recaptcha_challenge_field'];
  188. $field['string'] = $mybb->input['recaptcha_response_field'];
  189. }
  190. else if($this->type == 3)
  191. {
  192. // Are You a Human can't be built as a hidden captcha
  193. return '';
  194. }
  195. eval("\$this->html = \"".$templates->get("post_captcha_hidden")."\";");
  196. return $this->html;
  197. }
  198. /**
  199. * @return bool
  200. */
  201. function validate_captcha()
  202. {
  203. global $db, $lang, $mybb, $session, $plugins;
  204. $plugins->run_hooks('captcha_validate_start', $this);
  205. if($this->type == 1)
  206. {
  207. // We have a normal CAPTCHA to handle
  208. $imagehash = $db->escape_string($mybb->input['imagehash']);
  209. $imagestring = $db->escape_string(my_strtolower($mybb->input['imagestring']));
  210. switch($db->type)
  211. {
  212. case 'mysql':
  213. case 'mysqli':
  214. $field = 'imagestring';
  215. break;
  216. default:
  217. $field = 'LOWER(imagestring)';
  218. break;
  219. }
  220. $query = $db->simple_select("captcha", "*", "imagehash = '{$imagehash}' AND {$field} = '{$imagestring}'");
  221. $imgcheck = $db->fetch_array($query);
  222. if(!$imgcheck)
  223. {
  224. $this->set_error($lang->invalid_captcha_verify);
  225. $db->delete_query("captcha", "imagehash = '{$imagehash}'");
  226. }
  227. }
  228. elseif($this->type == 2)
  229. {
  230. $challenge = $mybb->input['recaptcha_challenge_field'];
  231. $response = $mybb->input['recaptcha_response_field'];
  232. if(!$challenge || strlen($challenge) == 0 || !$response || strlen($response) == 0)
  233. {
  234. $this->set_error($lang->invalid_captcha);
  235. }
  236. else
  237. {
  238. // We have a reCAPTCHA to handle
  239. $data = $this->_qsencode(array(
  240. 'privatekey' => $mybb->settings['captchaprivatekey'],
  241. 'remoteip' => $session->ipaddress,
  242. 'challenge' => $challenge,
  243. 'response' => $response
  244. ));
  245. // Contact Google and see if our reCAPTCHA was successful
  246. $http_request = "POST /recaptcha/api/verify HTTP/1.0\r\n";
  247. $http_request .= "Host: $this->verify_server\r\n";
  248. $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
  249. $http_request .= "Content-Length: ".strlen($data)."\r\n";
  250. $http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
  251. $http_request .= "\r\n";
  252. $http_request .= $data;
  253. $fs = @fsockopen($this->verify_server, 80, $errno, $errstr, 10);
  254. if($fs == false)
  255. {
  256. $this->set_error($lang->invalid_captcha_transmit);
  257. }
  258. else
  259. {
  260. // We connected, but is it correct?
  261. fwrite($fs, $http_request);
  262. while(!feof($fs))
  263. {
  264. $response .= fgets($fs, 1160);
  265. }
  266. fclose($fs);
  267. $response = explode("\r\n\r\n", $response, 2);
  268. $answer = explode("\n", $response[1]);
  269. if(trim($answer[0]) != 'true')
  270. {
  271. // We got it wrong! Oh no...
  272. $this->set_error($lang->invalid_captcha_verify);
  273. }
  274. }
  275. }
  276. }
  277. elseif($this->type == 4)
  278. {
  279. $response = $mybb->input['g-recaptcha-response'];
  280. if(!$response || strlen($response) == 0)
  281. {
  282. $this->set_error($lang->invalid_nocaptcha);
  283. }
  284. else
  285. {
  286. // We have a noCAPTCHA to handle
  287. // Contact Google and see if our reCAPTCHA was successful
  288. $response = fetch_remote_file($this->verify_server, array(
  289. 'secret' => $mybb->settings['captchaprivatekey'],
  290. 'remoteip' => $session->ipaddress,
  291. 'response' => $response
  292. ));
  293. if($response == false)
  294. {
  295. $this->set_error($lang->invalid_nocaptcha_transmit);
  296. }
  297. else
  298. {
  299. $answer = json_decode($response, true);
  300. if($answer['success'] != 'true')
  301. {
  302. // We got it wrong! Oh no...
  303. $this->set_error($lang->invalid_nocaptcha);
  304. }
  305. }
  306. }
  307. }
  308. $plugins->run_hooks('captcha_validate_end', $this);
  309. if(count($this->errors) > 0)
  310. {
  311. return false;
  312. }
  313. else
  314. {
  315. return true;
  316. }
  317. }
  318. function invalidate_captcha()
  319. {
  320. global $db, $mybb, $plugins;
  321. if($this->type == 1)
  322. {
  323. // We have a normal CAPTCHA to handle
  324. $imagehash = $db->escape_string($mybb->input['imagehash']);
  325. if($imagehash)
  326. {
  327. $db->delete_query("captcha", "imagehash = '{$imagehash}'");
  328. }
  329. }
  330. // Not necessary for reCAPTCHA or Are You a Human
  331. $plugins->run_hooks('captcha_invalidate_end', $this);
  332. }
  333. /**
  334. * Add an error to the error array.
  335. *
  336. * @param string $error
  337. * @param string $data
  338. */
  339. function set_error($error, $data='')
  340. {
  341. $this->errors[$error] = array(
  342. "error_code" => $error,
  343. "data" => $data
  344. );
  345. }
  346. /**
  347. * Returns the error(s) that occurred when handling data
  348. * in a format that MyBB can handle.
  349. *
  350. * @return array An array of errors in a MyBB format.
  351. */
  352. function get_errors()
  353. {
  354. global $lang;
  355. $errors = array();
  356. foreach($this->errors as $error)
  357. {
  358. $lang_string = $error['error_code'];
  359. if(!$lang_string)
  360. {
  361. if($lang->invalid_captcha_verify)
  362. {
  363. $lang_string = 'invalid_captcha_verify';
  364. }
  365. else
  366. {
  367. $lang_string = 'unknown_error';
  368. }
  369. }
  370. if(!isset($lang->$lang_string))
  371. {
  372. $errors[] = $error['error_code'];
  373. continue;
  374. }
  375. if(!empty($error['data']) && !is_array($error['data']))
  376. {
  377. $error['data'] = array($error['data']);
  378. }
  379. if(is_array($error['data']))
  380. {
  381. array_unshift($error['data'], $lang->$lang_string);
  382. $errors[] = call_user_func_array(array($lang, "sprintf"), $error['data']);
  383. }
  384. else
  385. {
  386. $errors[] = $lang->$lang_string;
  387. }
  388. }
  389. return $errors;
  390. }
  391. /**
  392. * @param array $data
  393. *
  394. * @return string
  395. */
  396. private function _qsencode($data)
  397. {
  398. $req = '';
  399. foreach($data as $key => $value)
  400. {
  401. $req .= $key.'='.urlencode(stripslashes($value)).'&';
  402. }
  403. $req = substr($req, 0, (strlen($req) - 1));
  404. return $req;
  405. }
  406. }