function captcha_form_alter in CAPTCHA 6
Same name and namespace in other branches
- 8 captcha.module \captcha_form_alter()
- 5.3 captcha.module \captcha_form_alter()
- 6.2 captcha.module \captcha_form_alter()
- 7 captcha.module \captcha_form_alter()
Implementation of hook_form_alter().
This function adds a CAPTCHA to forms for untrusted users if needed and adds CAPTCHA administration links for site administrators if this option is enabled.
File
- ./
captcha.module, line 180 - This module enables basic CAPTCHA functionality: administrators can add a CAPTCHA to desired forms that users without the 'skip CAPTCHA' permission (typically anonymous visitors) have to solve.
Code
function captcha_form_alter(&$form, $form_state, $form_id) {
if (!user_access('skip CAPTCHA')) {
// Visitor does not have permission to skip the CAPTCHA
// Get CAPTCHA type and module for this form. Return if no CAPTCHA was set.
$result = db_query("SELECT module, type FROM {captcha_points} WHERE form_id = '%s'", $form_id);
if (!$result) {
return;
}
$captcha_point = db_fetch_object($result);
if (!$captcha_point || !$captcha_point->type) {
return;
}
// Prevent caching of the page with this CAPTCHA enabled form.
// This needs to be done even if the CAPTCHA will be skipped (because of
// persistence): other untrusted users should not get a cached page when
// the current untrusted user can skip the current CAPTCHA.
global $conf;
$conf['cache'] = FALSE;
// Do not present CAPTCHA if not CAPTCHA-persistent and user has already solved a CAPTCHA for this form
if (_captcha_persistence_skip($form_id)) {
return;
}
// Generate a CAPTCHA and its solution
$captcha = module_invoke($captcha_point->module, 'captcha', 'generate', $captcha_point->type);
if (!$captcha) {
//The selected module returned nothing, maybe it is disabled or it's wrong, we should watchdog that and then quit.
watchdog('CAPTCHA', 'CAPTCHA problem: hook_captcha() of module %module returned nothing when trying to retrieve challenge type %type for form %form_id.', array(
'%type' => $captcha_point->type,
'%module' => $captcha_point->module,
'%form_id' => $form_id,
), WATCHDOG_ERROR);
return;
}
// Add a CAPTCHA part to the form (depends on value of captcha_description)
$captcha_description = _captcha_get_description();
if ($captcha_description) {
// $captcha_description is not empty: CAPTCHA part is a fieldset with description
$form['captcha'] = array(
'#type' => 'fieldset',
'#title' => t('CAPTCHA'),
'#description' => $captcha_description,
'#attributes' => array(
'class' => 'captcha',
),
);
}
else {
// $captcha_description is empty: CAPTCHA part is an empty markup form element
$form['captcha'] = array(
'#type' => 'markup',
'#prefix' => '<div class="captcha">',
'#suffix' => '</div>',
);
}
// Add the form elements of the generated CAPTCHA to the form
$form['captcha'] = array_merge($form['captcha'], $captcha['form']);
// Store the solution of the generated CAPTCHA as an internal form value.
// This will be stored later in $_SESSION during the pre_render phase.
// It can't be saved at this point because hook_form_alter is not only run
// before form rendering, but also before form validation (which happens
// in a new (POST) request. Consequently the right CAPTCHA solution would be
// overwritten just before validation. The pre_render functions are not run
// before validation and are the right place to store the solution in $_SESSION.
$form['captcha']['captcha_solution'] = array(
'#type' => 'value',
'#value' => $captcha['solution'],
);
// The CAPTCHA token is used to differentiate between different instances
// of the same form. This makes it possible to request the same form a
// couple of times before submitting them. The solution of the CAPTCHA of
// each of these form instances will be stored at the pre_render phase in
// $_SESSION['captcha'][$form_id][$captcha_token]
$form['captcha']['captcha_token'] = array(
'#type' => 'hidden',
'#value' => md5(mt_rand()),
);
// other internal values needed for the validation phase
$form['captcha']['captcha_info'] = array(
'#type' => 'value',
'#value' => array(
'form_id' => $form_id,
'preprocess' => isset($captcha['preprocess']) ? $captcha['preprocess'] : FALSE,
'module' => $captcha_point->module,
'type' => $captcha_point->type,
),
);
// Add pre_render function for additional CAPTCHA processing.
$form['#pre_render'][] = 'captcha_pre_render';
// Add pre_render function for placement of CAPTCHA formt element (above submit buttons).
$form['#pre_render'][] = 'captcha_pre_render_place_captcha';
// Add a validation function for the CAPTCHA form element.
$form['captcha']['#element_validate'] = array(
'captcha_validate',
);
}
elseif (user_access('administer CAPTCHA settings') && variable_get('captcha_administration_mode', FALSE) && arg(0) != 'admin') {
// For administrators: show CAPTCHA info and offer link to configure it
$result = db_query("SELECT module, type FROM {captcha_points} WHERE form_id = '%s'", $form_id);
if (!$result) {
return;
}
$captcha_point = db_fetch_object($result);
$form['captcha'] = array(
'#type' => 'fieldset',
'#title' => t('CAPTCHA'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
if ($captcha_point && $captcha_point->type) {
$form['captcha']['#description'] = t('Untrusted users will see a CAPTCHA here (!settings).', array(
'!settings' => l(t('general CAPTCHA settings'), 'admin/user/captcha'),
));
$form['captcha']['challenge'] = array(
'#type' => 'item',
'#title' => t('Enabled challenge'),
'#value' => t('"@type" by module "@module" (!change, !disable)', array(
'@type' => $captcha_point->type,
'@module' => $captcha_point->module,
'!change' => l(t('change'), "admin/user/captcha/captcha/captcha_point/{$form_id}", array(
'query' => drupal_get_destination(),
)),
'!disable' => l(t('disable'), "admin/user/captcha/captcha/captcha_point/{$form_id}/disable", array(
'query' => drupal_get_destination(),
)),
)),
);
}
else {
$form['captcha']['add_captcha'] = array(
'#value' => l(t('Place a CAPTCHA here for untrusted users.'), "admin/user/captcha/captcha/captcha_point/{$form_id}", array(
'query' => drupal_get_destination(),
)),
);
}
// Add pre_render function for placement of CAPTCHA formt element (above submit buttons).
$form['#pre_render'][] = 'captcha_pre_render_place_captcha';
}
}