PageRenderTime 43ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/phpBB/includes/captcha/plugins/captcha_abstract.php

http://github.com/phpbb/phpbb3
PHP | 372 lines | 273 code | 55 blank | 44 comment | 25 complexity | f8399b09967ef130d0de5f9c1045134a MD5 | raw file
Possible License(s): AGPL-1.0
  1. <?php
  2. /**
  3. *
  4. * @package VC
  5. * @copyright (c) 2006, 2008 phpBB Group
  6. * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
  7. *
  8. */
  9. /**
  10. * @ignore
  11. */
  12. if (!defined('IN_PHPBB'))
  13. {
  14. exit;
  15. }
  16. /**
  17. * This class holds the code shared by the two default 3.0.x CAPTCHAs.
  18. *
  19. * @package VC
  20. */
  21. class phpbb_captcha_plugins_captcha_abstract
  22. {
  23. var $confirm_id;
  24. var $confirm_code;
  25. var $code;
  26. var $seed;
  27. var $attempts = 0;
  28. var $type;
  29. var $solved = 0;
  30. var $captcha_vars = false;
  31. function init($type)
  32. {
  33. global $config, $db, $user;
  34. // read input
  35. $this->confirm_id = request_var('confirm_id', '');
  36. $this->confirm_code = request_var('confirm_code', '');
  37. $refresh = request_var('refresh_vc', false) && $config['confirm_refresh'];
  38. $this->type = (int) $type;
  39. if (!strlen($this->confirm_id) || !$this->load_code())
  40. {
  41. // we have no confirm ID, better get ready to display something
  42. $this->generate_code();
  43. }
  44. else if ($refresh)
  45. {
  46. $this->regenerate_code();
  47. }
  48. }
  49. function execute_demo()
  50. {
  51. global $user;
  52. $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
  53. $this->seed = hexdec(substr(unique_id(), 4, 10));
  54. // compute $seed % 0x7fffffff
  55. $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
  56. $captcha = new captcha();
  57. define('IMAGE_OUTPUT', 1);
  58. $captcha->execute($this->code, $this->seed);
  59. }
  60. function execute()
  61. {
  62. if (empty($this->code))
  63. {
  64. if (!$this->load_code())
  65. {
  66. // invalid request, bail out
  67. return false;
  68. }
  69. }
  70. $captcha = new captcha();
  71. define('IMAGE_OUTPUT', 1);
  72. $captcha->execute($this->code, $this->seed);
  73. }
  74. function get_template()
  75. {
  76. global $config, $user, $template, $phpEx, $phpbb_root_path;
  77. if ($this->is_solved())
  78. {
  79. return false;
  80. }
  81. else
  82. {
  83. $link = append_sid($phpbb_root_path . 'ucp.' . $phpEx, 'mode=confirm&amp;confirm_id=' . $this->confirm_id . '&amp;type=' . $this->type);
  84. $explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>');
  85. $template->assign_vars(array(
  86. 'CONFIRM_IMAGE_LINK' => $link,
  87. 'CONFIRM_IMAGE' => '<img src="' . $link . '" />',
  88. 'CONFIRM_IMG' => '<img src="' . $link . '" />',
  89. 'CONFIRM_ID' => $this->confirm_id,
  90. 'S_CONFIRM_CODE' => true,
  91. 'S_TYPE' => $this->type,
  92. 'S_CONFIRM_REFRESH' => ($config['enable_confirm'] && $config['confirm_refresh'] && $this->type == CONFIRM_REG) ? true : false,
  93. 'L_CONFIRM_EXPLAIN' => $explain,
  94. ));
  95. return 'captcha_default.html';
  96. }
  97. }
  98. function get_demo_template($id)
  99. {
  100. global $config, $user, $template, $phpbb_admin_path, $phpEx;
  101. $variables = '';
  102. if (is_array($this->captcha_vars))
  103. {
  104. foreach ($this->captcha_vars as $captcha_var => $template_var)
  105. {
  106. $variables .= '&amp;' . rawurlencode($captcha_var) . '=' . request_var($captcha_var, (int) $config[$captcha_var]);
  107. }
  108. }
  109. // acp_captcha has a delivery function; let's use it
  110. $template->assign_vars(array(
  111. 'CONFIRM_IMAGE' => append_sid($phpbb_admin_path . 'index.' . $phpEx, 'captcha_demo=1&amp;mode=visual&amp;i=' . $id . '&amp;select_captcha=' . $this->get_class_name()) . $variables,
  112. 'CONFIRM_ID' => $this->confirm_id,
  113. ));
  114. return 'captcha_default_acp_demo.html';
  115. }
  116. function get_hidden_fields()
  117. {
  118. $hidden_fields = array();
  119. // this is required for posting.php - otherwise we would forget about the captcha being already solved
  120. if ($this->solved)
  121. {
  122. $hidden_fields['confirm_code'] = $this->confirm_code;
  123. }
  124. $hidden_fields['confirm_id'] = $this->confirm_id;
  125. return $hidden_fields;
  126. }
  127. function garbage_collect($type)
  128. {
  129. global $db, $config;
  130. $sql = 'SELECT DISTINCT c.session_id
  131. FROM ' . CONFIRM_TABLE . ' c
  132. LEFT JOIN ' . SESSIONS_TABLE . ' s ON (c.session_id = s.session_id)
  133. WHERE s.session_id IS NULL' .
  134. ((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type);
  135. $result = $db->sql_query($sql);
  136. if ($row = $db->sql_fetchrow($result))
  137. {
  138. $sql_in = array();
  139. do
  140. {
  141. $sql_in[] = (string) $row['session_id'];
  142. }
  143. while ($row = $db->sql_fetchrow($result));
  144. if (sizeof($sql_in))
  145. {
  146. $sql = 'DELETE FROM ' . CONFIRM_TABLE . '
  147. WHERE ' . $db->sql_in_set('session_id', $sql_in);
  148. $db->sql_query($sql);
  149. }
  150. }
  151. $db->sql_freeresult($result);
  152. }
  153. function uninstall()
  154. {
  155. $this->garbage_collect(0);
  156. }
  157. function install()
  158. {
  159. return;
  160. }
  161. function validate()
  162. {
  163. global $config, $db, $user;
  164. if (empty($user->lang))
  165. {
  166. $user->setup();
  167. }
  168. $error = '';
  169. if (!$this->confirm_id)
  170. {
  171. $error = $user->lang['CONFIRM_CODE_WRONG'];
  172. }
  173. else
  174. {
  175. if ($this->check_code())
  176. {
  177. $this->solved = true;
  178. }
  179. else
  180. {
  181. $error = $user->lang['CONFIRM_CODE_WRONG'];
  182. }
  183. }
  184. if (strlen($error))
  185. {
  186. // okay, incorrect answer. Let's ask a new question.
  187. $this->new_attempt();
  188. return $error;
  189. }
  190. else
  191. {
  192. return false;
  193. }
  194. }
  195. /**
  196. * The old way to generate code, suitable for GD and non-GD. Resets the internal state.
  197. */
  198. function generate_code()
  199. {
  200. global $db, $user;
  201. $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
  202. $this->confirm_id = md5(unique_id($user->ip));
  203. $this->seed = hexdec(substr(unique_id(), 4, 10));
  204. $this->solved = 0;
  205. // compute $seed % 0x7fffffff
  206. $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
  207. $sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array(
  208. 'confirm_id' => (string) $this->confirm_id,
  209. 'session_id' => (string) $user->session_id,
  210. 'confirm_type' => (int) $this->type,
  211. 'code' => (string) $this->code,
  212. 'seed' => (int) $this->seed)
  213. );
  214. $db->sql_query($sql);
  215. }
  216. /**
  217. * New Question, if desired.
  218. */
  219. function regenerate_code()
  220. {
  221. global $db, $user;
  222. $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
  223. $this->seed = hexdec(substr(unique_id(), 4, 10));
  224. $this->solved = 0;
  225. // compute $seed % 0x7fffffff
  226. $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
  227. $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
  228. 'code' => (string) $this->code,
  229. 'seed' => (int) $this->seed)) . '
  230. WHERE
  231. confirm_id = \'' . $db->sql_escape($this->confirm_id) . '\'
  232. AND session_id = \'' . $db->sql_escape($user->session_id) . '\'';
  233. $db->sql_query($sql);
  234. }
  235. /**
  236. * New Question, if desired.
  237. */
  238. function new_attempt()
  239. {
  240. global $db, $user;
  241. $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
  242. $this->seed = hexdec(substr(unique_id(), 4, 10));
  243. $this->solved = 0;
  244. // compute $seed % 0x7fffffff
  245. $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
  246. $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
  247. 'code' => (string) $this->code,
  248. 'seed' => (int) $this->seed)) . '
  249. , attempts = attempts + 1
  250. WHERE
  251. confirm_id = \'' . $db->sql_escape($this->confirm_id) . '\'
  252. AND session_id = \'' . $db->sql_escape($user->session_id) . '\'';
  253. $db->sql_query($sql);
  254. }
  255. /**
  256. * Look up everything we need for painting&checking.
  257. */
  258. function load_code()
  259. {
  260. global $db, $user;
  261. $sql = 'SELECT code, seed, attempts
  262. FROM ' . CONFIRM_TABLE . "
  263. WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
  264. AND session_id = '" . $db->sql_escape($user->session_id) . "'
  265. AND confirm_type = " . $this->type;
  266. $result = $db->sql_query($sql);
  267. $row = $db->sql_fetchrow($result);
  268. $db->sql_freeresult($result);
  269. if ($row)
  270. {
  271. $this->code = $row['code'];
  272. $this->seed = $row['seed'];
  273. $this->attempts = $row['attempts'];
  274. return true;
  275. }
  276. return false;
  277. }
  278. function check_code()
  279. {
  280. return (strcasecmp($this->code, $this->confirm_code) === 0);
  281. }
  282. function get_attempt_count()
  283. {
  284. return $this->attempts;
  285. }
  286. function reset()
  287. {
  288. global $db, $user;
  289. $sql = 'DELETE FROM ' . CONFIRM_TABLE . "
  290. WHERE session_id = '" . $db->sql_escape($user->session_id) . "'
  291. AND confirm_type = " . (int) $this->type;
  292. $db->sql_query($sql);
  293. // we leave the class usable by generating a new question
  294. $this->generate_code();
  295. }
  296. function is_solved()
  297. {
  298. if (request_var('confirm_code', false) && $this->solved === 0)
  299. {
  300. $this->validate();
  301. }
  302. return (bool) $this->solved;
  303. }
  304. /**
  305. * API function
  306. */
  307. function has_config()
  308. {
  309. return false;
  310. }
  311. }
  312. /**
  313. * Old class name for legacy use. The new class name is auto loadable.
  314. */
  315. class phpbb_default_captcha extends phpbb_captcha_plugins_captcha_abstract
  316. {
  317. }