spamicide.module in Spamicide 6
Same filename and directory in other branches
This module provides yet another tool to eliminate spam.
File
spamicide.moduleView source
<?php
/**
* @defgroup spamicide Spamicide: another tool to eliminate spam.
*
* The spamicide module provides the ability to prevent spam being submitted to your site on various drupal forms.
*
* Author: Wes Roepken aka lipcpro (wes@lipcpro.com)
* Date: 04/29/2011
*/
/**
* @file
* This module provides yet another tool to eliminate spam.
*
* @ingroup spamicide
*/
/**
* Implementation of hook_menu().
*/
function spamicide_menu() {
$items = array();
$items['admin/settings/spamicide'] = array(
'title' => 'Spamicide',
'description' => 'Administer how and where Spamicide is used.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'spamicide_admin_form',
),
'access arguments' => array(
'administer spamicide',
),
'type' => MENU_NORMAL_ITEM,
);
// form for adding/editing spamicide form
$items['admin/settings/spamicide/spamicide_form/add/%'] = array(
'title' => 'Set Spamicide form',
'description' => 'Add or edit form_id\'s to protect with Spamicide.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'spamicide_admin_adform_form',
5,
TRUE,
),
'access arguments' => array(
'administer spamicide',
),
'type' => MENU_CALLBACK,
);
$items['admin/settings/spamicide/spamicide_form/delete/%'] = array(
'title' => 'Delete',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'spamicide_delete_confirm',
5,
TRUE,
),
'access arguments' => array(
'administer spamicide',
),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Implementation of hook_help().
*/
function spamicide_help($path, $arg) {
switch ($path) {
case 'admin/settings/spamicide':
return t('The spamicide module provides the ability to prevent spam being submitted to your site on various drupal forms');
case 'admin/help#spamicide':
$output = 'Spamicide';
$output .= '<p>' . t("Spamicide is intended to prevent spam without user interaction. Select the forms you'd like to attach spamicide to and a form field will be added but hidden by css. If the field is filled by anything (including humans that think they know better) it will prevent submission into you site.") . '</p>';
$output .= '<p>' . t('To add Spamicide to a form once you\'ve enabled adding admin links, navigate to that form, and click the link "Add Spamicide protection to this form"') . '</p>';
return $output;
}
}
/**
* Implementation of hook_perm().
*/
function spamicide_perm() {
return array(
'administer spamicide',
);
}
/**
* Implementation of hook_theme().
*/
function spamicide_theme() {
$spam_theme = array(
'spamicide_admin_settings_spamicide' => array(
'arguments' => array(
'form' => NULL,
),
),
'spamicide' => array(
'arguments' => array(
'form' => NULL,
),
),
);
/* $spam_fields = _spamicide_get_all_fields();
foreach($spam_fields as $key => $field) {
$spam_theme[$field] = array(
'arguments' => array('element' => NULL)
);
}//*/
return $spam_theme;
}
/**
* Form for spamicide administration
* @param $spamicide_form_id
* @return unknown_type
*/
function spamicide_admin_form($form) {
$form = array();
$form['spamicide_administration_mode'] = array(
'#type' => 'checkbox',
'#title' => t('Add Spamicide administration links to forms'),
'#default_value' => variable_get('spamicide_administration_mode', TRUE),
'#description' => t('This option will allow enabling/disabling Spamicide on forms. When enabled, users with the "%adminspamicide" permission will see Spamicide administration links on all forms (except on administrative pages, which shouldn\'t be accessible to untrusted users in the first place). These links make it possible to enable or disable it for the desired type.', array(
'%adminspamicide' => t('administer Spamicide settings'),
)),
);
$form['spamicide_forms'] = array(
'#type' => 'fieldset',
'#title' => t('Add Spamicide to a form or remove an added form'),
'#description' => t('Select from the listed forms (identified by their so called <em>form_id</em>\'s). You can easily add arbitrary forms with the help of the \'%spamicide_admin_links\' option.', array(
'%spamicide_admin_links' => t('Add Spamicide administration links to forms'),
'!add_spamicide' => url('admin/settings/spamicide/add_form'),
)),
'#tree' => TRUE,
'#collapsible' => TRUE,
'#collapsed' => FALSE,
'#theme' => 'spamicide_admin_settings_spamicide',
);
// list all possible form_id's
$result = db_query("SELECT * FROM {spamicide} ORDER BY form_id");
while ($spamicide = db_fetch_object($result)) {
$form['spamicide_forms'][$spamicide->form_id]['enabled'] = array(
'#type' => 'checkbox',
'#default_value' => $spamicide->enabled,
);
$form['spamicide_forms'][$spamicide->form_id]['form_id'] = array(
'#value' => $spamicide->form_id,
);
$form['spamicide_forms'][$spamicide->form_id]['form_field'] = array(
'#type' => 'textfield',
'#size' => 30,
'#default_value' => $spamicide->form_field,
);
// additional operations
if ($spamicide->removable) {
$form['spamicide_forms'][$spamicide->form_id]['operations'] = array(
'#value' => implode(", ", array(
l(t('delete'), "admin/settings/spamicide/spamicide_form/delete/{$spamicide->form_id}"),
)),
);
}
else {
$form['spamicide_forms'][$spamicide->form_id]['operations'] = array(
'#value' => "N/A",
);
}
}
$form['spamicide_log_attempts'] = array(
'#type' => 'checkbox',
'#title' => t('Log attempts'),
'#description' => t('Report information about attempts to the !watchdoglog.', array(
'!watchdoglog' => l(t('log'), 'admin/reports/watchdog'),
)),
'#default_value' => variable_get('spamicide_log_attempts', TRUE),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
/**
* Custom theme function
* @param $form
* @return unknown_type
*/
function theme_spamicide_admin_settings_spamicide($form) {
foreach (element_children($form) as $key) {
$row = array();
$row[] = drupal_render($form[$key]['enabled']);
$row[] = drupal_render($form[$key]['form_id']);
$row[] = drupal_render($form[$key]['form_field']);
$row[] = drupal_render($form[$key]['operations']);
$rows[] = $row;
}
$header = array(
'Enabled',
'Form_id',
'Form field name',
t('Delete'),
);
$output = theme('table', $header, $rows);
return $output;
}
/**
* Implementation of hook_form_validate
* Enter description here ...
* @param unknown_type $form
* @param unknown_type $form_state
*/
function spamicide_admin_form_validate($form, &$form_state) {
foreach ($form_state['values']['spamicide_forms'] as $spamicide_form_id => $data) {
if (preg_match_all('[\\W]', $data['form_field'], $str)) {
form_set_error('spamicide_forms][' . $spamicide_form_id . '][form_field', t("Only AlphaNumeric characters or the underscore please"));
}
}
}
/**
* Implementation of hook_form_submit
* @param $form
* @param $form_values
*/
function spamicide_admin_form_submit($form, &$form_state) {
variable_set('spamicide_administration_mode', $form_state['values']['spamicide_administration_mode']);
foreach ($form_state['values']['spamicide_forms'] as $spamicide_form_id => $data) {
if ($data['form_field'] != 'feed_me') {
_spamicide_set_css_file($data['form_field']);
}
db_query("UPDATE {spamicide} SET enabled = '%s', form_field = '%s' WHERE form_id = '%s'", $data['enabled'], $data['form_field'], $spamicide_form_id);
}
variable_set('spamicide_log_attempts', $form_state['values']['spamicide_log_attempts']);
drupal_set_message(t('The Spamicide settings were saved.'), 'status');
}
/**
* Form for adding spamicide functionality to an existing form
* @param $spamicide_form_id
* @return $form
*/
function spamicide_admin_adform_form($form, $spamicide_form_id = NULL) {
$form = array();
// use given spamicide form_id
$form['spamicide_form_id'] = array(
'#type' => 'textfield',
'#title' => t('Form ID'),
'#description' => t('The Drupal form_id of the form to add the Spamicide to.'),
'#value' => check_plain($spamicide_form_id),
'#disabled' => TRUE,
);
$form['spamicide_form_field'] = array(
'#type' => 'textfield',
'#title' => t('Form field'),
'#default_value' => 'feed_me',
'#description' => t('The name you want for the field. Use only letters, numbers, and the underscore character(_).'),
);
// redirect to general Spamicide settings page after submission
$form['#redirect'] = 'admin/settings/spamicide';
// submit button
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
/**
* Implementation of hook_form_submit
* @param $form
* @param $form_values
*/
function spamicide_admin_adform_form_submit($form, &$form_state) {
$spamicide_form_id = $form_state['values']['spamicide_form_id'];
// remove old settings
db_query("DELETE FROM {spamicide} WHERE form_id = '%s'", $spamicide_form_id);
// save new settings
db_query("INSERT INTO {spamicide} (form_id, form_field, enabled, removable) VALUES ('%s','%s', 1, 1)", $spamicide_form_id, $form_state['values']['spamicide_form_field']);
_spamicide_set_css_file($form_state['values']['spamicide_form_field']);
drupal_set_message(t('Saved Spamicide settings.'), 'status');
}
/**
* Confirm dialog for disabling/deleting a Spamicide
*
* @param $spamicide_form_id the form_id of the form to delete the Spamicide
* from
* @param $delete boolean for also deleting the Spamicide
*/
function spamicide_delete_confirm(&$form_state, $spamicide_form_id, $delete) {
$form = array();
$form['spamicide_form_id'] = array(
'#type' => 'value',
'#value' => $spamicide_form_id,
);
$form['spamicide_delete'] = array(
'#type' => 'value',
'#value' => $delete,
);
$message = t('Are you sure you want to delete the Spamicide for form_id %form_id?', array(
'%form_id' => $spamicide_form_id,
));
$yes = t('Delete');
return confirm_form($form, $message, isset($_GET['destination']) ? $_GET['destination'] : 'admin/settings/spamicide/spamicide_form', '', $yes);
}
/**
* submission handler of Spamicide delete confirm_form
*/
function spamicide_delete_confirm_submit($form, &$form_state) {
$spamicide_form_id = $form_state['values']['spamicide_form_id'];
$delete = $form_state['values']['spamicide_delete'];
db_query("DELETE FROM {spamicide} WHERE form_id = '%s'", $spamicide_form_id);
drupal_set_message(t('Deleted Spamicide for form %form_id.', array(
'%form_id' => $spamicide_form_id,
)));
// redirect to Spamicide admin
$form_state['redirect'] = 'admin/settings/spamicide';
}
/**
* Implementation of hook_form_alter
* @param $form_id
* @param $form
*/
function spamicide_form_alter(&$form, $form_state, $form_id) {
if (strpos($form_id, 'search') !== FALSE || strpos($form_id, 'update_script') !== FALSE) {
//ignore the search & update forms
return;
}
$spamicide_field = _spamicide_get_field($form_id);
if ($spamicide_field) {
$form['#pre_render'][] = '_spamicide_pre_render';
$spamicide_description = _spamicide_get_description();
$form[$spamicide_field] = array(
'#type' => 'textfield',
'#size' => 20,
'#description' => $spamicide_description,
'#name' => $spamicide_field,
'#post_render' => array(
'_spamicide_field_post_render',
),
);
$spam_fields = _spamicide_get_all_fields();
$form['destination'] = array(
'#type' => 'value',
'#value' => drupal_get_destination(),
);
$form['spamicide']['#element_validate'] = array(
'spamicide_validate',
);
spamicide_field_place_field($form, $form_id);
}
elseif (user_access('administer spamicide') && variable_get('spamicide_administration_mode', TRUE) && arg(0) != 'admin') {
$form['spamicide'] = array(
'#type' => 'fieldset',
'#title' => t('Spamicide'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['spamicide']['add_spamicide'] = array(
'#value' => l(t('Add Spamicide protection to this form.'), "admin/settings/spamicide/spamicide_form/add/{$form_id}", array()),
);
}
else {
return;
}
}
function _spamicide_pre_render($form) {
$spamicide_field = _spamicide_get_field($form['form_id']['#value']);
if ($spamicide_field == 'feed_me') {
drupal_add_css(drupal_get_path('module', 'spamicide') . '/feed_me.css');
}
else {
drupal_add_css(file_directory_path() . '/spamicide/' . $spamicide_field . '.css');
}
return $form;
}
/**
* Implementation of hook_validate
* @param $form_values
* @return none
*/
function spamicide_validate($form, &$form_state) {
$form_id = $form_state['values']['form_id'];
$spamicide_field = _spamicide_get_field($form_id);
if (!$spamicide_field) {
return;
}
elseif (empty($form_state['values'][$spamicide_field])) {
return;
}
else {
// update attempt counter
variable_set('spamicide_attempt_counter', variable_get('spamicide_attempt_counter', 0) + 1);
// log to watchdog if needed
if (variable_get('spamicide_log_attempts', TRUE)) {
watchdog('Spamicide', '%form_id post blocked by Spamicide module: their IP address is "%ipaddress".', array(
'%form_id' => $form_id,
'%ipaddress' => ip_address(),
), WATCHDOG_NOTICE);
}
// If Spamicide was on a login form: stop validating, quit the current request
// and forward to the current page (like a reload) to prevent logging in.
// We do that because the log in procedure, which happens after
// spamicide_validate(), does not check error conditions of extra form
// elements like the Spamicide.
if ($form_id == 'user_login' || $form_id == 'user_login_block') {
drupal_goto($_GET['q']);
}
else {
drupal_goto($form_state['values']['destination']);
}
}
}
/**
* Place the spamicide field just before the submit button
* @param $form_id
* @param $form
* @todo figure out how to make this work
*/
function spamicide_field_place_field(&$form, $form_id) {
// search the weights of the buttons in the form
$button_weights = array();
foreach (element_children($form) as $key) {
if ($key == 'buttons' || isset($form[$key]['#type']) && $form[$key]['#type'] == 'submit') {
if (!isset($form[$key]['#weight'])) {
/*
* forcing the issue of button weights
* Setting a weight if there isn't one
*/
$form[$key]['#weight'] = 1;
}
$button_weights[] = ++$form[$key]['#weight'];
}
}
if (!empty($button_weights)) {
/*
* forcing the issue of button weights
* push them all down 1
*/
$spamicide_weight = min($button_weights) - 1;
$spamicide_field = _spamicide_get_field($form_id);
if ($spamicide_field) {
$form[$spamicide_field]['#weight'] = $spamicide_weight;
}
else {
$form['spamicide']['#weight'] = $spamicide_weight;
}
// make sure the form gets sorted before rendering
unset($form['#sorted']);
}
return $form;
}
/**
* Get the spamicide field name and .css file_name
* @param $form
* @return the spamicide field name and .css file_name to call or FALSE
*/
function _spamicide_get_field(&$form) {
$result = db_query("SELECT enabled, form_field FROM {spamicide} WHERE form_id = '%s'", $form);
if ($result) {
$spamicide = db_fetch_object($result);
if (is_object($spamicide) && $spamicide->enabled) {
return $spamicide->form_field;
}
else {
return FALSE;
}
}
}
function _spamicide_get_all_fields() {
$spam_fields = array();
$result = db_query("SELECT form_field FROM {spamicide} ORDER BY form_field");
while ($spam_field = db_fetch_array($result)) {
$temp[] = $spam_field['form_field'];
}
foreach ($temp as $field) {
if (!in_array($field, $spam_fields)) {
$spam_fields[] = $field;
}
}
return $spam_fields;
}
/**
* Set the spamicide field name and .css file_name
* @param array $form_field
*/
function _spamicide_set_css_file($form_field) {
$spam_path = file_directory_path() . "/spamicide";
if (!file_check_directory($spam_path)) {
mkdir($spam_path);
}
$css_file = $spam_path . '/' . $form_field . '.css';
$path = file_create_path($css_file);
if (!file_exists($path)) {
$css = 'div.' . _spamicide_get_css_class($form_field) . ' { display:none; }';
file_save_data($css, $path, FILE_EXISTS_REPLACE);
}
}
/**
* Show translation if available
* @param $lang_code
* @return translated field description
* @todo change $default to be able to change it in the admin interface
* with the possibility of adding per form default description
*/
function _spamicide_get_description($lang_code = NULL) {
global $language;
$lang_code = isset($lang_code) ? $lang_code : $language->language;
$default = t('To prevent automated spam submissions leave this field empty.');
if (module_exists('locale')) {
$description = variable_get("spamicide_description_{$lang_code}", $default);
}
else {
$description = variable_get('spamicide_description', $default);
}
return $description;
}
/**
* #post_render callback on the spamicide field. This will wrap the field
* in a div so it can be hidden with CSS.
*
*/
function _spamicide_field_post_render($content, $element) {
return '<div class="' . _spamicide_get_css_class($element['#name']) . '">' . $content . '</div>';
}
/**
* Returns a CSS class name based on the field's name. Should be used
* to wrap around the field so it can be hidden.
*
* Note that it should be pretty generic so it can't be sniffed out
* by a spammer.
*
* @param string $name
* The field's name
* @return string
* The CSS class
*/
function _spamicide_get_css_class($name) {
return 'edit-' . str_replace('_', '-', $name) . '-wrapper';
}
Functions
Name | Description |
---|---|
spamicide_admin_adform_form | Form for adding spamicide functionality to an existing form |
spamicide_admin_adform_form_submit | Implementation of hook_form_submit |
spamicide_admin_form | Form for spamicide administration |
spamicide_admin_form_submit | Implementation of hook_form_submit |
spamicide_admin_form_validate | Implementation of hook_form_validate Enter description here ... |
spamicide_delete_confirm | Confirm dialog for disabling/deleting a Spamicide |
spamicide_delete_confirm_submit | submission handler of Spamicide delete confirm_form |
spamicide_field_place_field | Place the spamicide field just before the submit button |
spamicide_form_alter | Implementation of hook_form_alter |
spamicide_help | Implementation of hook_help(). |
spamicide_menu | Implementation of hook_menu(). |
spamicide_perm | Implementation of hook_perm(). |
spamicide_theme | Implementation of hook_theme(). |
spamicide_validate | Implementation of hook_validate |
theme_spamicide_admin_settings_spamicide | Custom theme function |
_spamicide_field_post_render | #post_render callback on the spamicide field. This will wrap the field in a div so it can be hidden with CSS. |
_spamicide_get_all_fields | |
_spamicide_get_css_class | Returns a CSS class name based on the field's name. Should be used to wrap around the field so it can be hidden. |
_spamicide_get_description | Show translation if available |
_spamicide_get_field | Get the spamicide field name and .css file_name |
_spamicide_pre_render | |
_spamicide_set_css_file | Set the spamicide field name and .css file_name |