View source
<?php
define('BOTCHA_LOG', 'BOTCHA');
define('BOTCHA_LOGLEVEL', variable_get('botcha_loglevel', 1));
function botcha_help($path, $arg) {
switch ($path) {
case 'admin/help#botcha':
$output = '<p>' . t('"BOTCHA" is an acronym for "BOT Computerized Heuristic Analysis". It is a method of protection from automated form submissions by performing analysis of submitted data that determines whether the user is a bot. The BOTCHA module is a tool to fight automated submission by malicious users that utilize automated form submission (e.g. for spamming) of for example comments forms, user registration forms, guestbook forms, etc. BOTCHA inserts elements into the desired forms that will not be shown to normal users. These elements have no impact on humans and require no puzzles to solve, but they are easy enough for automated scripts and spam bots to trip on.') . '</p>';
$output .= '<p>' . t('Note that BOTCHA module interacts with page caching (see <a href="!performancesettings">performance settings</a>). Because BOTCHA elements should be unique for each generated form, the caching of the page it appears on is prevented. Make sure that these forms do not appear on too many pages or you will lose much caching efficiency. For example, if you put a BOTCHA on the user login block, which typically appears on each page for anonymous visitors, caching will practically be disabled. The comment submission forms are another example. In this case you should set the "%commentlocation" to "%separatepage" in the comment settings of the relevant <a href="!contenttypes">content types</a> for better caching efficiency.', array(
'!performancesettings' => url('admin/settings/performance'),
'%commentlocation' => t('Location of comment submission form'),
'%separatepage' => t('Display on separate page'),
'!contenttypes' => url('admin/content/types'),
)) . '</p>';
return $output;
case 'admin/user/botcha':
module_load_include('inc', 'botcha');
$output = '<p>' . t('A BOTCHA protection can be added to virtually each Drupal form. Some default forms are already provided in the form list and more can be added using form internal name.') . '</p>';
$output .= '<p>' . t('All existing forms can be easily added and managed when the option "%adminlinks" is enabled.', array(
'%adminlinks' => t('Add BOTCHA administration links to forms'),
)) . '</p>';
if (botcha_is_captcha_installed()) {
$output .= '<p>' . t('Other forms will be added automatically based on CAPTCHA settings when the option "%usecaptcha" is enabled.', array(
'%usecaptcha' => t('Add BOTCHA to forms selected for CAPTCHA'),
)) . '</p>';
}
$output .= '<p>' . t('Forms served to users with the "%skipbotcha" <a href="@perm">permission</a> won\'t be protected. Be sure to grant this permission to the trusted users (e.g. site administrators). If you want to test a protected form, be sure to do it as a user without the "%skipbotcha" permission (e.g. as anonymous user).', array(
'%skipbotcha' => t('skip BOTCHA'),
'@perm' => url('admin/user/permissions', array(
'fragment' => 'module-' . 'botcha',
)),
)) . '</p>';
return $output;
}
}
function botcha_menu() {
$items = array();
$items['admin/user/botcha'] = array(
'title' => 'BOTCHA',
'description' => 'Administer how and where BOTCHAs are used.',
'file' => 'botcha.pages.inc',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'botcha_admin_settings',
),
'access arguments' => array(
'administer BOTCHA settings',
),
'type' => MENU_NORMAL_ITEM,
);
$items['admin/user/botcha/botcha_point'] = array(
'title' => 'BOTCHA point administration',
'file' => 'botcha.pages.inc',
'page callback' => 'botcha_point_admin',
'page arguments' => array(
4,
5,
),
'access arguments' => array(
'administer BOTCHA settings',
),
'type' => MENU_CALLBACK,
);
return $items;
}
function botcha_perm() {
return array(
'administer BOTCHA settings',
'skip BOTCHA',
);
}
function botcha_theme() {
return array(
'botcha_admin_settings_botcha_points' => array(
'arguments' => array(
'form' => NULL,
),
),
);
}
function botcha_form_alter(&$form, &$form_state, $form_id) {
$botcha = FALSE;
if (!user_access('skip BOTCHA')) {
module_load_include('inc', 'botcha');
$botcha_point = botcha_get_form_id_setting($form_id);
if ($botcha_point) {
$botcha = !$botcha_point->botcha_type || $botcha_point->botcha_type == 'none' ? FALSE : $botcha_point->botcha_type;
}
elseif (variable_get('botcha_on_captcha_forms', TRUE) && botcha_is_captcha_installed()) {
$captcha_point = botcha_get_captcha_point($form_id, TRUE);
if ($captcha_point && $captcha_point != 'none') {
$botcha = 'default';
}
}
}
if (variable_get('botcha_administration_mode', FALSE) && user_access('administer BOTCHA settings') && (arg(0) != 'admin' || variable_get('botcha_allow_on_admin_pages', FALSE) || $form_id == 'user_register')) {
module_load_include('inc', 'botcha');
$botcha_point = botcha_get_form_id_setting($form_id);
$botcha_element = array(
'#type' => 'fieldset',
'#title' => t('BOTCHA'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
if ($botcha_point !== NULL && $botcha_point->botcha_type && $botcha_point->botcha_type != 'none') {
$botcha_element['#title'] = t('BOTCHA: protection enabled (@type cookbook)', array(
'@type' => $botcha_point->botcha_type,
));
$botcha_element['#description'] = t('Untrusted users will have form %form_id protected by BOTCHA (!settings).', array(
'%form_id' => $form_id,
'!settings' => l(t('general BOTCHA settings'), 'admin/user/botcha'),
));
$botcha_element['protection'] = array(
'#type' => 'item',
'#title' => t('Enabled protection'),
'#value' => t('"@type" cookbook (!change, !disable)', array(
'@type' => $botcha_point->botcha_type,
'!change' => l(t('change'), "admin/user/botcha/botcha_point/{$form_id}", array(
'query' => drupal_get_destination(),
'html' => TRUE,
)),
'!disable' => l(t('disable'), "admin/user/botcha/botcha_point/{$form_id}/disable", array(
'query' => drupal_get_destination(),
'html' => TRUE,
)),
)),
);
}
else {
$botcha_element['#title'] = t('BOTCHA: no protection enabled');
$botcha_element['add_botcha'] = array(
'#value' => l(t('Add BOTCHA protection on form %form_id for untrusted users.', array(
'%form_id' => $form_id,
)), "admin/user/botcha/botcha_point/{$form_id}", array(
'query' => drupal_get_destination(),
'html' => TRUE,
)),
);
}
$botcha_placement = _botcha_get_botcha_placement($form_id, $form);
_botcha_insert_botcha_element($form, $botcha_placement, $botcha_element);
}
switch ($form_id) {
case 'user_register':
if (FALSE === strpos($form['#action'], 'user/register')) {
if (!variable_get('botcha_allow_on_admin_pages', FALSE)) {
$botcha = FALSE;
}
}
break;
}
if ($botcha) {
$form += array(
'#input' => TRUE,
);
$form['#process'][] = 'botcha_fprocess';
module_load_include('inc', 'botcha', 'botcha.botcha');
botcha_form_alter_botcha($form, $form_state, $form_id, $botcha);
}
if ($form_id == 'system_performance_settings') {
$form['page_cache']['cache']['#description'] .= '<p><strong class="error">' . t('Warning: the BOTCHA module will disable caching of pages that contain forms processed by BOTCHA.') . '</strong></p>';
}
}
function botcha_fprocess($element, $edit, &$form_state, $complete_form) {
global $conf;
$conf['cache'] = CACHE_DISABLED;
unset($element['#cache']);
return $element;
}
function botcha_menu_alter(&$items) {
}
function _botcha_variables($i18n = FALSE) {
$ret = array();
if (!$i18n) {
$ret += array(
'botcha_secret',
'botcha_loglevel',
'botcha_form_passed_counter',
'botcha_form_blocked_counter',
);
}
return $ret;
}
function _botcha_i18n() {
$variables = _botcha_variables(TRUE);
$i18n_variables = variable_get('i18n_variables', array());
if (in_array($variables[0], $i18n_variables)) {
return;
}
$i18n_variables = array_merge($i18n_variables, $variables);
variable_set('i18n_variables', $i18n_variables);
}