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
This commit is contained in:
Henry Sudhof 2008-09-19 13:17:30 +00:00
parent 5349280538
commit 461be11e8d
23 changed files with 937 additions and 415 deletions

View file

@ -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> <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> <label><input type="radio" class="radio" name="enable_post_confirm" value="0"<!-- IF not POST_ENABLE --> checked="checked"<!-- ENDIF --> /> {L_DISABLED}</label></dd>
</dl> </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>
<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>
<!-- ENDIF -->
</fieldset> </fieldset>
<fieldset>
<legend>{L_AVAILABLE_CAPTCHAS}</legend>
<dl>
<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="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>
</fieldset>
<!-- IF CAPTCHA_PREVIEW -->
<fieldset> <fieldset>
<legend>{L_PREVIEW}</legend> <legend>{L_PREVIEW}</legend>
<!-- IF PREVIEW --> {CAPTCHA_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>
</fieldset> </fieldset>
<!-- ENDIF -->
<fieldset class="submit-buttons"> <fieldset class="submit-buttons">
<legend>{L_SUBMIT}</legend> <legend>{L_SUBMIT}</legend>
<input class="button1" type="submit" id="submit" name="submit" value="{L_SUBMIT}" />&nbsp; <input class="button1" type="submit" id="main_submit" name="main_submit" value="{L_SUBMIT}" />&nbsp;
<input class="button2" type="reset" id="reset" name="reset" value="{L_RESET}" />&nbsp; <input class="button2" type="reset" id="form_reset" name="reset" value="{L_RESET}" />&nbsp;
<input class="button2" type="submit" id="preview" name="preview" value="{L_PREVIEW}" />
{S_FORM_TOKEN} {S_FORM_TOKEN}
</fieldset> </fieldset>
</form> </form>

View file

@ -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>

View file

@ -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}" />&nbsp;
<input class="button2" type="reset" id="reset" name="reset" value="{L_RESET}" />&nbsp;
<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 -->

View file

@ -10,6 +10,8 @@
/** /**
* @ignore * @ignore
*/ */
if (!defined('IN_PHPBB')) if (!defined('IN_PHPBB'))
{ {
exit; exit;
@ -28,94 +30,115 @@ class acp_captcha
$user->add_lang('acp/board'); $user->add_lang('acp/board');
include(PHPBB_ROOT_PATH . 'includes/captcha/captcha_factory.' . PHP_EXT);
$captcha_vars = array( $selected = request_var('select_captcha', $config['captcha_plugin']);
'captcha_gd_x_grid' => 'CAPTCHA_GD_X_GRID', $configure = request_var('configure', false);
'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'])) // Oh, they are just here for the view
if (isset($_GET['captcha_demo']))
{ {
$captcha_vars = array_keys($captcha_vars); $this->deliver_demo($selected);
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;
} }
$config_vars = array( // Delegate
'enable_confirm' => 'REG_ENABLE', if ($configure)
'enable_post_confirm' => 'POST_ENABLE',
'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))
{ {
$config_vars = array_keys($config_vars); $config_captcha = phpbb_captcha_factory::get_instance($selected);
foreach ($config_vars as $config_var) $config_captcha->acp_page($id, $this);
{
set_config($config_var, request_var($config_var, ''));
}
$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($this->u_action));
}
else if ($submit)
{
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action));
} }
else else
{ {
$captchas = phpbb_captcha_factory::get_captcha_types();
$preview_image_src = append_sid(append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=$id&amp;demo=demo")); $config_vars = array(
if (@extension_loaded('gd')) '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);
$submit = request_var('main_submit', false);
if ($submit && check_form_key($form_key))
{ {
$template->assign_var('GD', true); $config_vars = array_keys($config_vars);
foreach ($config_vars as $config_var)
{
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));
} }
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]; $captcha_select = '';
$template->assign_var($template_var, $var); foreach ($captchas['available'] as $value => $title)
$preview_image_src .= "&amp;$captcha_var=" . $var; {
$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,
));
} }
$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();
}
} }
?> ?>

View file

