diff options
author | Henry Sudhof <kellanved@phpbb.com> | 2009-06-02 14:12:23 +0000 |
---|---|---|
committer | Henry Sudhof <kellanved@phpbb.com> | 2009-06-02 14:12:23 +0000 |
commit | b776d02682492077a4fafd8835d7c4a17e50762d (patch) | |
tree | 0c94c7e662baaaf047f1eace9658bd13fc36b8e3 /phpBB/includes | |
parent | b9ece6bdfe65b2e63c42d4a83fd831b4377e1b90 (diff) | |
download | forums-b776d02682492077a4fafd8835d7c4a17e50762d.tar forums-b776d02682492077a4fafd8835d7c4a17e50762d.tar.gz forums-b776d02682492077a4fafd8835d7c4a17e50762d.tar.bz2 forums-b776d02682492077a4fafd8835d7c4a17e50762d.tar.xz forums-b776d02682492077a4fafd8835d7c4a17e50762d.zip |
Okay, a first ci of the new captcha plugins. We'll add dynamic template includes later, as well as documentation on how to use this. I'm prepared to get yelled at for bugs (oh, I know that there are plenty); but please blame spammers for broken styles and MODs.
git-svn-id: file:///svn/phpbb/branches/phpBB-3_0_0@9524 89ea8834-ac86-4346-8a33-228a782c2dd0
Diffstat (limited to 'phpBB/includes')
-rw-r--r-- | phpBB/includes/acp/acp_captcha.php | 177 | ||||
-rw-r--r-- | phpBB/includes/auth/auth_db.php | 39 | ||||
-rwxr-xr-x | phpBB/includes/captcha/captcha_factory.php | 92 | ||||
-rwxr-xr-x | phpBB/includes/captcha/captcha_gd_wave.php | 842 | ||||
-rwxr-xr-x | phpBB/includes/captcha/captcha_plugin.php | 97 | ||||
-rwxr-xr-x | phpBB/includes/captcha/plugins/captcha_abstract.php | 332 | ||||
-rwxr-xr-x | phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php | 122 | ||||
-rwxr-xr-x | phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php | 66 | ||||
-rwxr-xr-x | phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php | 68 | ||||
-rw-r--r-- | phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php | 312 | ||||
-rw-r--r-- | phpBB/includes/functions.php | 33 | ||||
-rw-r--r-- | phpBB/includes/session.php | 40 | ||||
-rw-r--r-- | phpBB/includes/ucp/ucp_confirm.php | 42 | ||||
-rw-r--r-- | phpBB/includes/ucp/ucp_register.php | 168 |
14 files changed, 2097 insertions, 333 deletions
diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php index 93505e1590..ed2ccf6ccc 100644 --- a/phpBB/includes/acp/acp_captcha.php +++ b/phpBB/includes/acp/acp_captcha.php @@ -10,6 +10,8 @@ /** * @ignore */ + + if (!defined('IN_PHPBB')) { exit; @@ -28,108 +30,119 @@ class acp_captcha global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; $user->add_lang('acp/board'); - $captcha_vars = array( - 'captcha_gd_x_grid' => 'CAPTCHA_GD_X_GRID', - 'captcha_gd_y_grid' => 'CAPTCHA_GD_Y_GRID', - 'captcha_gd_foreground_noise' => 'CAPTCHA_GD_FOREGROUND_NOISE', - 'captcha_gd' => 'CAPTCHA_GD_PREVIEWED', - 'captcha_gd_wave' => 'CAPTCHA_GD_WAVE', - 'captcha_gd_3d_noise' => 'CAPTCHA_GD_3D_NOISE', - 'captcha_gd_fonts' => 'CAPTCHA_GD_FONTS', - ); + include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); - if (isset($_GET['demo'])) + $selected = request_var('select_captcha', $config['captcha_plugin']); + $configure = request_var('configure', false); + + // Oh, they are just here for the view + if (isset($_GET['captcha_demo'])) { - $captcha_vars = array_keys($captcha_vars); - - foreach ($captcha_vars as $captcha_var) - { - $config[$captcha_var] = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var]; - } - - if ($config['captcha_gd']) - { - include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx); - } - else - { - include($phpbb_root_path . 'includes/captcha/captcha_non_gd.' . $phpEx); - } - - $captcha = new captcha(); - $captcha->execute(gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)), time()); - exit; + $this->deliver_demo($selected); } - - $config_vars = array( - 'enable_confirm' => 'REG_ENABLE', - 'enable_post_confirm' => 'POST_ENABLE', - 'confirm_refresh' => 'CONFIRM_REFRESH', - 'captcha_gd' => 'CAPTCHA_GD', - ); - - $this->tpl_name = 'acp_captcha'; - $this->page_title = 'ACP_VC_SETTINGS'; - $form_key = 'acp_captcha'; - add_form_key($form_key); - - $submit = request_var('submit', ''); - - if ($submit && check_form_key($form_key)) + + // Delegate + if ($configure) { - $config_vars = array_keys($config_vars); + $config_captcha = phpbb_captcha_factory::get_instance($selected); + $config_captcha->acp_page($id, $this); + add_log('admin', 'LOG_CONFIG_VISUAL'); + } + else + { + $captchas = phpbb_captcha_factory::get_captcha_types(); + $config_vars = array( + 'enable_confirm' => 'REG_ENABLE', + 'enable_post_confirm' => 'POST_ENABLE', + 'confirm_refresh' => 'CONFIRM_REFRESH', + ); - foreach ($config_vars as $config_var) - { - set_config($config_var, request_var($config_var, '')); - } + $this->tpl_name = 'acp_captcha'; + $this->page_title = 'ACP_VC_SETTINGS'; + $form_key = 'acp_captcha'; + add_form_key($form_key); - $captcha_vars = array_keys($captcha_vars); + $submit = request_var('main_submit', false); - foreach ($captcha_vars as $captcha_var) + if ($submit && check_form_key($form_key)) { - $value = request_var($captcha_var, 0); - if ($value >= 0) + $config_vars = array_keys($config_vars); + foreach ($config_vars as $config_var) { - set_config($captcha_var, $value); + set_config($config_var, request_var($config_var, false)); } + if ($selected !== $config['captcha_plugin']) + { + // sanity check + if (isset($captchas['available'][$selected])) + { + $old_captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $old_captcha->uninstall(); + set_config('captcha_plugin', $selected); + $new_captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $old_captcha->install(); + add_log('admin', 'LOG_CONFIG_VISUAL'); + } + else + { + trigger_error($user->lang['CAPTCHA_UNAVAILABLE'] . adm_back_link($this->u_action)); + } + } + trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); } - - add_log('admin', 'LOG_CONFIG_VISUAL'); - trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); - } - else if ($submit) - { - trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action)); - } - else - { - $preview_image_src = append_sid(append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&demo=demo")); - - if (@extension_loaded('gd')) + else if ($submit) { - $template->assign_var('GD', true); + trigger_error($user->lang['FORM_INVALID'] . adm_back_link()); } - - foreach ($config_vars as $config_var => $template_var) + else { - $template->assign_var($template_var, (isset($_REQUEST[$config_var])) ? request_var($config_var, '') : $config[$config_var]) ; - } + $captcha_select = ''; + foreach ($captchas['available'] as $value => $title) + { + $current = ($selected !== false && $value == $selected) ? ' selected="selected"' : ''; + $captcha_select .= '<option value="' . $value . '"' . $current . '>' . $user->lang[$title] . '</option>'; + } + foreach ($captchas['unavailable'] as $value => $title) + { + $current = ($selected !== false && $value == $selected) ? ' selected="selected"' : ''; + $captcha_select .= '<option value="' . $value . '"' . $current . ' class="disabled-option" >' . $user->lang[$title] . '</option>'; + } - foreach ($captcha_vars as $captcha_var => $template_var) - { - $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var]; - $template->assign_var($template_var, $var); - $preview_image_src .= "&$captcha_var=" . $var; + $demo_captcha = phpbb_captcha_factory::get_instance($selected); + + foreach ($config_vars as $config_var => $template_var) + { + $template->assign_var($template_var, (isset($_REQUEST[$config_var])) ? request_var($config_var, '') : $config[$config_var]) ; + } + + $template->assign_vars(array( + 'CAPTCHA_PREVIEW' => $demo_captcha->get_demo_template($id), + 'CAPTCHA_SELECT' => $captcha_select, + )); } - $template->assign_vars(array( - 'CAPTCHA_PREVIEW' => $preview_image_src, - 'PREVIEW' => isset($_POST['preview']), - )); } } + + + /** + * Entry point for delivering image CAPTCHAs in the ACP. + */ + function deliver_demo($selected) + { + global $db, $user, $config; + + $captcha = phpbb_captcha_factory::get_instance($selected); + $captcha->init(CONFIRM_REG); + $captcha->execute_demo(); + garbage_collection(); + exit_handler(); + } + + + + } ?>
\ No newline at end of file diff --git a/phpBB/includes/auth/auth_db.php b/phpBB/includes/auth/auth_db.php index 24d4c56614..bdafefa70b 100644 --- a/phpBB/includes/auth/auth_db.php +++ b/phpBB/includes/auth/auth_db.php @@ -81,42 +81,15 @@ function login_db(&$username, &$password) } else { - global $user; - - $sql = 'SELECT code - FROM ' . CONFIRM_TABLE . " - WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "' - AND session_id = '" . $db->sql_escape($user->session_id) . "' - AND confirm_type = " . CONFIRM_LOGIN; - $result = $db->sql_query($sql); - $confirm_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($confirm_row) + $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha->init(CONFIRM_LOGIN); + $vc_response = $captcha->validate(); + if ($vc_response) { - if (strcasecmp($confirm_row['code'], $confirm_code) === 0) - { - $sql = 'DELETE FROM ' . CONFIRM_TABLE . " - WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "' - AND session_id = '" . $db->sql_escape($user->session_id) . "' - AND confirm_type = " . CONFIRM_LOGIN; - $db->sql_query($sql); - } - else - { - return array( + return array( 'status' => LOGIN_ERROR_ATTEMPTS, - 'error_msg' => 'CONFIRM_CODE_WRONG', + 'error_msg' => 'LOGIN_ERROR_ATTEMPTS', 'user_row' => $row, - ); - } - } - else - { - return array( - 'status' => LOGIN_ERROR_ATTEMPTS, - 'error_msg' => 'CONFIRM_CODE_WRONG', - 'user_row' => $row, ); } } diff --git a/phpBB/includes/captcha/captcha_factory.php b/phpBB/includes/captcha/captcha_factory.php new file mode 100755 index 0000000000..e6f56172ec --- /dev/null +++ b/phpBB/includes/captcha/captcha_factory.php @@ -0,0 +1,92 @@ +<? +/** +* +* @package VC +* @version $Id: $ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + + +/** A small class until we get the autoloader done */ +class phpbb_captcha_factory +{ + /** + * return an instance of class $name in file $name_plugin.php + */ + function get_instance($name) + { + global $phpbb_root_path, $phpEx; + + $name = basename($name); + if (!class_exists($name)) + { + include($phpbb_root_path . "includes/captcha/plugins/{$name}_plugin." . $phpEx); + } + return call_user_func(array($name, 'get_instance')); + } + + /** + * Call the garbage collector + */ + function garbage_collect($name) + { + global $phpbb_root_path, $phpEx; + + $name = basename($name); + if (!class_exists($name)) + { + include($phpbb_root_path . "includes/captcha/plugins/{$name}_plugin." . $phpEx); + } + call_user_func(array($name, 'garbage_collect'), 0); + } + + /** + * return a list of all discovered CAPTCHA plugins + */ + function get_captcha_types() + { + global $phpbb_root_path, $phpEx; + + $captchas = array(); + $captchas['available'] = array(); + $captchas['unavailable'] = array(); + + $dp = @opendir($phpbb_root_path . 'includes/captcha/plugins'); + + if ($dp) + { + while (($file = readdir($dp)) !== false) + { + if ((preg_match('#_plugin\.' . $phpEx . '$#', $file))) + { + $name = preg_replace('#^(.*?)_plugin\.' . $phpEx . '$#', '\1', $file); + if (!class_exists($name)) + { + include($phpbb_root_path . "includes/captcha/plugins/$file"); + } + if (call_user_func(array($name, 'is_available'))) + { + $captchas['available'][$name] = call_user_func(array($name, 'get_name')); + } + else + { + $captchas['unavailable'][$name] = call_user_func(array($name, 'get_name')); + } + } + } + closedir($dp); + } + + return $captchas; + } +}
\ No newline at end of file diff --git a/phpBB/includes/captcha/captcha_gd_wave.php b/phpBB/includes/captcha/captcha_gd_wave.php new file mode 100755 index 0000000000..0356538a4d --- /dev/null +++ b/phpBB/includes/captcha/captcha_gd_wave.php @@ -0,0 +1,842 @@ +<?php
+/**
+*
+* @package VC
+* @version $Id: captcha_gd.php,v 1.19 2007/01/26 16:07:43 acydburn Exp $
+* @copyright (c) 2006 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+ + +/** +Wave3D CAPTCHA by Robert Hetzler +*/
+class captcha
+{
+ var $width = 360;
+ var $height = 96;
+
+ function execute($code, $seed)
+ {
+ global $starttime;
+
+ // seed the random generator
+ mt_srand($seed);
+
+ // set height and width
+ $img_x = $this->width;
+ $img_y = $this->height;
+
+ // Generate image
+ $img = imagecreatetruecolor($img_x, $img_y);
+ $x_grid = mt_rand(6, 10);
+ $y_grid = mt_rand(6, 10);
+
+ // Ok, so lets cut to the chase. We could accurately represent this in 3d and
+ // do all the appropriate linear transforms. my questions is... why bother?
+ // The computational overhead is unnecessary when you consider the simple fact:
+ // we're not here to accurately represent a model, but to just show off some random-ish
+ // polygons
+
+ // Conceive of 3 spaces.
+ // 1) planar-space (discrete "pixel" grid)
+ // 2) 3-space. (planar-space with z/height aspect)
+ // 3) image space (pixels on the screen)
+ // resolution of the planar-space we're embedding the text code in
+ $plane_x = 100;
+ $plane_y = 30;
+
+ $subdivision_factor = 3;
+ // $box is the 4 points in img_space that correspond to the corners of the plane in 3-space
+ $box = array(
+ 'upper_left' => array(
+ 'x' => mt_rand(5, 15),
+ 'y' => mt_rand(10, 15)
+ ),
+ 'upper_right' => array(
+ 'x' => mt_rand($img_x - 35, $img_x - 19),
+ 'y' => mt_rand(10, 17)
+ ),
+ 'lower_left' => array(
+ 'x' => mt_rand($img_x - 5, $img_x - 45),
+ 'y' => mt_rand($img_y - 0, $img_y - 15)
+ ),
+ );
+ $box['lower_right'] = array(
+ 'x' => $box['lower_left']['x'] + $box['upper_left']['x'] - $box['upper_right']['x'],
+ 'y' => $box['lower_left']['y'] + $box['upper_left']['y'] - $box['upper_right']['y'],
+ );
+
+
+ // TODO
+ $background = imagecolorallocate($img, mt_rand(155, 255), mt_rand(155, 255), mt_rand(155, 255));
+ imagefill($img, 0, 0, $background);
+ $black = imagecolorallocate($img, 0, 0, 0);
+
+ $random = array();
+ $fontcolors = array();
+
+ for ($i = 0; $i < 15; ++$i)
+ {
+ $random[$i] = imagecolorallocate($img, mt_rand(120, 255), mt_rand(120, 255), mt_rand(120, 255));
+ }
+
+ $fontcolors[0] = imagecolorallocate($img, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120));
+
+ $colors = array();
+
+ $minr = mt_rand(20, 30);
+ $ming = mt_rand(20, 30);
+ $minb = mt_rand(20, 30);
+
+ $maxr = mt_rand(150, 230);
+ $maxg = mt_rand(150, 230);
+ $maxb = mt_rand(150, 230);
+
+ for ($i = -30; $i <= 30; ++$i)
+ {
+ $coeff1 = ($i + 12) / 45;
+ $coeff2 = 1 - $coeff1;
+ $colors[$i] = imagecolorallocate($img, ($coeff2 * $maxr) + ($coeff1 * $minr), ($coeff2 * $maxg) + ($coeff1 * $ming), ($coeff2 * $maxb) + ($coeff1 * $minb));
+ }
+
+ // $img_buffer is the last row of 3-space positions (converted to img-space), cached
+ // (using this means we don't need to recalculate all 4 positions for each new polygon,
+ // merely the newest point that we're adding, which is then cached.
+ $img_buffer = array(array(), array());
+
+ // In image-space, the x- and y-offset necessary to move one unit in the x-direction in planar-space
+ $dxx = ($box['upper_right']['x'] - $box['upper_left']['x']) / ($subdivision_factor * $plane_x);
+ $dxy = ($box['upper_right']['y'] - $box['upper_left']['y']) / ($subdivision_factor * $plane_x);
+
+ // In image-space, the x- and y-offset necessary to move one unit in the y-direction in planar-space
+ $dyx = ($box['lower_right']['x'] - $box['upper_left']['x']) / ($subdivision_factor * $plane_y);
+ $dyy = ($box['lower_right']['y'] - $box['upper_left']['y']) / ($subdivision_factor * $plane_y);
+
+ // Initial captcha-letter offset in planar-space
+ $plane_offset_x = mt_rand(3, 8);
+ $plane_offset_y = mt_rand( 12, 15);
+
+ // character map
+ $map = $this->captcha_bitmaps();
+
+ // matrix
+ $plane = array();
+
+ // for each character, we'll silkscreen it into our boolean pixel plane
+ for ($c = 0, $code_num = strlen($code); $c < $code_num; ++$c)
+ {
+ $letter = $code[$c];
+
+ for ($x = $map['width'] - 1; $x >= 0; --$x)
+ {
+ for ($y = $map['height'] - 1; $y >= 0; --$y)
+ {
+ if ($map['data'][$letter][$y][$x])
+ {
+ $plane[$y + $plane_offset_y + (($c & 1) ? 1 : -1)][$x + $plane_offset_x] = true;
+ }
+ }
+ }
+ $plane_offset_x += 11;
+ }
+
+ // calculate our first buffer, we can't actually draw polys with these yet
+ // img_pos_prev == screen x,y location to our immediate left.
+ // img_pos_cur == current screen x,y location
+ // we calculate screen position of our
+ // current cell based on the difference from the previous cell
+ // rather than recalculating from absolute coordinates
+ // What we cache into the $img_buffer contains the raised text coordinates.
+ $img_pos_prev = $img_buffer[0][0] = array($box['upper_left']['x'], $box['upper_left']['y']);
+ $cur_height = $prev_height = $this->wave_height(0, 0, $subdivision_factor);
+ $full_x = $plane_x * $subdivision_factor;
+ $full_y = $plane_y * $subdivision_factor;
+
+ for ($x = 1; $x <= $full_x; ++$x)
+ {
+ $cur_height = $this->wave_height($x, 0, $subdivision_factor);
+ $offset = $cur_height - $prev_height;
+ $img_pos_cur = array($img_pos_prev[0] + $dxx, $img_pos_prev[1] + $dxy + $offset);
+
+ $img_buffer[0][$x] = $img_pos_cur;
+ $img_pos_prev = $img_pos_cur;
+ $prev_height = $cur_height;
+ }
+
+ for ($y = 1; $y <= $full_y; ++$y)
+ {
+ // swap buffers
+ $buffer_cur = $y & 1;
+ $buffer_prev = 1 - $buffer_cur;
+
+ $prev_height = $this->wave_height(0, $y, $subdivision_factor);
+ $offset = $prev_height - $this->wave_height(0, $y - 1, $subdivision_factor);
+ $img_pos_cur = array($img_buffer[$buffer_prev][0][0] + $dyx, min($img_buffer[$buffer_prev][0][1] + $dyy + $offset, $img_y - 1));
+
+ // make sure we don't try to write off the page
+ $img_pos_prev = $img_pos_cur;
+
+ $img_buffer[$buffer_cur][0] = $img_pos_cur;
+
+ for ($x = 1; $x <= $full_x; ++$x)
+ {
+ $cur_height = $this->wave_height($x, $y, $subdivision_factor) + $this->grid_height($x, $y, 1, $x_grid, $y_grid);
+
+ // height is a z-factor, not a y-factor
+ $offset = $cur_height - $prev_height;
+ $img_pos_cur = array($img_pos_prev[0] + $dxx, $img_pos_prev[1] + $dxy + $offset);
+
+ // height is float, index it to an int, get closest color
+ $color = $colors[intval($cur_height)];
+ $img_pos_prev = $img_pos_cur;
+ $prev_height = $cur_height;
+
+ $y_index_old = intval(($y - 1) / $subdivision_factor);
+ $y_index_new = intval($y / $subdivision_factor);
+ $x_index_old = intval(($x - 1) / $subdivision_factor);
+ $x_index_new = intval($x / $subdivision_factor);
+
+ if (!empty($plane[$y_index_new][$x_index_new]))
+ {
+ $img_pos_cur[1] += $this->wave_height($x, $y, $subdivision_factor, 1) - 30 - $cur_height;
+ $color = $colors[20];
+ }
+ $img_pos_cur[1] = min($img_pos_cur[1], $img_y - 1);
+ $img_buffer[$buffer_cur][$x] = $img_pos_cur;
+
+ // Smooth the edges as much as possible by having not more than one low<->high traingle per square
+ // Otherwise, just
+ $diag_down = (empty($plane[$y_index_old][$x_index_old]) == empty($plane[$y_index_new][$x_index_new]));
+ $diag_up = (empty($plane[$y_index_old][$x_index_new]) == empty($plane[$y_index_new][$x_index_old]));
+
+ // natural switching
+ $mode = ($x + $y) & 1;
+
+ // override if it requires it
+ if ($diag_down != $diag_up)
+ {
+ $mode = $diag_up;
+ }
+
+ if ($mode)
+ {
+ // +-/ /
+ // 1 |/ 2 /|
+ // / /-+
+ $poly1 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_prev][$x]);
+ $poly2 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_cur][$x], $img_buffer[$buffer_prev][$x]);
+ }
+ else
+ {
+ // \ \-+
+ // 1 |\ 2 \|
+ // +-\ \
+ $poly1 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_cur][$x]);
+ $poly2 = array_merge($img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_prev][$x], $img_buffer[$buffer_cur][$x]);
+ }
+
+ imagefilledpolygon($img, $poly1, 3, $color);
+ imagefilledpolygon($img, $poly2, 3, $color);
+ }
+ }
+
+ // Output image
+ header('Content-Type: image/png');
+ header('Cache-control: no-cache, no-store');
+ //$mtime = explode(' ', microtime());
+ //$totaltime = $mtime[0] + $mtime[1] - $starttime;
+
+ //echo $totaltime . "<br />\n";
+ //echo memory_get_usage() - $tmp;
+ imagepng($img);
+ imagedestroy($img);
+ }
+
+ function wave_height($x, $y, $factor = 1, $tweak = 0.7)
+ {
+ // stretch the wave. TODO: pretty it up
+ $x = $x/5 + 180;
+ $y = $y/4;
+ return ((sin($x / (3 * $factor)) + sin($y / (3 * $factor))) * 10 * $tweak);
+ }
+
+ function grid_height($x, $y, $factor = 1, $x_grid, $y_grid)
+ {
+ return ((!($x % ($x_grid * $factor)) || !($y % ($y_grid * $factor))) ? 3 : 0);
+ }
+
+ function captcha_bitmaps()
+ {
+ return array(
+ 'width' => 9,
+ 'height' => 13,
+ 'data' => array(
+ 'A' => array(
+ array(0,0,1,1,1,1,0,0,0),
+ array(0,1,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,1,1,1,1,1,1,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'B' => array(
+ array(1,1,1,1,1,1,0,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,1,1,1,1,1,0,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,1,1,1,1,1,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'C' => array(
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'D' => array(
+ array(1,1,1,1,1,1,1,0,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,1,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'E' => array(
+ array(0,0,1,1,1,1,1,1,1),
+ array(0,1,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,1,1,1,1,1,1,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(0,1,0,0,0,0,0,0,0),
+ array(0,0,1,1,1,1,1,1,1),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'F' => array(
+ array(0,0,1,1,1,1,1,1,0),
+ array(0,1,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,1,1,1,1,1,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'G' => array(
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,1,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'H' => array(
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,1,1,1,1,1,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'I' => array(
+ array(0,1,1,1,1,1,1,1,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,1,1,1,1,1,1,1,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'J' => array(
+ array(0,0,0,0,0,0,1,1,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,0,1,0,0,0,0,1,0),
+ array(0,0,0,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'K' => array(
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,1,0,0,0),
+ array(1,0,0,0,1,0,0,0,0),
+ array(1,0,0,1,0,0,0,0,0),
+ array(1,0,1,0,0,0,0,0,0),
+ array(1,1,0,0,0,0,0,0,0),
+ array(1,0,1,0,0,0,0,0,0),
+ array(1,0,0,1,0,0,0,0,0),
+ array(1,0,0,0,1,0,0,0,0),
+ array(1,0,0,0,0,1,0,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'L' => array(
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(0,1,0,0,0,0,0,0,0),
+ array(0,0,1,1,1,1,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'M' => array(
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,1,1,0,0,0,1,1,0),
+ array(0,1,0,1,0,1,0,1,0),
+ array(0,1,0,0,1,0,0,1,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'N' => array(
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,1,0,0,0,0,0,0,1),
+ array(1,0,1,0,0,0,0,0,1),
+ array(1,0,0,1,0,0,0,0,1),
+ array(1,0,0,0,1,0,0,0,1),
+ array(1,0,0,0,0,1,0,0,1),
+ array(1,0,0,0,0,0,1,0,1),
+ array(1,0,0,0,0,0,0,1,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'O' => array(
+ array(0,0,0,1,1,1,0,0,0),
+ array(0,0,1,0,0,0,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,0,0,0,1,0,0),
+ array(0,0,0,1,1,1,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'P' => array(
+ array(1,1,1,1,1,1,0,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,1,1,1,1,1,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'Q' => array(
+ array(0,0,1,1,1,1,0,0,0),
+ array(0,1,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,1,0,0,1,0),
+ array(1,0,0,0,0,1,0,1,0),
+ array(0,1,0,0,0,0,1,0,0),
+ array(0,0,1,1,1,1,0,1,0),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'R' => array(
+ array(1,1,1,1,1,1,0,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,1,1,1,1,1,0,0,0),
+ array(1,0,1,0,0,0,0,0,0),
+ array(1,0,0,1,0,0,0,0,0),
+ array(1,0,0,0,1,0,0,0,0),
+ array(1,0,0,0,0,1,0,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'S' => array(
+ array(0,0,1,1,1,1,1,1,1),
+ array(0,1,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(0,1,0,0,0,0,0,0,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,1,0),
+ array(1,1,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'T' => array(
+ array(1,1,1,1,1,1,1,1,1),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'U' => array(
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'V' => array(
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,0,0,0,1,0,0),
+ array(0,0,0,1,0,1,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'W' => array(
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,1,0,0,0,1),
+ array(1,0,0,1,0,1,0,0,1),
+ array(1,0,1,0,0,0,1,0,1),
+ array(1,1,0,0,0,0,0,1,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'X' => array(
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,0,0,0,1,0,0),
+ array(0,0,0,1,0,1,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,1,0,1,0,0,0),
+ array(0,0,1,0,0,0,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'Y' => array(
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,0,0,0,1,0,0),
+ array(0,0,0,1,0,1,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'Z' => array(
+ array(1,1,1,1,1,1,1,1,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,1,0,0),
+ array(0,0,0,0,0,1,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,1,0,0,0,0,0),
+ array(0,0,1,0,0,0,0,0,0),
+ array(0,1,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,1,1,1,1,1,1,1,1),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '1' => array(
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,1,1,0,0,0,0),
+ array(0,0,1,0,1,0,0,0,0),
+ array(0,1,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,1,1,1,1,1,1,1,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '2' => array(
+ array(0,0,0,1,1,1,0,0,0),
+ array(0,0,1,0,0,0,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,1,0,0),
+ array(0,0,0,0,0,1,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,1,0,0,0,0,0),
+ array(0,0,1,0,0,0,0,0,0),
+ array(0,1,1,1,1,1,1,1,1),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '3' => array(
+ array(0,0,0,1,1,1,1,0,0),
+ array(0,0,1,0,0,0,0,1,0),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,1,1,0,0),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,0,1,0,0,0,0,1,0),
+ array(0,0,0,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '4' => array(
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,1,1,0),
+ array(0,0,0,0,0,1,0,1,0),
+ array(0,0,0,0,1,0,0,1,0),
+ array(0,0,0,1,0,0,0,1,0),
+ array(0,0,1,0,0,0,0,1,0),
+ array(0,1,1,1,1,1,1,1,1),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '5' => array(
+ array(1,1,1,1,1,1,1,1,1),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(0,1,0,0,0,0,0,0,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '6' => array(
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,1,1,1,1,0,0),
+ array(1,0,1,0,0,0,0,1,0),
+ array(1,1,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '7' => array(
+ array(1,1,1,1,1,1,1,1,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,1,0,0),
+ array(0,0,0,0,0,1,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '8' => array(
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '9' => array(
+ array(0,0,0,1,1,1,1,0,0),
+ array(0,0,1,0,0,0,0,1,0),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,1),
+ array(0,0,1,1,1,1,1,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,0,1,0,0,0,0,1,0),
+ array(0,0,0,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ )
+ );
+ } +}
+
+?>
\ No newline at end of file diff --git a/phpBB/includes/captcha/captcha_plugin.php b/phpBB/includes/captcha/captcha_plugin.php new file mode 100755 index 0000000000..08a149764c --- /dev/null +++ b/phpBB/includes/captcha/captcha_plugin.php @@ -0,0 +1,97 @@ +<? + +interface phpbb_captcha_plugin +{ + /** + * Initiates the CAPTCHA to validate codes. + * @param int $type the type as defined in constants.php + */ + function init($type); + + + /** + * Returns true if the captcha will work on the current install + */ + static function is_available(); + + /** + * Returns the translated pretty name of the captcha. + */ + static function get_name(); + + /** + * Returns the class name of the captcha. + */ + static function get_class_name(); + + /** + * Returns an instance; does not have to be the same instance twice. + */ + static function get_instance(); + + /** + * Returns the HTML needed to embed the captcha in another template + */ + function get_template(); + + + /** + * Delivers the image of image based captchas; not required for text/remote etc CAPTCHAs + */ + function execute(); + + /** + * Returns the HTML needed to display a demo of the captcha + */ + function get_demo_template($id); + + + /** + * Delivers the demo image of image based captchas; not required for text/remote etc CAPTCHAs + */ + function execute_demo(); + + /** + * Clears leftover entries in the database. + */ + static function garbage_collect($type); + + + /** + * Clears all entries from the database if the CAPTCHA is replaced + */ + function uninstall(); + + /** + * Sets up the CAPTCHA when it is selected in the ACP. + */ + function install(); + + + /** + * Checks the captcha; returns false if the code was correct; a translated error string otherwise + */ + function validate(); + + /** + * Prepares the captcha to ask a new question; required call on failed answers + */ + function reset(); + + /** + * Displays the configuration options in the ACP + */ + function acp_page($id, &$module); + + /** + * Returns the entries for the hidden field array needed to preserve the current state. + */ + function get_hidden_fields(); + + + /** + * Returns the number of solving attempts of the current user + */ + function get_attempt_count(); + +}
\ No newline at end of file diff --git a/phpBB/includes/captcha/plugins/captcha_abstract.php b/phpBB/includes/captcha/plugins/captcha_abstract.php new file mode 100755 index 0000000000..f5c135dc74 --- /dev/null +++ b/phpBB/includes/captcha/plugins/captcha_abstract.php @@ -0,0 +1,332 @@ +<? +/** +* +* @package VC +* @version $Id: $ +* @copyright (c) 2006 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + + +/** +* This class holds the code shared by the two default 3.0 CAPTCHAs. +*/ +class phpbb_default_captcha +{ + var $confirm_id; + var $confirm_code; + var $code; + var $seed; + var $type; + var $solved = false; + + + function init($type) + { + global $config, $db, $user; + + // read input + $this->confirm_id = request_var('confirm_id', ''); + $this->confirm_code = request_var('confirm_code', ''); + $refresh = request_var('refresh_vc', false) && $config['confirm_refresh']; + + $this->type = (int) $type; + + if (!strlen($this->confirm_id)) + { + // we have no confirm ID, better get ready to display something + $this->generate_code(); + } + else if ($refresh) + { + $this->regenerate_code(); + } + + } + + function execute_demo() + { + global $user; + + $this->code = gen_rand_string(mt_rand(5, 8)); + $this->seed = hexdec(substr(unique_id(), 4, 10)); + + // compute $seed % 0x7fffffff + $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff); + + $captcha = new captcha(); + $captcha->execute($this->code, $this->seed); + } + + + function execute() + { + if (empty($this->code)) + { + if (!$this->load_code()) + { + // invalid request, bail out + return false; + } + } + $captcha = new captcha(); + $captcha->execute($this->code, $this->seed); + } + + + function get_template() + { + global $config, $user, $template, $phpEx, $phpbb_root_path; + + $template->set_filenames(array( + 'captcha' => 'captcha_default.html') + ); + + $template->assign_vars(array( + 'CONFIRM_IMAGE' => append_sid($phpbb_root_path . 'ucp.' . $phpEx . '?mode=confirm&confirm_id=' . $this->confirm_id . '&type=' . $this->type), + 'CONFIRM_ID' => $this->confirm_id, + 'S_REFRESH' => (bool) $config['confirm_refresh'], + + )); + + return $template->assign_display('captcha'); + } + + function get_demo_template($id) + { + global $config, $user, $template, $phpbb_admin_path, $phpEx; + + $template->set_filenames(array( + 'captcha_demo' => 'captcha_default_acp_demo.html') + ); + // acp_captcha has a delivery function; let's use it + $template->assign_vars(array( + 'CONFIRM_IMAGE' => append_sid($phpbb_admin_path . 'index.' . $phpEx . '?captcha_demo=1&mode=visual&i=' . $id . '&select_captcha=' . $this->get_class_name()), + 'CONFIRM_ID' => $this->confirm_id, + )); + + return $template->assign_display('captcha_demo'); + } + + function get_hidden_fields() + { + $hidden_fields = array(); + + // this is required for postig.php - otherwise we would forget about the captcha being already solved + if ($this->solved) + { + $hidden_fields['confirm_code'] = $this->confirm_code; + } + $hidden_fields['confirm_id'] = $this->confirm_id; + return $hidden_fields; + } + + function garbage_collect($type) + { + global $db, $config; + + $sql = 'SELECT DISTINCT c.session_id + FROM ' . CONFIRM_TABLE . ' c + LEFT JOIN ' . SESSIONS_TABLE . ' s ON (c.session_id = s.session_id) + WHERE s.session_id IS NULL' . + ((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type); + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $sql_in = array(); + do + { + $sql_in[] = (string) $row['session_id']; + } + while ($row = $db->sql_fetchrow($result)); + + if (sizeof($sql_in)) + { + $sql = 'DELETE FROM ' . CONFIRM_TABLE . ' + WHERE ' . $db->sql_in_set('session_id', $sql_in); + $db->sql_query($sql); + } + } + $db->sql_freeresult($result); + } + + function uninstall() + { + self::garbage_collect(0); + } + + function install() + { + return; + } + + function validate() + { + global $config, $db, $user; + + $this->confirm_code = request_var('confirm_code', ''); + if (!$this->confirm_id) + { + $error = $user->lang['CONFIRM_CODE_WRONG']; + } + else + { + if ($this->check_code()) + { + // $this->delete_code(); commented out to allow posting.php to repeat the question + $this->solved = true; + } + else + { + $error = $user->lang['CONFIRM_CODE_WRONG']; + } + } + + if (strlen($error)) + { + // okay, inorect answer. Let's ask a new question + $this->generate_code(); + return $error; + } + else + { + return false; + } + } + + + /** + * The old way to generate code, suitable for GD and non-GD. Resets the internal state. + */ + function generate_code() + { + global $db, $user; + + $this->code = gen_rand_string(mt_rand(5, 8)); + $this->confirm_id = md5(unique_id($user->ip)); + $this->seed = hexdec(substr(unique_id(), 4, 10)); + $this->solved = false; + // compute $seed % 0x7fffffff + $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff); + + $sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'confirm_id' => (string) $this->confirm_id, + 'session_id' => (string) $user->session_id, + 'confirm_type' => (int) $this->type, + 'code' => (string) $this->code, + 'seed' => (int) $this->seed) + ); + $db->sql_query($sql); + } + + /** + * New Question, if desired. + */ + function regenerate_code() + { + global $db, $user; + + $this->code = gen_rand_string(mt_rand(5, 8)); + $this->seed = hexdec(substr(unique_id(), 4, 10)); + $this->solved = false; + // compute $seed % 0x7fffffff + $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff); + $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array( + 'code' => (string) $this->code, + 'seed' => (int) $this->seed)) . ' + WHERE + confirm_id = \'' . $db->sql_escape($this->confirm_id) . '\' AND + session_id = \'' . $db->sql_escape($user->session_id) . '\''; + $db->sql_query($sql); + } + + /** + * Look up everything we need for painting&checking. + */ + function load_code() + { + global $db, $user; + $sql = 'SELECT code, seed + FROM ' . CONFIRM_TABLE . " + WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "' + AND session_id = '" . $db->sql_escape($user->session_id) . "' + AND confirm_type = " . $this->type; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + if ($row) + { + $this->code = $row['code']; + $this->seed = $row['seed']; + return true; + } + return false; + + } + + function check_code() + { + global $db; + + if (empty($this->code)) + { + if (!$this->load_code()) + { + return false; + } + } + return (strcasecmp($this->code, $this->confirm_code) === 0); + } + + function delete_code() + { + global $db, $user; + + $sql = 'DELETE FROM ' . CONFIRM_TABLE . " + WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "' + AND session_id = '" . $db->sql_escape($user->session_id) . "' + AND confirm_type = " . $this->type; + $db->sql_query($sql); + } + + function get_attempt_count() + { + global $db, $user; + + $sql = 'SELECT COUNT(session_id) AS attempts + FROM ' . CONFIRM_TABLE . " + WHERE session_id = '" . $db->sql_escape($user->session_id) . "' + AND confirm_type = " . $this->type; + $result = $db->sql_query($sql); + $attempts = (int) $db->sql_fetchfield('attempts'); + $db->sql_freeresult($result); + + return $attempts; + } + + + function reset() + { + global $db, $user; + + $sql = 'DELETE FROM ' . CONFIRM_TABLE . " + WHERE session_id = '" . $db->sql_escape($user->session_id) . "' + AND confirm_type = " . (int) $this->type; + $db->sql_query($sql); + + // we leave the class usable by generating a new question + $this->generate_code(); + } + +} + diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php new file mode 100755 index 0000000000..850794e133 --- /dev/null +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php @@ -0,0 +1,122 @@ +<? +/** +* +* @package VC +* @version $Id: $ +* @copyright (c) 2006 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Placeholder for autoload +*/ +if (!class_exists('phpbb_default_captcha')) +{ + include_once($phpbb_root_path . "includes/captcha/plugins/captcha_abstract." . $phpEx); +} + +class phpbb_captcha_gd extends phpbb_default_captcha +{ + + function phpbb_captcha_gd() + { + global $phpbb_root_path, $phpEx; + if (!class_exists('captcha')) + { + include_once($phpbb_root_path . "includes/captcha/captcha_gd." . $phpEx); + } + } + + function get_instance() + { + return new phpbb_captcha_gd(); + } + + function is_available() + { + return (@extension_loaded('gd') || can_load_dll('gd')); + } + + function get_name() + { + return 'CAPTCHA_GD'; + } + + function get_class_name() + { + return 'phpbb_captcha_gd'; + } + + function acp_page($id, &$module) + { + global $db, $user, $auth, $template; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $user->add_lang('acp/board'); + $captcha_vars = array( + 'captcha_gd_x_grid' => 'CAPTCHA_GD_X_GRID', + 'captcha_gd_y_grid' => 'CAPTCHA_GD_Y_GRID', + 'captcha_gd_foreground_noise' => 'CAPTCHA_GD_FOREGROUND_NOISE', + 'captcha_gd' => 'CAPTCHA_GD_PREVIEWED', + 'captcha_gd_wave' => 'CAPTCHA_GD_WAVE', + 'captcha_gd_3d_noise' => 'CAPTCHA_GD_3D_NOISE', + 'captcha_gd_fonts' => 'CAPTCHA_GD_FONTS', + + ); + + $config_vars = array( + 'enable_confirm' => 'REG_ENABLE', + 'enable_post_confirm' => 'POST_ENABLE', + 'confirm_refresh' => 'CONFIRM_REFRESH', + 'captcha_gd' => 'CAPTCHA_GD', + ); + + + $module->tpl_name = 'captcha_gd_acp'; + $module->page_title = 'ACP_VC_SETTINGS'; + $form_key = 'acp_captcha'; + add_form_key($form_key); + + $submit = request_var('submit', ''); + + if ($submit && check_form_key($form_key)) + { + $captcha_vars = array_keys($captcha_vars); + foreach ($captcha_vars as $captcha_var) + { + $value = request_var($captcha_var, 0); + if ($value >= 0) + { + set_config($captcha_var, $value); + } + } + trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action)); + } + else if ($submit) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($module->u_action)); + } + else + { + foreach ($captcha_vars as $captcha_var => $template_var) + { + $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var]; + $template->assign_var($template_var, $var); + } + $template->assign_vars(array( + 'CAPTCHA_PREVIEW' => $this->get_demo_template($id), + 'CAPTCHA_NAME' => $this->get_class_name(), + )); + + } + } +} + diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php new file mode 100755 index 0000000000..769867655c --- /dev/null +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php @@ -0,0 +1,66 @@ +<?php +/** +* +* @package VC +* @version $Id$ +* @copyright (c) 2006 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Placeholder for autoload +*/ +if (!class_exists('captcha_abstract')) +{ + include_once($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); +} + +class phpbb_captcha_gd_wave extends phpbb_default_captcha +{ + + function phpbb_captcha_gd_wave() + { + global $phpbb_root_path, $phpEx; + if (!class_exists('captcha')) + { + include_once($phpbb_root_path . 'includes/captcha/captcha_gd_wave.' . $phpEx); + } + } + + function get_instance() + { + return new phpbb_captcha_gd_wave(); + } + + function is_available() + { + return (@extension_loaded('gd') || can_load_dll('gd')); + } + + function get_name() + { + return 'CAPTCHA_GD_WAVE'; + } + + function get_class_name() + { + return 'phpbb_captcha_gd_wave'; + } + + function acp_page($id, &$module) + { + global $config, $db, $template, $user; + + trigger_error($user->lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action)); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php new file mode 100755 index 0000000000..c5a32137d7 --- /dev/null +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php @@ -0,0 +1,68 @@ +<? +/** +* +* @package VC +* @version $Id: $ +* @copyright (c) 2006 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Placeholder for autoload +*/ +if (!class_exists('phpbb_default_captcha')) +{ + include_once($phpbb_root_path . "includes/captcha/plugins/captcha_abstract." . $phpEx); +} + +class phpbb_captcha_nogd extends phpbb_default_captcha +{ + + function phpbb_captcha_nogd() + { + global $phpbb_root_path, $phpEx; + if (!class_exists('captcha')) + { + include_once($phpbb_root_path . "includes/captcha/captcha_non_gd." . $phpEx); + } + } + + function get_instance() + { + return new phpbb_captcha_nogd(); + } + + function is_available() + { + return true; + } + + function get_name() + { + global $user; + + return 'CAPTCHA_NO_GD'; + } + + function get_class_name() + { + return 'phpbb_captcha_nogd'; + } + + + function acp_page($id, &$module) + { + global $user; + + trigger_error($user->lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action)); + } +} + diff --git a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php new file mode 100644 index 0000000000..7a3c406324 --- /dev/null +++ b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php @@ -0,0 +1,312 @@ +<? +/** +* +* @package VC +* @version $Id: $ +* @copyright (c) 2006 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +if (!class_exists('phpbb_default_captcha')) +{ + // we need the classic captcha code for tracking solutions and attempts + include_once($phpbb_root_path . "includes/captcha/plugins/captcha_abstract." . $phpEx); +} + +class phpbb_recaptcha extends phpbb_default_captcha +{ + var $recaptcha_server = 'http://api.recaptcha.net'; + var $recaptcha_verify_server = 'api-verify.recaptcha.net'; + var $challenge; + var $response; + + + function init($type) + { + global $config, $db, $user; + + $user->add_lang('recaptcha'); + parent::init($type); + $this->challenge = request_var('recaptcha_challenge_field', ''); + $this->response = request_var('recaptcha_response_field', ''); + } + + + function get_instance() + { + return new phpbb_recaptcha(); + } + + function is_available() + { + global $config, $user; + $user->add_lang('recaptcha'); + return (isset($config['recaptcha_pubkey']) && !empty($config['recaptcha_pubkey'])); + } + + function get_name() + { + return 'CAPTCHA_RECAPTCHA'; + } + + function get_class_name() + { + return 'phpbb_recaptcha'; + } + + function acp_page($id, &$module) + { + global $config, $db, $template, $user; + + $captcha_vars = array( + 'recaptcha_pubkey' => 'RECAPTCHA_PUBKEY', + 'recaptcha_privkey' => 'RECAPTCHA_PRIVKEY', + ); + + $module->tpl_name = 'captcha_recaptcha_acp'; + $module->page_title = 'ACP_VC_SETTINGS'; + $form_key = 'acp_captcha'; + add_form_key($form_key); + + $submit = request_var('submit', ''); + + if ($submit && check_form_key($form_key)) + { + $captcha_vars = array_keys($captcha_vars); + foreach ($captcha_vars as $captcha_var) + { + $value = request_var($captcha_var, ''); + if ($value) + { + set_config($captcha_var, $value); + } + } + trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action)); + } + else if ($submit) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($module->u_action)); + } + else + { + foreach ($captcha_vars as $captcha_var => $template_var) + { + $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, '') : ((isset($config[$captcha_var])) ? $config[$captcha_var] : ''); + $template->assign_var($template_var, $var); + } + $template->assign_vars(array( + 'CAPTCHA_PREVIEW' => $this->get_demo_template($id), + 'CAPTCHA_NAME' => $this->get_class_name(), + )); + + } + } + + + // not needed + function execute_demo() + { + } + + + // not needed + function execute() + { + } + + + function get_template() + { + global $config, $user, $template; + + $template->set_filenames(array( + 'captcha' => 'captcha_recaptcha.html') + ); + + $template->assign_vars(array( + 'RECAPTCHA_SERVER' => $this->recaptcha_server, + 'RECAPTCHA_PUBKEY' => isset($config['recaptcha_pubkey']) ? $config['recaptcha_pubkey'] : '', + 'RECAPTCHA_ERRORGET' => '', + 'S_RECAPTCHA_AVAILABLE' => $this->is_available(), + )); + + return $template->assign_display('captcha'); + } + + function get_demo_template($id) + { + return $this->get_template(); + } + + function get_hidden_fields() + { + $hidden_fields = array(); + + // this is required for postig.php - otherwise we would forget about the captcha being already solved + if ($this->solved) + { + $hidden_fields['confirm_code'] = $this->confirm_code; + } + $hidden_fields['confirm_id'] = $this->confirm_id; + return $hidden_fields; + } + + function uninstall() + { + self::garbage_collect(0); + } + + function install() + { + return; + } + + function validate() + { + if (!parent::validate()) + { + return false; + } + else + { + return $this->recaptcha_check_answer(); + } + } + + +// Code from here on is based on recaptchalib.php +/* + * This is a PHP library that handles calling reCAPTCHA. + * - Documentation and latest version + * http://recaptcha.net/plugins/php/ + * - Get a reCAPTCHA API Key + * http://recaptcha.net/api/getkey + * - Discussion group + * http://groups.google.com/group/recaptcha + * + * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net + * AUTHORS: + * Mike Crawford + * Ben Maurer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + /** + * Submits an HTTP POST to a reCAPTCHA server + * @param string $host + * @param string $path + * @param array $data + * @param int port + * @return array response + */ + function _recaptcha_http_post($host, $path, $data, $port = 80) + { + $req = $this->_recaptcha_qsencode ($data); + + $http_request = "POST $path HTTP/1.0\r\n"; + $http_request .= "Host: $host\r\n"; + $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n"; + $http_request .= "Content-Length: " . strlen($req) . "\r\n"; + $http_request .= "User-Agent: reCAPTCHA/PHP/phpBB\r\n"; + $http_request .= "\r\n"; + $http_request .= $req; + + $response = ''; + if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) { + die ('Could not open socket'); + } + + fwrite($fs, $http_request); + + while ( !feof($fs) ) + $response .= fgets($fs, 1160); // One TCP-IP packet + fclose($fs); + $response = explode("\r\n\r\n", $response, 2); + + return $response; + } + + + /** + * Calls an HTTP POST function to verify if the user's guess was correct + * @param array $extra_params an array of extra variables to post to the server + * @return ReCaptchaResponse + */ + function recaptcha_check_answer ($extra_params = array()) + { + global $config, $user; + //discard spam submissions + if ($this->challenge == null || strlen($this->challenge) == 0 || $this->response == null || strlen($this->response) == 0) + { + return $user->lang['RECAPTCHA_INCORRECT']; + } + + $response = $this->_recaptcha_http_post ($this->recaptcha_verify_server, "/verify", + array ( + 'privatekey' => $config['recaptcha_privkey'], + 'remoteip' => $user->ip, + 'challenge' => $this->challenge, + 'response' => $this->response + ) + $extra_params + ); + + $answers = explode ("\n", $response[1]); + + if (trim ($answers[0]) === 'true') + { + $this->solved = true; + return false; + } + else + { + if ($answers[1] === 'incorrect-captcha-sol') + { + return $user->lang['RECAPTCHA_INCORRECT']; + } + } + } + + /** + * Encodes the given data into a query string format + * @param $data - array of string elements to be encoded + * @return string - encoded request + */ + function _recaptcha_qsencode ($data) + { + $req = ''; + foreach ( $data as $key => $value ) + { + $req .= $key . '=' . urlencode( stripslashes($value) ) . '&'; + } + // Cut the last '&' + $req=substr($req,0,strlen($req)-1); + return $req; + } +} + diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 476565452c..58601be65b 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -2520,6 +2520,11 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa { global $db, $user, $template, $auth, $phpEx, $phpbb_root_path, $config; + if (!class_exists('phpbb_captcha_factory')) + { + include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); + } + $err = ''; // Make sure user->setup() has been called @@ -2630,34 +2635,14 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa { case LOGIN_ERROR_ATTEMPTS: - // Show confirm image - $sql = 'DELETE FROM ' . CONFIRM_TABLE . " - WHERE session_id = '" . $db->sql_escape($user->session_id) . "' - AND confirm_type = " . CONFIRM_LOGIN; - $db->sql_query($sql); - - // Generate code - $code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); - $confirm_id = md5(unique_id($user->ip)); - $seed = hexdec(substr(unique_id(), 4, 10)); + $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha->init(CONFIRM_LOGIN); + $captcha->reset(); - // compute $seed % 0x7fffffff - $seed -= 0x7fffffff * floor($seed / 0x7fffffff); - - $sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array( - 'confirm_id' => (string) $confirm_id, - 'session_id' => (string) $user->session_id, - 'confirm_type' => (int) CONFIRM_LOGIN, - 'code' => (string) $code, - 'seed' => (int) $seed) - ); - $db->sql_query($sql); $template->assign_vars(array( 'S_CONFIRM_CODE' => true, - 'CONFIRM_ID' => $confirm_id, - 'CONFIRM_IMAGE' => '<img src="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=confirm&id=' . $confirm_id . '&type=' . CONFIRM_LOGIN) . '" alt="" title="" />', - 'L_LOGIN_CONFIRM_EXPLAIN' => sprintf($user->lang['LOGIN_CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'), + 'CONFIRM' => $captcha->get_template(''), )); $err = $user->lang[$result['error_msg']]; diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php index 043a637584..e039fce6e1 100644 --- a/phpBB/includes/session.php +++ b/phpBB/includes/session.php @@ -891,7 +891,7 @@ class session */ function session_gc() { - global $db, $config; + global $db, $config, $phpbb_root_path, $phpEx; $batch_size = 10; @@ -949,40 +949,16 @@ class session WHERE last_login < ' . (time() - (86400 * (int) $config['max_autologin_time'])); $db->sql_query($sql); } - $this->confirm_gc(); - } - - return; - } - - function confirm_gc($type = 0) - { - global $db, $config; - - $sql = 'SELECT DISTINCT c.session_id - FROM ' . CONFIRM_TABLE . ' c - LEFT JOIN ' . SESSIONS_TABLE . ' s ON (c.session_id = s.session_id) - WHERE s.session_id IS NULL' . - ((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type); - $result = $db->sql_query($sql); - - if ($row = $db->sql_fetchrow($result)) - { - $sql_in = array(); - do - { - $sql_in[] = (string) $row['session_id']; - } - while ($row = $db->sql_fetchrow($result)); - - if (sizeof($sql_in)) + + // only called from CRON; should be a safe workaround until the infrastructure gets going + if (!class_exists('captcha_factory')) { - $sql = 'DELETE FROM ' . CONFIRM_TABLE . ' - WHERE ' . $db->sql_in_set('session_id', $sql_in); - $db->sql_query($sql); + include($phpbb_root_path . "includes/captcha/captcha_factory." . $phpEx); } + captcha_factory::garbage_collect($config['captcha_plugin']); } - $db->sql_freeresult($result); + + return; } diff --git a/phpBB/includes/ucp/ucp_confirm.php b/phpBB/includes/ucp/ucp_confirm.php index b91c88b7e8..445f7c7d2a 100644 --- a/phpBB/includes/ucp/ucp_confirm.php +++ b/phpBB/includes/ucp/ucp_confirm.php @@ -3,7 +3,7 @@ * * @package VC * @version $Id$ -* @copyright (c) 2005 phpBB Group +* @copyright (c) 2005 2008 phpBB Group * @license http://opensource.org/licenses/gpl-license.php GNU Public License * */ @@ -37,42 +37,10 @@ class ucp_confirm { global $db, $user, $phpbb_root_path, $config, $phpEx; - // Do we have an id? No, then just exit - $confirm_id = request_var('id', ''); - $type = request_var('type', 0); - - if (!$confirm_id || !$type) - { - exit; - } - - // Try and grab code for this id and session - $sql = 'SELECT code, seed - FROM ' . CONFIRM_TABLE . " - WHERE session_id = '" . $db->sql_escape($user->session_id) . "' - AND confirm_id = '" . $db->sql_escape($confirm_id) . "' - AND confirm_type = $type"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - // If we have a row then grab data else create a new id - if (!$row) - { - exit; - } - - if ($config['captcha_gd']) - { - include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx); - } - else - { - include($phpbb_root_path . 'includes/captcha/captcha_non_gd.' . $phpEx); - } - - $captcha = new captcha(); - $captcha->execute($row['code'], $row['seed']); + include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); + $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha->init(request_var('type', 0)); + $captcha->execute(); garbage_collection(); exit_handler(); diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index e42ad8369d..958369a03e 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -37,14 +37,12 @@ class ucp_register include($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx); - $confirm_id = request_var('confirm_id', ''); - $confirm_refresh = (isset($_POST['confirm_refresh']) && $config['confirm_refresh']) ? ((!empty($_POST['confirm_refresh'])) ? 1 : 0) : false; - $coppa = (isset($_REQUEST['coppa'])) ? ((!empty($_REQUEST['coppa'])) ? 1 : 0) : false; - $agreed = (!empty($_POST['agreed'])) ? 1 : 0; - $submit = (isset($_POST['submit'])) ? true : false; - $change_lang = request_var('change_lang', ''); - $user_lang = request_var('lang', $user->lang_name); - + $coppa = (isset($_REQUEST['coppa'])) ? ((!empty($_REQUEST['coppa'])) ? 1 : 0) : false; + $agreed = (!empty($_POST['agreed'])) ? 1 : 0; + $submit = (isset($_POST['submit'])) ? true : false; + $change_lang = request_var('change_lang', ''); + $user_lang = request_var('lang', $user->lang_name); + $confirm_refresh = (isset($_POST['confirm_refresh']) && $config['confirm_refresh']) ? ((!empty($_POST['confirm_refresh'])) ? 1 : 0) : false; if ($agreed) { add_form_key('ucp_register'); @@ -54,7 +52,14 @@ class ucp_register add_form_key('ucp_register_terms'); } - + + if ($config['enable_confirm']) + { + include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); + $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha->init(CONFIRM_REG); + } + if ($change_lang || $user_lang != $config['default_lang']) { $use_lang = ($change_lang) ? basename($change_lang) : basename($user_lang); @@ -89,8 +94,8 @@ class ucp_register { $add_lang = ($change_lang) ? '&change_lang=' . urlencode($change_lang) : ''; $add_coppa = ($coppa !== false) ? '&coppa=' . $coppa : ''; - - $s_hidden_fields = ($confirm_id) ? array('confirm_id' => $confirm_id) : array(); + + $s_hidden_fields = array(); // If we change the language, we want to pass on some more possible parameter. if ($change_lang) @@ -100,11 +105,14 @@ class ucp_register 'username' => utf8_normalize_nfc(request_var('username', '', true)), 'email' => strtolower(request_var('email', '')), 'email_confirm' => strtolower(request_var('email_confirm', '')), - 'confirm_code' => request_var('confirm_code', ''), - 'confirm_id' => request_var('confirm_id', ''), 'lang' => $user->lang_name, 'tz' => request_var('tz', (float) $config['board_timezone']), )); + + if ($config['enable_confirm']) + { + $s_hidden_fields = array_merge($s_hidden_fields, $captcha->get_hidden_fields()); + } } if ($coppa === false && $config['coppa_enable']) @@ -168,7 +176,6 @@ class ucp_register 'password_confirm' => request_var('password_confirm', '', true), 'email' => strtolower(request_var('email', '')), 'email_confirm' => strtolower(request_var('email_confirm', '')), - 'confirm_code' => request_var('confirm_code', ''), 'lang' => basename(request_var('lang', $user->lang_name)), 'tz' => request_var('tz', (float) $timezone), ); @@ -188,7 +195,6 @@ class ucp_register array('string', false, 6, 60), array('email')), 'email_confirm' => array('string', false, 6, 60), - 'confirm_code' => array('string', !$config['enable_confirm'], CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS), 'tz' => array('num', false, -14, 14), 'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'), )); @@ -199,6 +205,22 @@ class ucp_register // Replace "error" strings with their real, localised form $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + if ($config['enable_confirm']) + { + $vc_response = $captcha->validate(); + if ($vc_response) + { + $error[] = $vc_response; + } + else + { + $captcha->reset(); + } + if ($config['max_reg_attempts'] && $captcha->get_attempt_count() > $config['max_reg_attempts']) + { + $error[] = $user->lang['TOO_MANY_REGISTERS']; + } + } // DNSBL check if ($config['check_dnsbl']) { @@ -211,50 +233,6 @@ class ucp_register // validate custom profile fields $cp->submit_cp_field('register', $user->get_iso_lang_id(), $cp_data, $error); - // Visual Confirmation handling - $wrong_confirm = false; - if ($config['enable_confirm']) - { - if (!$confirm_id) - { - $error[] = $user->lang['CONFIRM_CODE_WRONG']; - $wrong_confirm = true; - } - else - { - $sql = 'SELECT code - FROM ' . CONFIRM_TABLE . " - WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "' - AND session_id = '" . $db->sql_escape($user->session_id) . "' - AND confirm_type = " . CONFIRM_REG; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($row) - { - if (strcasecmp($row['code'], $data['confirm_code']) === 0) - { - $sql = 'DELETE FROM ' . CONFIRM_TABLE . " - WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "' - AND session_id = '" . $db->sql_escape($user->session_id) . "' - AND confirm_type = " . CONFIRM_REG; - $db->sql_query($sql); - } - else - { - $error[] = $user->lang['CONFIRM_CODE_WRONG']; - $wrong_confirm = true; - } - } - else - { - $error[] = $user->lang['CONFIRM_CODE_WRONG']; - $wrong_confirm = true; - } - } - } - if (!sizeof($error)) { if ($data['new_password'] != $data['password_confirm']) @@ -452,74 +430,17 @@ class ucp_register if ($change_lang || $confirm_refresh) { $str = '&change_lang=' . $change_lang; - $sql = 'SELECT code - FROM ' . CONFIRM_TABLE . " - WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "' - AND session_id = '" . $db->sql_escape($user->session_id) . "' - AND confirm_type = " . CONFIRM_REG; - $result = $db->sql_query($sql); - if (!$row = $db->sql_fetchrow($result)) - { - $confirm_id = ''; - } - $db->sql_freeresult($result); } else { $str = ''; - } - if (!$change_lang || !$confirm_id || !$confirm_refresh) - { - $user->confirm_gc(CONFIRM_REG); - $sql = 'SELECT COUNT(session_id) AS attempts - FROM ' . CONFIRM_TABLE . " - WHERE session_id = '" . $db->sql_escape($user->session_id) . "' - AND confirm_type = " . CONFIRM_REG; - $result = $db->sql_query($sql); - $attempts = (int) $db->sql_fetchfield('attempts'); - $db->sql_freeresult($result); - - if ($config['max_reg_attempts'] && $attempts > $config['max_reg_attempts']) - { - trigger_error('TOO_MANY_REGISTERS'); - } - - $code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); - $confirm_id = md5(unique_id($user->ip)); - $seed = hexdec(substr(unique_id(), 4, 10)); - - // compute $seed % 0x7fffffff - $seed -= 0x7fffffff * floor($seed / 0x7fffffff); - - $sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array( - 'confirm_id' => (string) $confirm_id, - 'session_id' => (string) $user->session_id, - 'confirm_type' => (int) CONFIRM_REG, - 'code' => (string) $code, - 'seed' => (int) $seed) - ); - $db->sql_query($sql); - } - else if ($confirm_refresh) - { - $code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); - $confirm_id = md5(unique_id($user->ip)); - $seed = hexdec(substr(unique_id(), 4, 10)); - // compute $seed % 0x7fffffff - $seed -= 0x7fffffff * floor($seed / 0x7fffffff); - $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array( - 'confirm_type' => (int) CONFIRM_REG, - 'code' => (string) $code, - 'seed' => (int) $seed)) . " - WHERE - confirm_id = '" . $db->sql_escape($confirm_id) . "' AND - session_id = '" . $db->sql_escape($session_id) . "' AND - confirm_type = " . (int) CONFIRM_REG; - $db->sql_query($sql); } - $confirm_image = '<img src="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=confirm&id=' . $confirm_id . '&type=' . CONFIRM_REG . $str) . '" alt="" title="" />'; - $s_hidden_fields .= '<input type="hidden" name="confirm_id" value="' . $confirm_id . '" />'; + $template->assign_vars(array( + 'L_CONFIRM_EXPLAIN' => sprintf($user->lang['CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'), + 'S_CAPTCHA' => $captcha->get_template(), + )); + } // @@ -534,7 +455,7 @@ class ucp_register $l_reg_cond = $user->lang['UCP_ADMIN_ACTIVATE']; break; } - + $template->assign_vars(array( 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', 'USERNAME' => $data['username'], @@ -542,16 +463,13 @@ class ucp_register 'PASSWORD_CONFIRM' => $data['password_confirm'], 'EMAIL' => $data['email'], 'EMAIL_CONFIRM' => $data['email_confirm'], - 'CONFIRM_IMG' => $confirm_image, - 'L_CONFIRM_EXPLAIN' => sprintf($user->lang['CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'), 'L_REG_COND' => $l_reg_cond, 'L_USERNAME_EXPLAIN' => sprintf($user->lang[$config['allow_name_chars'] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']), 'L_PASSWORD_EXPLAIN' => sprintf($user->lang[$config['pass_complex'] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']), 'S_LANG_OPTIONS' => language_select($data['lang']), 'S_TZ_OPTIONS' => tz_select($data['tz']), - 'S_CONFIRM_CODE' => ($config['enable_confirm']) ? true : false, 'S_CONFIRM_REFRESH' => ($config['enable_confirm'] && $config['confirm_refresh']) ? true : false, 'S_COPPA' => $coppa, 'S_HIDDEN_FIELDS' => $s_hidden_fields, |