PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/includes/captcha/plugins/captcha_abstract.php

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