@ -81,42 +81,15 @@ function login_db(&$username, &$password)
} }
else else
{ {
global $user; $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']);
$captcha->init(CONFIRM_LOGIN);
$sql = 'SELECT code $vc_response = $captcha->validate();
FROM ' . CONFIRM_TABLE . " if ($vc_response)
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)
{
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(
'status' => LOGIN_ERROR_ATTEMPTS,
'error_msg' => 'CONFIRM_CODE_WRONG',
'user_row' => $row,
);
}
}
else
{ {
return array( return array(
'status' => LOGIN_ERROR_ATTEMPTS, 'status' => LOGIN_ERROR_ATTEMPTS,
'error_msg' => 'CONFIRM_CODE_WRONG', 'error_msg' => 'LOGIN_ERROR_ATTEMPTS',
'user_row' => $row, 'user_row' => $row,
); );
} }
} }

View file

@ -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;
}
}

View file

@ -85,7 +85,7 @@ class captcha
} }
else else
{ {
for ($j = 0; $j < $this->width; $j++) for ($j = 0; $j < self::width; $j++)
{ {
$image .= chr(mt_rand(140, 255)); $image .= chr(mt_rand(140, 255));
} }
@ -93,7 +93,7 @@ class captcha
} }
unset($hold_chars); unset($hold_chars);
$image = self::create_png($image, $this->width, $this->height); $image = self::create_png($image, self::width, self::height);
// Output image // Output image
header('Content-Type: image/png'); header('Content-Type: image/png');
@ -149,7 +149,7 @@ class captcha
* png because it's a fully recognised open standard and supported * png because it's a fully recognised open standard and supported
* by practically all modern browsers and OSs * by practically all modern browsers and OSs
*/ */
function create_png($raw_image, $width, $height) static function create_png($raw_image, $width, $height)
{ {
// SIG // SIG
$image = pack('C8', 137, 80, 78, 71, 13, 10, 26, 10); $image = pack('C8', 137, 80, 78, 71, 13, 10, 26, 10);

View file

@ -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();
}

View file

@ -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&amp;confirm_id=' . $this->confirm_id . '&amp;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&amp;mode=visual&amp;i=' . $id . '&amp;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();
}
}

View file

@ -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(),
));
}
}
}

View file

@ -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));
}
}

View file

@ -2365,6 +2365,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
{ {
global $db, $user, $template, $auth, $config; global $db, $user, $template, $auth, $config;
include(PHPBB_ROOT_PATH . 'includes/captcha/captcha_factory.' . PHP_EXT);
$err = ''; $err = '';
@ -2483,34 +2484,13 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
{ {
case LOGIN_ERROR_ATTEMPTS: case LOGIN_ERROR_ATTEMPTS:
// Show confirm image $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']);
$sql = 'DELETE FROM ' . CONFIRM_TABLE . " $captcha->init(CONFIRM_LOGIN);
WHERE session_id = '" . $db->sql_escape($user->session_id) . "' $captcha->reset();
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);
$template->assign_vars(array( $template->assign_vars(array(
'S_CONFIRM_CODE' => true, 'S_CONFIRM_CODE' => true,
'CONFIRM_ID' => $confirm_id, 'CONFIRM' => $captcha->get_template(''),
'CONFIRM_IMAGE' => '<img src="' . append_sid('ucp', 'mode=confirm&amp;id=' . $confirm_id . '&amp;type=' . CONFIRM_LOGIN) . '" alt="" title="" />',
'L_LOGIN_CONFIRM_EXPLAIN' => sprintf($user->lang['LOGIN_CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'),
)); ));
$err = $user->lang[$result['error_msg']]; $err = $user->lang[$result['error_msg']];

View file

@ -923,42 +923,18 @@ class session
WHERE last_login < ' . (time() - (86400 * (int) $config['max_autologin_time'])); WHERE last_login < ' . (time() - (86400 * (int) $config['max_autologin_time']));
$db->sql_query($sql); $db->sql_query($sql);
} }
$this->confirm_gc();
// only called from CRON; should be a safe workaround until the infrastructure gets going
if (!class_exists('captcha_factory'))
{
include(PHPBB_ROOT_PATH . "includes/captcha/captcha_factory." . PHP_EXT);
}
captcha_factory::garbage_collect($config['captcha_plugin']);
} }
return; 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))
{
$sql = 'DELETE FROM ' . CONFIRM_TABLE . '
WHERE ' . $db->sql_in_set('session_id', $sql_in);
$db->sql_query($sql);
}
}
$db->sql_freeresult($result);
}
/** /**
* Sets a cookie * Sets a cookie

View file

@ -3,7 +3,7 @@
* *
* @package VC * @package VC
* @version $Id$ * @version $Id$
* @copyright (c) 2005 phpBB Group * @copyright (c) 2005 2008 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License * @license http://opensource.org/licenses/gpl-license.php GNU Public License
* *
*/ */
@ -36,43 +36,10 @@ class ucp_confirm
function main($id, $mode) function main($id, $mode)
{ {
global $db, $user, $config; global $db, $user, $config;
include(PHPBB_ROOT_PATH . 'includes/captcha/captcha_factory.' . PHP_EXT);
// Do we have an id? No, then just exit $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']);
$confirm_id = request_var('id', ''); $captcha->init(request_var('type', 0));
$type = request_var('type', 0); $captcha->execute();
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']);
garbage_collection(); garbage_collection();
exit_handler(); exit_handler();
} }

