diff options
author | Henry Sudhof <kellanved@phpbb.com> | 2008-09-19 13:17:30 +0000 |
---|---|---|
committer | Henry Sudhof <kellanved@phpbb.com> | 2008-09-19 13:17:30 +0000 |
commit | 461be11e8d0f5d4bd879cf95bd1472dbe985e0b6 (patch) | |
tree | d170e1a09d717a49bf676ef1f2ed9edbfa1be0db /phpBB | |
parent | 5349280538df70d63c5e6f91e7f4e6ecad01d23d (diff) | |
download | forums-461be11e8d0f5d4bd879cf95bd1472dbe985e0b6.tar forums-461be11e8d0f5d4bd879cf95bd1472dbe985e0b6.tar.gz forums-461be11e8d0f5d4bd879cf95bd1472dbe985e0b6.tar.bz2 forums-461be11e8d0f5d4bd879cf95bd1472dbe985e0b6.tar.xz forums-461be11e8d0f5d4bd879cf95bd1472dbe985e0b6.zip |
Okay, that is pretty raw, but better to have it in place than trying to play catch-up. Introducing an early stage of CAPTCHA modules.
git-svn-id: file:///svn/phpbb/trunk@8889 89ea8834-ac86-4346-8a33-228a782c2dd0
Diffstat (limited to 'phpBB')
23 files changed, 927 insertions, 405 deletions
diff --git a/phpBB/adm/style/acp_captcha.html b/phpBB/adm/style/acp_captcha.html index d9d087d6ba..5d04938778 100644 --- a/phpBB/adm/style/acp_captcha.html +++ b/phpBB/adm/style/acp_captcha.html @@ -22,47 +22,34 @@ <dd><label><input type="radio" class="radio" id="enable_post_confirm" name="enable_post_confirm" value="1"<!-- IF POST_ENABLE --> checked="checked"<!-- ENDIF --> /> {L_ENABLED}</label> <label><input type="radio" class="radio" name="enable_post_confirm" value="0"<!-- IF not POST_ENABLE --> checked="checked"<!-- ENDIF --> /> {L_DISABLED}</label></dd> </dl> -<!-- IF GD --> -<dl> - <dt><label for="captcha_gd">{L_CAPTCHA_GD}:</label><br /><span>{L_CAPTCHA_GD_EXPLAIN}</span></dt> - <dd><label><input id="captcha_gd" name="captcha_gd" value="1" class="radio" type="radio"<!-- IF CAPTCHA_GD --> checked="checked"<!-- ENDIF --> /> {L_YES}</label> - <label><input name="captcha_gd" value="0" class="radio" type="radio"<!-- IF not CAPTCHA_GD --> checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd> -</dl> -<dl> - <dt><label for="captcha_gd_foreground_noise">{L_CAPTCHA_GD_FOREGROUND_NOISE}:</label><br /><span>{L_CAPTCHA_GD_FOREGROUND_NOISE_EXPLAIN}</span></dt> - <dd><label><input id="captcha_gd_foreground_noise" name="captcha_gd_foreground_noise" value="1" class="radio" type="radio"<!-- IF CAPTCHA_GD_FOREGROUND_NOISE --> checked="checked"<!-- ENDIF --> /> {L_YES}</label> - <label><input name="captcha_gd_foreground_noise" value="0" class="radio" type="radio"<!-- IF not CAPTCHA_GD_FOREGROUND_NOISE --> checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd> -</dl> + +</fieldset> + +<fieldset> +<legend>{L_AVAILABLE_CAPTCHAS}</legend> + <dl> - <dt><label for="captcha_gd_x_grid">{L_CAPTCHA_GD_X_GRID}:</label><br /><span>{L_CAPTCHA_GD_X_GRID_EXPLAIN}</span></dt> - <dd><input id="captcha_gd_x_grid" name="captcha_gd_x_grid" value="{CAPTCHA_GD_X_GRID}" type="text" /></dd> + <dt><label for="captcha_select">{L_CAPTCHA_SELECT}:</label><br /><span>{L_CAPTCHA_SELECT_EXPLAIN}</span></dt> + <dd><select id="captcha_select" name="select_captcha" onchange="(document.getElementById('acp_captcha')).submit()" >{CAPTCHA_SELECT}</select></dd> </dl> <dl> - <dt><label for="captcha_gd_y_grid">{L_CAPTCHA_GD_Y_GRID}:</label><br /><span>{L_CAPTCHA_GD_Y_GRID_EXPLAIN}</span></dt> - <dd><input id="captcha_gd_y_grid" name="captcha_gd_y_grid" value="{CAPTCHA_GD_Y_GRID}" type="text" /></dd> + <dt><label for="configure">{L_CAPTCHA_CONFIGURE}:</label><br /><span>{L_CAPTCHA_CONFIGURE_EXPLAIN}</span></dt> + <dd><input class="button2" type="submit" id="configure" name="configure" value="{L_CONFIGURE}" /></dd> </dl> -<!-- ENDIF --> - + </fieldset> + +<!-- IF CAPTCHA_PREVIEW --> <fieldset> <legend>{L_PREVIEW}</legend> -<!-- IF PREVIEW --> - <div class="successbox"> - <h3>{L_WARNING}</h3> - <p>{L_CAPTCHA_PREVIEW_MSG}</p> - </div> -<!-- ENDIF --> -<dl> - <dt><label for="captcha_preview">{L_PREVIEW}:</label><br /><span>{L_CAPTCHA_PREVIEW_EXPLAIN}</span></dt> - <dd><img src="{CAPTCHA_PREVIEW}" alt="{L_PREVIEW}" <!-- IF CAPTCHA_GD_PREVIEWED -->width="360" height="96"<!-- ELSE --> width="320" height="50"<!-- ENDIF --> id="captcha_preview" /></dd> -</dl> +{CAPTCHA_PREVIEW} </fieldset> +<!-- ENDIF --> <fieldset class="submit-buttons"> <legend>{L_SUBMIT}</legend> - <input class="button1" type="submit" id="submit" name="submit" value="{L_SUBMIT}" /> - <input class="button2" type="reset" id="reset" name="reset" value="{L_RESET}" /> - <input class="button2" type="submit" id="preview" name="preview" value="{L_PREVIEW}" /> + <input class="button1" type="submit" id="main_submit" name="main_submit" value="{L_SUBMIT}" /> + <input class="button2" type="reset" id="form_reset" name="reset" value="{L_RESET}" /> {S_FORM_TOKEN} </fieldset> </form> diff --git a/phpBB/adm/style/captcha_default_acp_demo.html b/phpBB/adm/style/captcha_default_acp_demo.html new file mode 100755 index 0000000000..a714386e51 --- /dev/null +++ b/phpBB/adm/style/captcha_default_acp_demo.html @@ -0,0 +1,5 @@ + +<dl> + <dt><label for="captcha_preview">{L_PREVIEW}:</label><br /><span>{L_CAPTCHA_PREVIEW_EXPLAIN}</span></dt> + <dd><img src="{CONFIRM_IMAGE}" alt="{L_PREVIEW}" width="360" height="96" id="captcha_preview" /></dd> +</dl>
\ No newline at end of file diff --git a/phpBB/adm/style/captcha_gd_acp.html b/phpBB/adm/style/captcha_gd_acp.html new file mode 100755 index 0000000000..ff1500e7d0 --- /dev/null +++ b/phpBB/adm/style/captcha_gd_acp.html @@ -0,0 +1,53 @@ +<!-- INCLUDE overall_header.html --> + +<a name="maincontent"></a> + +<h1>{L_ACP_VC_SETTINGS}</h1> + +<p>{L_ACP_VC_SETTINGS_EXPLAIN}</p> + + +<form id="acp_captcha" method="post" action="{U_ACTION}"> + +<fieldset> +<legend>{L_GENERAL_OPTIONS}</legend> + +<dl> + <dt><label for="captcha_gd_foreground_noise">{L_CAPTCHA_GD_FOREGROUND_NOISE}:</label><br /><span>{L_CAPTCHA_GD_FOREGROUND_NOISE_EXPLAIN}</span></dt> + <dd><label><input id="captcha_gd_foreground_noise" name="captcha_gd_foreground_noise" value="1" class="radio" type="radio"<!-- IF CAPTCHA_GD_FOREGROUND_NOISE --> checked="checked"<!-- ENDIF --> /> {L_YES}</label> + <label><input name="captcha_gd_foreground_noise" value="0" class="radio" type="radio"<!-- IF not CAPTCHA_GD_FOREGROUND_NOISE --> checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd> +</dl> +<dl> + <dt><label for="captcha_gd_x_grid">{L_CAPTCHA_GD_X_GRID}:</label><br /><span>{L_CAPTCHA_GD_X_GRID_EXPLAIN}</span></dt> + <dd><input id="captcha_gd_x_grid" name="captcha_gd_x_grid" value="{CAPTCHA_GD_X_GRID}" type="text" /></dd> +</dl> +<dl> + <dt><label for="captcha_gd_y_grid">{L_CAPTCHA_GD_Y_GRID}:</label><br /><span>{L_CAPTCHA_GD_Y_GRID_EXPLAIN}</span></dt> + <dd><input id="captcha_gd_y_grid" name="captcha_gd_y_grid" value="{CAPTCHA_GD_Y_GRID}" type="text" /></dd> +</dl> + + +</fieldset> +<fieldset> + <legend>{L_PREVIEW}</legend> +<!-- IF PREVIEW --> + <div class="successbox"> + <h3>{L_WARNING}</h3> + <p>{L_CAPTCHA_PREVIEW_MSG}</p> + </div> +<!-- ENDIF --> +{CAPTCHA_PREVIEW} +</fieldset> + +<fieldset class="submit-buttons"> + <legend>{L_SUBMIT}</legend> + <input class="button1" type="submit" id="submit" name="submit" value="{L_SUBMIT}" /> + <input class="button2" type="reset" id="reset" name="reset" value="{L_RESET}" /> + <input type="hidden" name="select_captcha" value="{CAPTCHA_NAME}" /> + <input type="hidden" name="configure" value="1" /> + + {S_FORM_TOKEN} +</fieldset> +</form> + +<!-- INCLUDE overall_footer.html --> diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php index e61b8c2170..57de03c4c9 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,94 +30,115 @@ class acp_captcha $user->add_lang('acp/board'); + include(PHPBB_ROOT_PATH . 'includes/captcha/captcha_factory.' . PHP_EXT); - $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' - ); - - 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.' . PHP_EXT); - } - else - { - include(PHPBB_ROOT_PATH . 'includes/captcha/captcha_non_gd.' . PHP_EXT); - } - captcha::execute(gen_rand_string(mt_rand(5, 8)), time()); - exit; + $this->deliver_demo($selected); + } + + // Delegate + if ($configure) + { + $config_captcha = phpbb_captcha_factory::get_instance($selected); + $config_captcha->acp_page($id, $this); } + else + { + $captchas = phpbb_captcha_factory::get_captcha_types(); - $config_vars = array( - 'enable_confirm' => 'REG_ENABLE', - 'enable_post_confirm' => 'POST_ENABLE', - 'captcha_gd' => 'CAPTCHA_GD', - ); + $config_vars = array( + 'enable_confirm' => 'REG_ENABLE', + 'enable_post_confirm' => 'POST_ENABLE', + ); - $this->tpl_name = 'acp_captcha'; - $this->page_title = 'ACP_VC_SETTINGS'; - $form_key = 'acp_captcha'; - add_form_key($form_key); + $this->tpl_name = 'acp_captcha'; + $this->page_title = 'ACP_VC_SETTINGS'; + $form_key = 'acp_captcha'; + add_form_key($form_key); - $submit = request_var('submit', ''); + $submit = request_var('main_submit', false); - if ($submit && check_form_key($form_key)) - { - $config_vars = array_keys($config_vars); - foreach ($config_vars as $config_var) - { - set_config($config_var, request_var($config_var, '')); - } - $captcha_vars = array_keys($captcha_vars); - 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(); + } + 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)); } - 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.' . PHP_EXT, "i=$id&demo=demo")); - if (@extension_loaded('gd')) - { - $template->assign_var('GD', true); - } - foreach ($config_vars as $config_var => $template_var) + else if ($submit) { - $template->assign_var($template_var, (isset($_REQUEST[$config_var])) ? request_var($config_var, '') : $config[$config_var]) ; + trigger_error($user->lang['FORM_INVALID'] . adm_back_link()); } - foreach ($captcha_vars as $captcha_var => $template_var) + else { - $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; - } - $template->assign_vars(array( - 'CAPTCHA_PREVIEW' => $preview_image_src, - 'PREVIEW' => isset($_POST['preview']), - )); + $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) + { + $captcha_select .= '<option value="' . $value . '"' . $current . ' class="disabled-option" >' . $user->lang[$title] . '</option>'; + } + + $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, + )); + } + } } + + + /** + * 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 fa99a2fe4c..402f22f827 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..dfbe605917 --- /dev/null +++ b/phpBB/includes/captcha/captcha_factory.php @@ -0,0 +1,90 @@ +<? +/** +* +* @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; +} + +if (!interface_exists('phpbb_captcha_plugin')) +{ + include(PHPBB_ROOT_PATH . "includes/captcha/captcha_plugin." . PHP_EXT); +} + +/** A small class until we get the autoloader done */ +class phpbb_captcha_factory +{ + /** + * return an instance of class $name in file $name_plugin.php + */ + public static function get_instance($name) + { + $name = basename($name); + if (!class_exists($name)) + { + include(PHPBB_ROOT_PATH . "includes/captcha/plugins/{$name}_plugin." . PHP_EXT); + } + return call_user_func(array($name, 'get_instance')); + } + + /** + * Call the garbage collector + */ + public static function garbage_collect($name) + { + $name = basename($name); + if (!class_exists($name)) + { + include(PHPBB_ROOT_PATH . "includes/captcha/plugins/{$name}_plugin." . PHP_EXT); + } + call_user_func(array($name, 'garbage_collect'), 0); + } + + /** + * return a list of all discovered CAPTCHA plugins + */ + public static function get_captcha_types() + { + $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\.' . PHP_EXT . '$#', $file))) + { + $name = preg_replace('#^(.*?)_plugin\.' . PHP_EXT . '$#', '\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_non_gd.php b/phpBB/includes/captcha/captcha_non_gd.php index 24452aca26..3f9db24f3a 100644 --- a/phpBB/includes/captcha/captcha_non_gd.php +++ b/phpBB/includes/captcha/captcha_non_gd.php @@ -85,7 +85,7 @@ class captcha } else { - for ($j = 0; $j < $this->width; $j++) + for ($j = 0; $j < self::width; $j++) { $image .= chr(mt_rand(140, 255)); } @@ -93,7 +93,7 @@ class captcha } unset($hold_chars); - $image = self::create_png($image, $this->width, $this->height); + $image = self::create_png($image, self::width, self::height); // Output image header('Content-Type: image/png'); @@ -149,7 +149,7 @@ class captcha * png because it's a fully recognised open standard and supported * by practically all modern browsers and OSs */ - function create_png($raw_image, $width, $height) + static function create_png($raw_image, $width, $height) { // SIG $image = pack('C8', 137, 80, 78, 71, 13, 10, 26, 10); 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..a1a56db1e1 --- /dev/null +++ b/phpBB/includes/captcha/plugins/captcha_abstract.php @@ -0,0 +1,301 @@ +<? +/** +* +* @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. +*/ +abstract class phpbb_default_captcha implements phpbb_captcha_plugin +{ + protected $confirm_id; + protected $confirm_code; + protected $code; + protected $seed; + protected $type; + protected $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', ''); + $this->type = (int) $type; + + if (!strlen($this->confirm_id)) + { + // we have no confirm ID, better get ready to display something + $this->generate_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::execute($this->code, $this->seed); + } + + + function execute() + { + if (empty($this->code)) + { + if (!$this->load_code()) + { + // invalid request, bail out + return false; + } + } + captcha::execute($this->code, $this->seed); + } + + + function get_template() + { + global $config, $user, $template; + + $template->set_filenames(array( + 'captcha' => 'captcha_default.html') + ); + + $template->assign_vars(array( + 'CONFIRM_IMAGE' => append_sid('ucp', 'mode=confirm&confirm_id=' . $this->confirm_id . '&type=' . $this->type), + 'CONFIRM_ID' => $this->confirm_id, + )); + + return $template->assign_display('captcha'); + } + + function get_demo_template($id) + { + global $config, $user, $template; + + $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.' . PHP_EXT, '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; + } + + static 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->reset(); + return $error; + } + else + { + return false; + } + } + + + /** + * The old way to generate code, suitable for GD and non-GD. Resets the internal state. + */ + protected 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); + } + + /** + * Look up everything we need for painting&checking. + */ + protected 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; + + } + + protected function check_code() + { + global $db; + + if (empty($this->code)) + { + if (!$this->load_code()) + { + return false; + } + } + return (strcasecmp($this->code, $this->confirm_code) === 0); + } + + protected 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..e4f0bff87e --- /dev/null +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php @@ -0,0 +1,101 @@ +<? +/** +* +* @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 +*/ +include_once(PHPBB_ROOT_PATH . "includes/captcha/plugins/captcha_abstract." . PHP_EXT); + +class phpbb_captcha_gd extends phpbb_default_captcha implements phpbb_captcha_plugin +{ + + function __construct() + { + include_once(PHPBB_ROOT_PATH . "includes/captcha/captcha_gd." . PHP_EXT); + } + + public static function get_instance() + { + return new phpbb_captcha_gd(); + } + + static function is_available() + { + return (@extension_loaded('gd') || can_load_dll('gd')); + } + + static function get_name() + { + return 'CAPTCHA_GD'; + } + + static function get_class_name() + { + return 'phpbb_captcha_gd'; + } + + function acp_page($id, &$module) + { + global $config, $db, $template, $user; + + $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' + ); + + $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_nogd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php new file mode 100755 index 0000000000..a2521a330e --- /dev/null +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php @@ -0,0 +1,58 @@ +<? +/** +* +* @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; +} + +include_once(PHPBB_ROOT_PATH . "includes/captcha/plugins/captcha_abstract." . PHP_EXT); + +class phpbb_captcha_nogd extends phpbb_default_captcha implements phpbb_captcha_plugin +{ + + function __construct() + { + include_once(PHPBB_ROOT_PATH . "includes/captcha/captcha_non_gd." . PHP_EXT); + } + + public static function get_instance() + { + return new phpbb_captcha_nogd(); + } + + static function is_available() + { + return true; + } + + static function get_name() + { + global $user; + + return 'CAPTCHA_NO_GD'; + } + + static 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/functions.php b/phpBB/includes/functions.php index 8fef702ab1..734a9716c8 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -2365,6 +2365,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa { global $db, $user, $template, $auth, $config; + include(PHPBB_ROOT_PATH . 'includes/captcha/captcha_factory.' . PHP_EXT); $err = ''; @@ -2483,34 +2484,13 @@ 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(5, 8)); - $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_LOGIN, - 'code' => (string) $code, - 'seed' => (int) $seed) - ); - $db->sql_query($sql); + $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha->init(CONFIRM_LOGIN); + $captcha->reset(); $template->assign_vars(array( 'S_CONFIRM_CODE' => true, - 'CONFIRM_ID' => $confirm_id, - 'CONFIRM_IMAGE' => '<img src="' . append_sid('ucp', '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 b5f2a9b6a1..450f044414 100644 --- a/phpBB/includes/session.php +++ b/phpBB/includes/session.php @@ -923,40 +923,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 + + // only called from CRON; should be a safe workaround until the infrastructure gets going + if (!class_exists('captcha_factory')) { - $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); + include(PHPBB_ROOT_PATH . "includes/captcha/captcha_factory." . PHP_EXT); } + 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 94fb9a729f..26ffc3c5fb 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 * */ @@ -36,43 +36,10 @@ class ucp_confirm function main($id, $mode) { global $db, $user, $config; - - // 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.' . PHP_EXT); - } - else - { - include(PHPBB_ROOT_PATH . 'includes/captcha/captcha_non_gd.' . PHP_EXT); - } - - captcha::execute($row['code'], $row['seed']); - + include(PHPBB_ROOT_PATH . 'includes/captcha/captcha_factory.' . PHP_EXT); + $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 0246e96061..c0ebd5f2c5 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -37,7 +37,6 @@ class ucp_register include(PHPBB_ROOT_PATH . 'includes/functions_profile_fields.' . PHP_EXT); - $confirm_id = request_var('confirm_id', ''); $coppa = (isset($_REQUEST['coppa'])) ? ((!empty($_REQUEST['coppa'])) ? 1 : 0) : false; $agreed = (!empty($_POST['agreed'])) ? 1 : 0; $submit = (isset($_POST['submit'])) ? true : false; @@ -53,7 +52,14 @@ class ucp_register add_form_key('ucp_register_terms'); } - + + if ($config['enable_confirm']) + { + include(PHPBB_ROOT_PATH . 'includes/captcha/captcha_factory.' . PHP_EXT); + $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); @@ -88,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) @@ -99,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']) @@ -167,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), ); @@ -187,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'], 5, 8), 'tz' => array('num', false, -14, 14), 'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'), )); @@ -198,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']) { @@ -210,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']) @@ -451,57 +430,16 @@ class ucp_register if ($change_lang) { $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) - { - $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(5, 8)); - $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); - } - $confirm_image = '<img src="' . append_sid('ucp', '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(), + )); } // @@ -516,7 +454,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'], @@ -524,16 +462,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_COPPA' => $coppa, 'S_HIDDEN_FIELDS' => $s_hidden_fields, 'S_UCP_ACTION' => append_sid('ucp', 'mode=register'), diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index 1c3f490ccb..3b0fdc5011 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -1387,8 +1387,8 @@ class install_install extends module if (@extension_loaded('gd') || can_load_dll('gd')) { $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config - SET config_value = '1' - WHERE config_name = 'captcha_gd'"; + SET config_value = 'phpbb_captcha_gd' + WHERE config_name = 'captcha_plugin'"; } // We set a (semi-)unique cookie name to bypass login issues related to the cookie name. diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index aa9740e8ac..a6d0c328a7 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -60,7 +60,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('browser_check', '1 INSERT INTO phpbb_config (config_name, config_value) VALUES ('bump_interval', '10'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('bump_type', 'd'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('cache_gc', '7200'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_plugin', 'phpbb_captcha_nogd'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_foreground_noise', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_x_grid', '25'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_y_grid', '25'); diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index 81d2504a1c..e61f04904b 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -230,8 +230,9 @@ $lang = array_merge($lang, array( // Visual Confirmation Settings $lang = array_merge($lang, array( - 'ACP_VC_SETTINGS_EXPLAIN' => 'Here you are able to define visual confirmation defaults and CAPTCHA settings.', - + 'ACP_VC_SETTINGS_EXPLAIN' => 'Here you are able to define visual confirmation defaults and CAPTCHA settings.', + 'AVAILABLE_CAPTCHAS' => 'Available plugins', + 'CAPTCHA_UNAVAILABLE' => 'The CAPTCHA cannot be selected as its requirements are not met.', 'CAPTCHA_GD' => 'GD CAPTCHA', 'CAPTCHA_GD_FOREGROUND_NOISE' => 'GD CAPTCHA foreground noise', 'CAPTCHA_GD_EXPLAIN' => 'Use GD to make a more advanced CAPTCHA.', @@ -241,8 +242,17 @@ $lang = array_merge($lang, array( 'CAPTCHA_GD_Y_GRID' => 'GD CAPTCHA background noise y-axis', 'CAPTCHA_GD_Y_GRID_EXPLAIN' => 'Use lower settings of this to make the GD based CAPTCHA harder. 0 will disable y-axis background noise.', + 'CAPTCHA_NO_GD' => 'CAPTCHA without GD', + 'CAPTCHA_PREVIEW_MSG' => 'Your changes to the visual confirmation setting were not saved. This is just a preview.', - 'CAPTCHA_PREVIEW_EXPLAIN' => 'The CAPTCHA as it will look like using the current settings. Use the preview button to refresh. Note that captchas are randomized and will differ from one view to the next.', + 'CAPTCHA_PREVIEW_EXPLAIN' => 'The CAPTCHA as it would look like using the current selection.', + + 'CAPTCHA_SELECT' => 'Installed CAPTCHA plugins', + 'CAPTCHA_SELECT_EXPLAIN' => 'The dropdown holds the CAPTCHA plugins recognized by the board. Gray entries are not available right now and might need configuration prior to use.', + 'CAPTCHA_CONFIGURE' => 'Configure CAPTCHAs', + 'CAPTCHA_CONFIGURE_EXPLAIN' => 'Change the settings for the selected CAPTCHA.', + 'CONFIGURE' => 'Configure', + 'CAPTCHA_NO_OPTIONS' => 'This CAPTCHA has no configuration options.', 'VISUAL_CONFIRM_POST' => 'Enable visual confirmation for guest postings', 'VISUAL_CONFIRM_POST_EXPLAIN' => 'Requires anonymous users to enter a random code matching an image to help prevent mass postings.', 'VISUAL_CONFIRM_REG' => 'Enable visual confirmation for registrations', diff --git a/phpBB/posting.php b/phpBB/posting.php index 947d34925e..d1e6684152 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -45,7 +45,13 @@ $mode = ($delete && !$preview && !$refresh && $submit) ? 'delete' : request_var $error = $post_data = array(); $current_time = time(); - +if ($config['enable_post_confirm'] && !$user->data['is_registered']) +{ + include(PHPBB_ROOT_PATH . 'includes/captcha/captcha_factory.' . PHP_EXT); + $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha->init(CONFIRM_POST); +} + // Was cancel pressed? If so then redirect to the appropriate page if ($cancel || ($current_time - $lastclick < 2 && $submit)) { @@ -741,21 +747,10 @@ if ($submit || $preview || $refresh) if ($config['enable_post_confirm'] && !$user->data['is_registered'] && in_array($mode, array('quote', 'post', 'reply'))) { - $confirm_id = request_var('confirm_id', ''); - $confirm_code = request_var('confirm_code', ''); - - $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_POST; - $result = $db->sql_query($sql); - $confirm_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (empty($confirm_row['code']) || strcasecmp($confirm_row['code'], $confirm_code) !== 0) + $vc_response = $captcha->validate(); + if ($vc_response) { - $error[] = $user->lang['CONFIRM_CODE_WRONG']; + $error += $vc_response; } else { @@ -999,7 +994,10 @@ if ($submit || $preview || $refresh) } $redirect_url = submit_post($mode, $post_data['post_subject'], $post_data['username'], $post_data['topic_type'], $poll, $data, $update_message); - + if ($config['enable_post_confirm'] && !$user->data['is_registered'] && in_array($mode, array('quote', 'post', 'reply'))) + { + $captcha->reset(); + } // Check the permissions for post approval, as well as the queue trigger where users are put on approval with a post count lower than specified. Moderators are not affected. if (($config['enable_queue_trigger'] && $user->data['user_posts'] < $config['queue_trigger_posts'] && !$auth->acl_get('m_approve', $data['forum_id'])) || !$auth->acl_get('f_noapprove', $data['forum_id'])) { @@ -1220,34 +1218,11 @@ generate_forum_rules($post_data); if ($config['enable_post_confirm'] && !$user->data['is_registered'] && $solved_captcha === false && ($mode == 'post' || $mode == 'reply' || $mode == 'quote')) { - // Show confirm image - $sql = 'DELETE FROM ' . CONFIRM_TABLE . " - WHERE session_id = '" . $db->sql_escape($user->session_id) . "' - AND confirm_type = " . CONFIRM_POST; - $db->sql_query($sql); - - // Generate code - $code = gen_rand_string(mt_rand(5, 8)); - $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_POST, - 'code' => (string) $code, - 'seed' => (int) $seed) - ); - $db->sql_query($sql); + $captcha->reset(); $template->assign_vars(array( 'S_CONFIRM_CODE' => true, - 'CONFIRM_ID' => $confirm_id, - 'CONFIRM_IMAGE' => '<img src="' . append_sid('ucp', 'mode=confirm&id=' . $confirm_id . '&type=' . CONFIRM_POST) . '" alt="" title="" />', - 'L_POST_CONFIRM_EXPLAIN' => sprintf($user->lang['POST_CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'), + 'CONFIRM' => $captcha->get_template(), )); } @@ -1258,10 +1233,7 @@ $s_hidden_fields .= ($draft_id || isset($_REQUEST['draft_loaded'])) ? '<input ty // Add the confirm id/code pair to the hidden fields, else an error is displayed on next submit/preview if ($solved_captcha !== false) { - $s_hidden_fields .= build_hidden_fields(array( - 'confirm_id' => request_var('confirm_id', ''), - 'confirm_code' => request_var('confirm_code', '')) - ); + $s_hidden_fields .= build_hidden_fields($captcha->get_hidden_fields()); } $form_enctype = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || !$config['allow_attachments'] || !$auth->acl_get('u_attach') || !$auth->acl_get('f_attach', $forum_id)) ? '' : ' enctype="multipart/form-data"'; diff --git a/phpBB/styles/prosilver/template/captcha_default.html b/phpBB/styles/prosilver/template/captcha_default.html new file mode 100755 index 0000000000..2cfc41338d --- /dev/null +++ b/phpBB/styles/prosilver/template/captcha_default.html @@ -0,0 +1,8 @@ + + <dl> + <dt><label for="confirm_code">{L_CONFIRM_CODE}:</label></dt> + <dd><img src="{CONFIRM_IMAGE}" alt="" /></dd> + <dd><input type="text" name="confirm_code" id="confirm_code" size="8" maxlength="8" class="inputbox narrow" title="{L_CONFIRM_CODE}" /> + <input type="hidden" name="confirm_id" id="confirm_id" value="{CONFIRM_ID}" /></dd> + <dd>{L_CONFIRM_CODE_EXPLAIN}</dd> + </dl>
\ No newline at end of file diff --git a/phpBB/styles/prosilver/template/login_body.html b/phpBB/styles/prosilver/template/login_body.html index ac7ada28c9..a32c2d1e42 100644 --- a/phpBB/styles/prosilver/template/login_body.html +++ b/phpBB/styles/prosilver/template/login_body.html @@ -21,21 +21,16 @@ <!-- IF U_RESEND_ACTIVATION --><dd><a href="{U_RESEND_ACTIVATION}">{L_RESEND_ACTIVATION}</a></dd><!-- ENDIF --> <!-- ENDIF --> </dl> - <!-- IF S_CONFIRM_CODE --> - <dl> - <dt><label for="confirm_code">{L_CONFIRM_CODE}:</label><br /><span>{L_CONFIRM_CODE_EXPLAIN}</span></dt> - <dd><input type="hidden" name="confirm_id" value="{CONFIRM_ID}" />{CONFIRM_IMAGE}</dd> - <dd><input type="text" name="confirm_code" id="confirm_code" size="8" maxlength="8" tabindex="3" class="inputbox narrow" title="{L_CONFIRM_CODE}" /></dd> - </dl> + {CONFIRM} <!-- ENDIF --> - <!-- IF S_DISPLAY_FULL_LOGIN --> <dl> <!-- IF S_AUTOLOGIN_ENABLED --><dd><label for="autologin"><input type="checkbox" name="autologin" id="autologin" tabindex="4" /> {L_LOG_ME_IN}</label></dd><!-- ENDIF --> <dd><label for="viewonline"><input type="checkbox" name="viewonline" id="viewonline" tabindex="5" /> {L_HIDE_ME}</label></dd> </dl> <!-- ENDIF --> + <dl> <dt> </dt> <dd>{S_HIDDEN_FIELDS}<input type="submit" name="login" tabindex="6" value="{L_LOGIN}" class="button1" /></dd> @@ -46,6 +41,7 @@ <span class="corners-bottom"><span></span></span></div> </div> + <!-- IF not S_ADMIN_AUTH and S_REGISTER_ENABLED --> <div class="panel"> <div class="inner"><span class="corners-top"><span></span></span> diff --git a/phpBB/styles/prosilver/template/posting_editor.html b/phpBB/styles/prosilver/template/posting_editor.html index f255862430..89c11703b7 100644 --- a/phpBB/styles/prosilver/template/posting_editor.html +++ b/phpBB/styles/prosilver/template/posting_editor.html @@ -100,11 +100,7 @@ <dd><input type="text" name="subject" id="subject" size="45" maxlength="<!-- IF S_NEW_MESSAGE -->60<!-- ELSE -->64<!-- ENDIF -->" tabindex="2" value="{SUBJECT}{DRAFT_SUBJECT}" class="inputbox autowidth" /></dd> </dl> <!-- IF S_CONFIRM_CODE --> - <dl> - <dt><label for="confirm_code">{L_CONFIRM_CODE}:</label><br /><span>{L_CONFIRM_CODE_EXPLAIN}</span></dt> - <dd><input type="hidden" name="confirm_id" value="{CONFIRM_ID}" />{CONFIRM_IMAGE}</dd> - <dd><input type="text" name="confirm_code" id="confirm_code" size="8" maxlength="8" tabindex="3" class="inputbox narrow" title="{L_CONFIRM_CODE}" /></dd> - </dl> + {CONFIRM} <!-- ENDIF --> <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/ucp_register.html b/phpBB/styles/prosilver/template/ucp_register.html index 721028cef6..8d635198d3 100644 --- a/phpBB/styles/prosilver/template/ucp_register.html +++ b/phpBB/styles/prosilver/template/ucp_register.html @@ -71,8 +71,7 @@ </dl> <!-- END profile_fields --> </fieldset> - -<!-- IF S_CONFIRM_CODE --> +<!-- IF S_CAPTCHA --> <span class="corners-bottom"><span></span></span></div> </div> @@ -83,15 +82,10 @@ <p>{L_CONFIRM_EXPLAIN}</p> <fieldset class="fields2"> - <dl> - <dt><label for="confirm_code">{L_CONFIRM_CODE}:</label></dt> - <dd>{CONFIRM_IMG}</dd> - <dd><input type="text" name="confirm_code" id="confirm_code" size="8" maxlength="8" class="inputbox narrow" title="{L_CONFIRM_CODE}" /></dd> - <dd>{L_CONFIRM_CODE_EXPLAIN}</dd> - </dl> + {S_CAPTCHA} </fieldset> -<!-- ENDIF --> +<!-- ENDIF --> <!-- IF S_COPPA --> <span class="corners-bottom"><span></span></span></div> </div> |