PageRenderTime 47ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/includes/captcha/plugins/captcha_abstract.php

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