View file

@ -37,7 +37,6 @@ class ucp_register
include(PHPBB_ROOT_PATH . 'includes/functions_profile_fields.' . PHP_EXT); 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; $coppa = (isset($_REQUEST['coppa'])) ? ((!empty($_REQUEST['coppa'])) ? 1 : 0) : false;
$agreed = (!empty($_POST['agreed'])) ? 1 : 0; $agreed = (!empty($_POST['agreed'])) ? 1 : 0;
$submit = (isset($_POST['submit'])) ? true : false; $submit = (isset($_POST['submit'])) ? true : false;
@ -54,6 +53,13 @@ class ucp_register
} }
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']) if ($change_lang || $user_lang != $config['default_lang'])
{ {
$use_lang = ($change_lang) ? basename($change_lang) : basename($user_lang); $use_lang = ($change_lang) ? basename($change_lang) : basename($user_lang);
@ -89,7 +95,7 @@ class ucp_register
$add_lang = ($change_lang) ? '&amp;change_lang=' . urlencode($change_lang) : ''; $add_lang = ($change_lang) ? '&amp;change_lang=' . urlencode($change_lang) : '';
$add_coppa = ($coppa !== false) ? '&amp;coppa=' . $coppa : ''; $add_coppa = ($coppa !== false) ? '&amp;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 we change the language, we want to pass on some more possible parameter.
if ($change_lang) if ($change_lang)
@ -99,11 +105,14 @@ class ucp_register
'username' => utf8_normalize_nfc(request_var('username', '', true)), 'username' => utf8_normalize_nfc(request_var('username', '', true)),
'email' => strtolower(request_var('email', '')), 'email' => strtolower(request_var('email', '')),
'email_confirm' => strtolower(request_var('email_confirm', '')), 'email_confirm' => strtolower(request_var('email_confirm', '')),
'confirm_code' => request_var('confirm_code', ''),
'confirm_id' => request_var('confirm_id', ''),
'lang' => $user->lang_name, 'lang' => $user->lang_name,
'tz' => request_var('tz', (float) $config['board_timezone']), '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']) if ($coppa === false && $config['coppa_enable'])
@ -167,7 +176,6 @@ class ucp_register
'password_confirm' => request_var('password_confirm', '', true), 'password_confirm' => request_var('password_confirm', '', true),
'email' => strtolower(request_var('email', '')), 'email' => strtolower(request_var('email', '')),
'email_confirm' => strtolower(request_var('email_confirm', '')), 'email_confirm' => strtolower(request_var('email_confirm', '')),
'confirm_code' => request_var('confirm_code', ''),
'lang' => basename(request_var('lang', $user->lang_name)), 'lang' => basename(request_var('lang', $user->lang_name)),
'tz' => request_var('tz', (float) $timezone), 'tz' => request_var('tz', (float) $timezone),
); );
@ -187,7 +195,6 @@ class ucp_register
array('string', false, 6, 60), array('string', false, 6, 60),
array('email')), array('email')),
'email_confirm' => array('string', false, 6, 60), 'email_confirm' => array('string', false, 6, 60),
'confirm_code' => array('string', !$config['enable_confirm'], 5, 8),
'tz' => array('num', false, -14, 14), 'tz' => array('num', false, -14, 14),
'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'), 'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'),
)); ));
@ -198,6 +205,22 @@ class ucp_register
// Replace "error" strings with their real, localised form // Replace "error" strings with their real, localised form
$error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); $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 // DNSBL check
if ($config['check_dnsbl']) if ($config['check_dnsbl'])
{ {
@ -210,50 +233,6 @@ class ucp_register
// validate custom profile fields // validate custom profile fields
$cp->submit_cp_field('register', $user->get_iso_lang_id(), $cp_data, $error); $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 (!sizeof($error))
{ {
if ($data['new_password'] != $data['password_confirm']) if ($data['new_password'] != $data['password_confirm'])
@ -451,57 +430,16 @@ class ucp_register
if ($change_lang) if ($change_lang)
{ {
$str = '&amp;change_lang=' . $change_lang; $str = '&amp;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 else
{ {
$str = ''; $str = '';
} }
if (!$change_lang || !$confirm_id)
{
$user->confirm_gc(CONFIRM_REG);
$sql = 'SELECT COUNT(session_id) AS attempts $template->assign_vars(array(
FROM ' . CONFIRM_TABLE . " 'L_CONFIRM_EXPLAIN' => sprintf($user->lang['CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'),
WHERE session_id = '" . $db->sql_escape($user->session_id) . "' 'S_CAPTCHA' => $captcha->get_template(),
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&amp;id=' . $confirm_id . '&amp;type=' . CONFIRM_REG . $str) . '" alt="" title="" />';
$s_hidden_fields .= '<input type="hidden" name="confirm_id" value="' . $confirm_id . '" />';
} }
// //
@ -524,16 +462,13 @@ class ucp_register
'PASSWORD_CONFIRM' => $data['password_confirm'], 'PASSWORD_CONFIRM' => $data['password_confirm'],
'EMAIL' => $data['email'], 'EMAIL' => $data['email'],
'EMAIL_CONFIRM' => $data['email_confirm'], '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_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_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']), '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_LANG_OPTIONS' => language_select($data['lang']),
'S_TZ_OPTIONS' => tz_select($data['tz']), 'S_TZ_OPTIONS' => tz_select($data['tz']),
'S_CONFIRM_CODE' => ($config['enable_confirm']) ? true : false,
'S_COPPA' => $coppa, 'S_COPPA' => $coppa,
'S_HIDDEN_FIELDS' => $s_hidden_fields, 'S_HIDDEN_FIELDS' => $s_hidden_fields,
'S_UCP_ACTION' => append_sid('ucp', 'mode=register'), 'S_UCP_ACTION' => append_sid('ucp', 'mode=register'),

View file

@ -1387,8 +1387,8 @@ class install_install extends module
if (@extension_loaded('gd') || can_load_dll('gd')) if (@extension_loaded('gd') || can_load_dll('gd'))
{ {
$sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config
SET config_value = '1' SET config_value = 'phpbb_captcha_gd'
WHERE config_name = 'captcha_gd'"; WHERE config_name = 'captcha_plugin'";
} }
// We set a (semi-)unique cookie name to bypass login issues related to the cookie name. // We set a (semi-)unique cookie name to bypass login issues related to the cookie name.

View file

@ -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_interval', '10');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('bump_type', 'd'); 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 ('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_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_x_grid', '25');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_y_grid', '25'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_y_grid', '25');

View file

@ -230,8 +230,9 @@ $lang = array_merge($lang, array(
// Visual Confirmation Settings // Visual Confirmation Settings
$lang = array_merge($lang, array( $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' => 'GD CAPTCHA',
'CAPTCHA_GD_FOREGROUND_NOISE' => 'GD CAPTCHA foreground noise', 'CAPTCHA_GD_FOREGROUND_NOISE' => 'GD CAPTCHA foreground noise',
'CAPTCHA_GD_EXPLAIN' => 'Use GD to make a more advanced CAPTCHA.', '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' => '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_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_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' => '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_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', 'VISUAL_CONFIRM_REG' => 'Enable visual confirmation for registrations',

View file

@ -45,6 +45,12 @@ $mode = ($delete && !$preview && !$refresh && $submit) ? 'delete' : request_var
$error = $post_data = array(); $error = $post_data = array();
$current_time = time(); $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 // Was cancel pressed? If so then redirect to the appropriate page
if ($cancel || ($current_time - $lastclick < 2 && $submit)) 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'))) if ($config['enable_post_confirm'] && !$user->data['is_registered'] && in_array($mode, array('quote', 'post', 'reply')))
{ {
$confirm_id = request_var('confirm_id', ''); $vc_response = $captcha->validate();
$confirm_code = request_var('confirm_code', ''); if ($vc_response)
$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)
{ {
$error[] = $user->lang['CONFIRM_CODE_WRONG']; $error += $vc_response;
} }
else 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); $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. // 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'])) 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')) if ($config['enable_post_confirm'] && !$user->data['is_registered'] && $solved_captcha === false && ($mode == 'post' || $mode == 'reply' || $mode == 'quote'))
{ {
// Show confirm image $captcha->reset();
$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);
$template->assign_vars(array( $template->assign_vars(array(
'S_CONFIRM_CODE' => true, 'S_CONFIRM_CODE' => true,
'CONFIRM_ID' => $confirm_id, 'CONFIRM' => $captcha->get_template(),
'CONFIRM_IMAGE' => '<img src="' . append_sid('ucp', 'mode=confirm&amp;id=' . $confirm_id . '&amp;type=' . CONFIRM_POST) . '" alt="" title="" />',
'L_POST_CONFIRM_EXPLAIN' => sprintf($user->lang['POST_CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'),
)); ));
} }
@ -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 // Add the confirm id/code pair to the hidden fields, else an error is displayed on next submit/preview
if ($solved_captcha !== false) if ($solved_captcha !== false)
{ {
$s_hidden_fields .= build_hidden_fields(array( $s_hidden_fields .= build_hidden_fields($captcha->get_hidden_fields());
'confirm_id' => request_var('confirm_id', ''),
'confirm_code' => request_var('confirm_code', ''))
);
} }
$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"'; $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"';

View file

@ -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>

View file

@ -21,21 +21,16 @@
<!-- IF U_RESEND_ACTIVATION --><dd><a href="{U_RESEND_ACTIVATION}">{L_RESEND_ACTIVATION}</a></dd><!-- ENDIF --> <!-- IF U_RESEND_ACTIVATION --><dd><a href="{U_RESEND_ACTIVATION}">{L_RESEND_ACTIVATION}</a></dd><!-- ENDIF -->
<!-- ENDIF --> <!-- ENDIF -->
</dl> </dl>
<!-- IF S_CONFIRM_CODE --> <!-- IF S_CONFIRM_CODE -->
<dl> {CONFIRM}
<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>
<!-- ENDIF --> <!-- ENDIF -->
<!-- IF S_DISPLAY_FULL_LOGIN --> <!-- IF S_DISPLAY_FULL_LOGIN -->
<dl> <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 --> <!-- 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> <dd><label for="viewonline"><input type="checkbox" name="viewonline" id="viewonline" tabindex="5" /> {L_HIDE_ME}</label></dd>
</dl> </dl>
<!-- ENDIF --> <!-- ENDIF -->
<dl> <dl>
<dt>&nbsp;</dt> <dt>&nbsp;</dt>
<dd>{S_HIDDEN_FIELDS}<input type="submit" name="login" tabindex="6" value="{L_LOGIN}" class="button1" /></dd> <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> <span class="corners-bottom"><span></span></span></div>
</div> </div>
<!-- IF not S_ADMIN_AUTH and S_REGISTER_ENABLED --> <!-- IF not S_ADMIN_AUTH and S_REGISTER_ENABLED -->
<div class="panel"> <div class="panel">
<div class="inner"><span class="corners-top"><span></span></span> <div class="inner"><span class="corners-top"><span></span></span>

View file

@ -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> <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> </dl>
<!-- IF S_CONFIRM_CODE --> <!-- IF S_CONFIRM_CODE -->
<dl> {CONFIRM}
<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>
<!-- ENDIF --> <!-- ENDIF -->
<!-- ENDIF --> <!-- ENDIF -->

View file

@ -71,8 +71,7 @@
</dl> </dl>
<!-- END profile_fields --> <!-- END profile_fields -->
</fieldset> </fieldset>
<!-- IF S_CAPTCHA -->
<!-- IF S_CONFIRM_CODE -->
<span class="corners-bottom"><span></span></span></div> <span class="corners-bottom"><span></span></span></div>
</div> </div>
@ -83,15 +82,10 @@
<p>{L_CONFIRM_EXPLAIN}</p> <p>{L_CONFIRM_EXPLAIN}</p>
<fieldset class="fields2"> <fieldset class="fields2">
<dl> {S_CAPTCHA}
<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>
</fieldset> </fieldset>
<!-- ENDIF -->
<!-- ENDIF -->
<!-- IF S_COPPA --> <!-- IF S_COPPA -->
<span class="corners-bottom"><span></span></span></div> <span class="corners-bottom"><span></span></span></div>
</div> </div>