captcha_after.module in CAPTCHA After 6
Same filename and directory in other branches
Show CAPTCHA protection on selected forms after specified number of unsuccessful form submit attempts has been made.
File
captcha_after.moduleView source
<?php
/**
* @file
* Show CAPTCHA protection on selected forms after specified number of
* unsuccessful form submit attempts has been made.
*/
/**
* Implementation of hook_menu().
*/
function captcha_after_menu() {
$items = array();
$items['admin/user/captcha/captcha/after'] = array(
'title' => 'CAPTCHA After',
'file' => 'captcha_after.admin.inc',
'description' => 'Change CAPTCHA After settings.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'captcha_after_settings',
),
'access arguments' => array(
'administer CAPTCHA settings',
),
'type' => MENU_LOCAL_TASK,
'weight' => 2,
);
return $items;
}
/**
* Implementation of hook_form_alter().
*/
function captcha_after_form_alter(&$form, $form_state, $form_id) {
// First check do we have captcha for this form.
module_load_include('inc', 'captcha');
$captcha_point = captcha_get_form_id_setting($form_id, TRUE);
if (!$captcha_point || $captcha_point == '' || $captcha_point == 'none') {
return;
}
// Load captcha after settings for this form.
$ca_settings = captcha_after_get_forms_settings($form_id);
// Check if captcha_after is enabled for this form.
if (!$ca_settings['enable']) {
return;
}
$form['#after_build'][] = 'captcha_after_form_after_build';
$form['#validate'][] = 'captcha_after_form_validate';
$form['#pre_render'][] = 'captcha_after_form_pre_render';
$form['#submit'][] = 'captcha_after_form_submit';
}
/**
* After build state of form. Decide should we skip captcha element validation.
*/
function captcha_after_form_after_build($form_element, &$form_state) {
// Test should we skip captcha widget validation.
if (!captcha_after_show_captcha($form_element['form_id']['#value']) && ($captcha =& captcha_after_get_captcha_element($form_element))) {
$captcha['#validated'] = TRUE;
$captcha['captcha_widgets']['captcha_response']['#validated'] = TRUE;
}
return $form_element;
}
/**
* Form is validated.
*/
function captcha_after_form_validate($form, &$form_state) {
// Form is submited - lets increment flood counter.
flood_register_event('captcha_after_' . $form['form_id']['#value']);
}
/**
* Form is submited.
*/
function captcha_after_form_submit($form, &$form_state) {
$form_id = $form['form_id']['#value'];
// We are in submit - reset flood submit threshold counter.
captcha_after_db_flood_delete_events('captcha_after_' . $form_id);
// Register correct form submission.
flood_register_event($form_id);
}
/**
* Form is in pre rendered state.
*/
function captcha_after_form_pre_render($form) {
// Test should we hide captcha widget.
if (!captcha_after_show_captcha($form['form_id']['#value']) && ($captcha =& captcha_after_get_captcha_element($form))) {
$captcha =& captcha_after_get_captcha_element($form);
$captcha['#access'] = FALSE;
}
return $form;
}
/**
* Helper function.
*
* Removed hostname check from Drupal core's flood_is_allowed function.
*/
function captcha_after_global_flood_is_allowed($name, $threshold) {
$number = db_result(db_query("SELECT COUNT(*) FROM {flood} WHERE event = '%s' AND timestamp > %d", $name, time() - 3600));
return $number < $threshold ? TRUE : FALSE;
}
/**
* Helper function for returning captcha_after forms configuration values.
*/
function captcha_after_get_forms_settings($form_id) {
$form_settings = captcha_after_db_get_form($form_id);
$settings['enable'] = FALSE;
// If we do not have captcha_after settings for this form or captcha_after is
// disabled for this form there is nothign to do.
if (!$form_settings || !$form_settings['enable']) {
return $settings;
}
$settings['enable'] = $form_settings['enable'];
// Load global settings for all forms.
$settings['submit_threshold'] = variable_get('captcha_after_submit_threshold', 3);
$settings['flooding_threshold'] = variable_get('captcha_after_flooding_threshold', 3);
$settings['global_flooding_threshold'] = variable_get('captcha_after_global_flooding_threshold', 1000);
// Overide global settings where needed.
if ($form_settings = captcha_after_db_get_form($form_id)) {
foreach ($settings as $key => $value) {
if (isset($form_settings['options'][$key]) && $form_settings['options'][$key] != '') {
$settings[$key] = $form_settings['options'][$key];
}
}
}
return $settings;
}
/**
* Helper function for finding captcha element in form array.
*
* @return boolean
* Reference to form captcha element or FALSE if if captcha element is not
* found in form.
*/
function &captcha_after_get_captcha_element(&$form) {
if (isset($form['captcha'])) {
return $form['captcha'];
}
if (isset($form['actions']['captcha'])) {
return $form['actions']['captcha'];
}
// For node forms.
if (isset($form['buttons']['captcha'])) {
return $form['buttons']['captcha'];
}
// We didn't find captcha element on captcha enabled form - this is a valid
// case for example when skip captcha protection is configured for some user
// roles. And we are returing variable here because function needs to return
// reference.
$element = FALSE;
return $element;
}
/**
* Tests current form on captcha after threashold settings.
*
* @param string $form_id
* Form id.
* @return boolean
* If some of the threasholds are reached returns TRUE (captcha should be
* shown). If not returns FALSE.
*/
function captcha_after_show_captcha($form_id) {
// Get captcha_after settings for this form.
$ca_settings = captcha_after_get_forms_settings($form_id);
// Now we will test all captcha_after threshold settings.
// If some settings is empty or 0 we will not take it into consideration.
if (!empty($ca_settings['flooding_threshold']) && !flood_is_allowed($form_id, $ca_settings['flooding_threshold'])) {
return TRUE;
}
if (!empty($ca_settings['submit_threshold']) && !flood_is_allowed('captcha_after_' . $form_id, $ca_settings['submit_threshold'])) {
return TRUE;
}
if (!empty($ca_settings['global_flooding_threshold']) && !captcha_after_global_flood_is_allowed($form_id, $ca_settings['global_flooding_threshold'])) {
return TRUE;
}
// All captcha_after tests are passed so we do not need to show captcha.
return FALSE;
}
/**
* Loads all captcha_after forms settings from database.
*
* @return array
* Array of all captcha_after form settings.
*/
function captcha_after_db_get_forms() {
$forms = array();
$res = db_query('SELECT * FROM {captcha_after}');
while ($form = db_fetch_array($res)) {
$form['options'] = empty($form['options']) ? $form['options'] : unserialize($form['options']);
$forms[$form['form_id']] = $form;
}
return $forms;
}
/**
* Loads captcha_after form settings from database.
*
* @param $form_id
* Form id value.
* @return array
* Array of all captcha_after form settings if they exist in database or
* FALSE.
*/
function captcha_after_db_get_form($form_id) {
static $forms = array();
if (!isset($forms[$form_id])) {
$form = db_fetch_array(db_query("SELECT * FROM {captcha_after} WHERE form_id = '%s'", $form_id));
if (!empty($form)) {
$form['options'] = empty($form['options']) ? $form['options'] : unserialize($form['options']);
$forms[$form_id] = $form;
}
else {
$forms[$form_id] = FALSE;
}
}
return $forms[$form_id];
}
/**
* Saves captcha_after form settings in database.
*/
function captcha_after_db_set_form($form_id, array $options) {
$enable = $options['enable'];
unset($options['enable']);
db_query("DELETE FROM {captcha_after} WHERE form_id = '%s'", $form_id);
db_query("INSERT INTO {captcha_after} (form_id, enable, options) VALUES ('%s', %d, '%s')", $form_id, $enable, serialize($options));
}
/**
* Delete flood events for a given name and user hostname.
*
* @param string $name
* Registerd flood name.
*/
function captcha_after_db_flood_delete_events($name) {
db_query("DELETE FROM {flood} WHERE event = '%s' AND hostname = '%s'", $name, ip_address());
}
Functions
Name | Description |
---|---|
captcha_after_db_flood_delete_events | Delete flood events for a given name and user hostname. |
captcha_after_db_get_form | Loads captcha_after form settings from database. |
captcha_after_db_get_forms | Loads all captcha_after forms settings from database. |
captcha_after_db_set_form | Saves captcha_after form settings in database. |
captcha_after_form_after_build | After build state of form. Decide should we skip captcha element validation. |
captcha_after_form_alter | Implementation of hook_form_alter(). |
captcha_after_form_pre_render | Form is in pre rendered state. |
captcha_after_form_submit | Form is submited. |
captcha_after_form_validate | Form is validated. |
captcha_after_get_captcha_element | Helper function for finding captcha element in form array. |
captcha_after_get_forms_settings | Helper function for returning captcha_after forms configuration values. |
captcha_after_global_flood_is_allowed | Helper function. |
captcha_after_menu | Implementation of hook_menu(). |
captcha_after_show_captcha | Tests current form on captcha after threashold settings. |