updated date pathauto addressfield honeypot features modules
This commit is contained in:
@@ -32,7 +32,7 @@ function honeypot_admin_form($form, &$form_state) {
|
||||
$form['configuration']['honeypot_element_name'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Honeypot element name'),
|
||||
'#description' => t("The name of the Honeypot form field. It's usually most effective to use a generic name like email, homepage, or name, but this should be changed if it interferes with fields that are already in your forms. Must not contain spaces or special characters."),
|
||||
'#description' => t("The name of the Honeypot form field. It's usually most effective to use a generic name like email, homepage, or link, but this should be changed if it interferes with fields that are already in your forms. Must not contain spaces or special characters."),
|
||||
'#default_value' => variable_get('honeypot_element_name', 'url'),
|
||||
'#required' => TRUE,
|
||||
'#size' => 30,
|
||||
@@ -170,11 +170,25 @@ function honeypot_admin_form_validate($form, &$form_state) {
|
||||
if (!preg_match("/^[-_a-zA-Z0-9]+$/", $form_state['values']['honeypot_element_name'])) {
|
||||
form_set_error('honeypot_element_name', t("The element name cannot contain spaces or other special characters."));
|
||||
}
|
||||
|
||||
// Make sure Honeypot element name isn't one of the reserved names.
|
||||
$reserved_element_names = array(
|
||||
'name',
|
||||
'pass',
|
||||
'website',
|
||||
);
|
||||
if (in_array($form_state['values']['honeypot_element_name'], $reserved_element_names)) {
|
||||
form_set_error('honeypot_element_name', t("The element name cannot match one of the common Drupal form field names (e.g. @names).", array('@names' => implode(', ', $reserved_element_names))));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the honeypot form cache on submit.
|
||||
* Honeypot admin form submit callback.
|
||||
*/
|
||||
function honeypot_admin_form_submit($form, &$form_state) {
|
||||
// Create CSS file for honeypot.
|
||||
honeypot_create_css($form_state['values']['honeypot_element_name']);
|
||||
|
||||
// Clear the Honeypot form cache on submit.
|
||||
cache_clear_all('honeypot_protected_forms', 'cache');
|
||||
}
|
||||
|
@@ -6,9 +6,9 @@ package = "Spam control"
|
||||
|
||||
files[] = honeypot.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2014-05-30
|
||||
version = "7.x-1.17"
|
||||
; Information added by Drupal.org packaging script on 2015-09-04
|
||||
version = "7.x-1.21"
|
||||
core = "7.x"
|
||||
project = "honeypot"
|
||||
datestamp = "1401478128"
|
||||
datestamp = "1441334340"
|
||||
|
||||
|
@@ -37,10 +37,15 @@ function honeypot_schema() {
|
||||
* Implements hook_install().
|
||||
*/
|
||||
function honeypot_install() {
|
||||
$t = get_t();
|
||||
drupal_set_message($t("Honeypot installed successfully. Please !link to protect your forms from spam bots.", array(
|
||||
'!link' => l($t('configure Honeypot'), 'admin/config/content/honeypot'),
|
||||
)));
|
||||
// Create CSS file.
|
||||
honeypot_create_css(variable_get('honeypot_element_name', 'url'));
|
||||
|
||||
if (!drupal_is_cli()) {
|
||||
$t = get_t();
|
||||
drupal_set_message($t("Honeypot installed successfully. Please !link to protect your forms from spam bots.", array(
|
||||
'!link' => l($t('configure Honeypot'), 'admin/config/content/honeypot'),
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,6 +61,9 @@ function honeypot_uninstall() {
|
||||
cache_clear_all($table, 'cache');
|
||||
}
|
||||
}
|
||||
|
||||
// Delete 'honeypot' directory from public file directory.
|
||||
file_unmanaged_delete_recursive('public://honeypot');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,3 +137,12 @@ function honeypot_update_7003() {
|
||||
db_create_table('honeypot_user', $table);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Honeypot CSS file.
|
||||
*/
|
||||
function honeypot_update_7004() {
|
||||
drupal_load('module', 'honeypot');
|
||||
module_load_include('inc', 'honeypot', 'honeypot.admin');
|
||||
honeypot_create_css(variable_get('honeypot_element_name', 'url'));
|
||||
}
|
||||
|
@@ -45,6 +45,12 @@ function honeypot_cron() {
|
||||
db_delete('honeypot_user')
|
||||
->condition('timestamp', time() - variable_get('honeypot_expire', 300), '<')
|
||||
->execute();
|
||||
|
||||
// Regenerate the honeypot css file if it does not exist.
|
||||
$honeypot_css = honeypot_get_css_file_path();
|
||||
if (!file_exists($honeypot_css)) {
|
||||
honeypot_create_css(variable_get('honeypot_element_name', 'url'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,6 +148,7 @@ function honeypot_get_protected_forms() {
|
||||
$forms = $cache->data;
|
||||
}
|
||||
else {
|
||||
$forms = array();
|
||||
// Look up all the honeypot forms in the variables table.
|
||||
$result = db_query("SELECT name FROM {variable} WHERE name LIKE 'honeypot_form_%'")->fetchCol();
|
||||
// Add each form that's enabled to the $forms array.
|
||||
@@ -185,6 +192,15 @@ function honeypot_add_form_protection(&$form, &$form_state, $options = array())
|
||||
// Get the element name (default is generic 'url').
|
||||
$honeypot_element = variable_get('honeypot_element_name', 'url');
|
||||
|
||||
// Add 'autocomplete="off"' if configured.
|
||||
$attributes = array();
|
||||
if (variable_get('honeypot_autocomplete_attribute', 1)) {
|
||||
$attributes = array('autocomplete' => 'off');
|
||||
}
|
||||
|
||||
// Get the path to the honeypot css file.
|
||||
$honeypot_css = honeypot_get_css_file_path();
|
||||
|
||||
// Build the honeypot element.
|
||||
$honeypot_class = $honeypot_element . '-textfield';
|
||||
$form[$honeypot_element] = array(
|
||||
@@ -192,14 +208,14 @@ function honeypot_add_form_protection(&$form, &$form_state, $options = array())
|
||||
'#title' => t('Leave this field blank'),
|
||||
'#size' => 20,
|
||||
'#weight' => 100,
|
||||
'#attributes' => array('autocomplete' => 'off'),
|
||||
'#attributes' => $attributes,
|
||||
'#element_validate' => array('_honeypot_honeypot_validate'),
|
||||
'#prefix' => '<div class="' . $honeypot_class . '">',
|
||||
'#suffix' => '</div>',
|
||||
// Hide honeypot.
|
||||
// Hide honeypot using CSS.
|
||||
'#attached' => array(
|
||||
'css' => array(
|
||||
'.' . $honeypot_class . ' { display: none !important; }' => array('type' => 'inline'),
|
||||
'data' => $honeypot_css,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -211,13 +227,13 @@ function honeypot_add_form_protection(&$form, &$form_state, $options = array())
|
||||
$form['honeypot_time'] = array(
|
||||
'#type' => 'hidden',
|
||||
'#title' => t('Timestamp'),
|
||||
'#default_value' => time(),
|
||||
'#default_value' => honeypot_get_signed_timestamp(time()),
|
||||
'#element_validate' => array('_honeypot_time_restriction_validate'),
|
||||
);
|
||||
|
||||
// Disable page caching to make sure timestamp isn't cached.
|
||||
if (user_is_anonymous()) {
|
||||
$GLOBALS['conf']['cache'] = 0;
|
||||
drupal_page_is_cacheable(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,18 +267,18 @@ function _honeypot_time_restriction_validate($element, &$form_state) {
|
||||
}
|
||||
|
||||
// Get the time value.
|
||||
$honeypot_time = $form_state['values']['honeypot_time'];
|
||||
$honeypot_time = honeypot_get_time_from_signed_timestamp($form_state['values']['honeypot_time']);
|
||||
|
||||
// Get the honeypot_time_limit.
|
||||
$time_limit = honeypot_get_time_limit($form_state['values']);
|
||||
|
||||
// Make sure current time - (time_limit + form time value) is greater than 0.
|
||||
// If not, throw an error.
|
||||
if (time() < ($honeypot_time + $time_limit)) {
|
||||
if (!$honeypot_time || time() < ($honeypot_time + $time_limit)) {
|
||||
_honeypot_log($form_state['values']['form_id'], 'honeypot_time');
|
||||
// Get the time limit again, since it increases after first failure.
|
||||
$time_limit = honeypot_get_time_limit($form_state['values']);
|
||||
$form_state['values']['honeypot_time'] = time();
|
||||
$form_state['values']['honeypot_time'] = honeypot_get_signed_timestamp(time());
|
||||
form_set_error('', t('There was a problem with your form submission. Please wait @limit seconds and try again.', array('@limit' => $time_limit)));
|
||||
}
|
||||
}
|
||||
@@ -300,16 +316,20 @@ function honeypot_get_time_limit($form_values = array()) {
|
||||
|
||||
// Only calculate time limit if honeypot_time_limit has a value > 0.
|
||||
if ($honeypot_time_limit) {
|
||||
$expire_time = variable_get('honeypot_expire', 300);
|
||||
// Get value from {honeypot_user} table for authenticated users.
|
||||
if ($user->uid) {
|
||||
$number = db_query("SELECT COUNT(*) FROM {honeypot_user} WHERE uid = :uid", array(':uid' => $user->uid))->fetchField();
|
||||
$number = db_query("SELECT COUNT(*) FROM {honeypot_user} WHERE uid = :uid AND timestamp > :time", array(
|
||||
':uid' => $user->uid,
|
||||
':time' => time() - $expire_time,
|
||||
))->fetchField();
|
||||
}
|
||||
// Get value from {flood} table for anonymous users.
|
||||
else {
|
||||
$number = db_query("SELECT COUNT(*) FROM {flood} WHERE event = :event AND identifier = :hostname AND timestamp > :time", array(
|
||||
':event' => 'honeypot',
|
||||
':hostname' => ip_address(),
|
||||
':time' => time() - variable_get('honeypot_expire', 300),
|
||||
':time' => time() - $expire_time,
|
||||
))->fetchField();
|
||||
}
|
||||
// Don't add more than 30 days' worth of extra time.
|
||||
@@ -372,3 +392,76 @@ function honeypot_log_failure($form_id, $type) {
|
||||
rules_invoke_event('honeypot_reject', $form_id, $type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the location of the Honeypot CSS file.
|
||||
*
|
||||
* @return string
|
||||
* The path to the honeypot.css file.
|
||||
*/
|
||||
function honeypot_get_css_file_path() {
|
||||
return variable_get('file_public_path', conf_path() . '/files') . '/honeypot/honeypot.css';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create CSS file to hide the Honeypot field.
|
||||
*
|
||||
* @param string $element_name
|
||||
* The honeypot element class name (e.g. 'url').
|
||||
*/
|
||||
function honeypot_create_css($element_name) {
|
||||
$path = 'public://honeypot';
|
||||
|
||||
if (!file_prepare_directory($path, FILE_CREATE_DIRECTORY)) {
|
||||
drupal_set_message(t('Unable to create Honeypot CSS directory, %path. Check the permissions on your files directory.', array('%path' => file_uri_target($path))), 'error');
|
||||
}
|
||||
else {
|
||||
$filename = $path . '/honeypot.css';
|
||||
$data = '.' . $element_name . '-textfield { display: none !important; }';
|
||||
file_unmanaged_save_data($data, $filename, FILE_EXISTS_REPLACE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign the timestamp $time.
|
||||
*
|
||||
* @param mixed $time
|
||||
* The timestamp to sign.
|
||||
*
|
||||
* @return string
|
||||
* A signed timestamp in the form timestamp|HMAC.
|
||||
*/
|
||||
function honeypot_get_signed_timestamp($time) {
|
||||
return $time . '|' . drupal_hmac_base64($time, drupal_get_private_key());
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a signed timestamp.
|
||||
*
|
||||
* @param string $signed_timestamp
|
||||
* A timestamp concateneted with the signature
|
||||
*
|
||||
* @return int
|
||||
* The timestamp if the signature is correct, 0 otherwise.
|
||||
*/
|
||||
function honeypot_get_time_from_signed_timestamp($signed_timestamp) {
|
||||
$honeypot_time = 0;
|
||||
|
||||
// Fail fast if timestamp was forged or saved with an older Honeypot version.
|
||||
if (strpos($signed_timestamp, '|') === FALSE) {
|
||||
return $honeypot_time;
|
||||
}
|
||||
|
||||
list($timestamp, $received_hmac) = explode('|', $signed_timestamp);
|
||||
|
||||
if ($timestamp && $received_hmac) {
|
||||
$calculated_hmac = drupal_hmac_base64($timestamp, drupal_get_private_key());
|
||||
// Prevent leaking timing information, compare second order hmacs.
|
||||
$random_key = drupal_random_bytes(32);
|
||||
if (drupal_hmac_base64($calculated_hmac, $random_key) === drupal_hmac_base64($received_hmac, $random_key)) {
|
||||
$honeypot_time = $timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
return $honeypot_time;
|
||||
}
|
||||
|
@@ -171,6 +171,65 @@ class HoneypotFormTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Honeypot's CSS generation routines.
|
||||
*/
|
||||
class HoneypotCssTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Honeypot CSS tests',
|
||||
'description' => 'Ensure that Honeypot rebuilds its CSS file correctly.',
|
||||
'group' => 'Form API',
|
||||
);
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
// Enable modules required for this test.
|
||||
parent::setUp(array('honeypot'));
|
||||
|
||||
// Set up required Honeypot variables.
|
||||
variable_set('honeypot_element_name', 'url');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test CSS file regeneration.
|
||||
*/
|
||||
public function testHoneypotCssRegeneration() {
|
||||
$honeypot_css = honeypot_get_css_file_path();
|
||||
|
||||
// Delete the Honeypot CSS file (if it exists).
|
||||
file_unmanaged_delete($honeypot_css);
|
||||
|
||||
// Make sure the Honeypot CSS file doesn't exist.
|
||||
$this->assertFalse(file_exists($honeypot_css));
|
||||
|
||||
// Create the CSS file.
|
||||
honeypot_create_css(variable_get('honeypot_element_name', 'url'));
|
||||
|
||||
// Make sure the Honeypot CSS file exists.
|
||||
$this->assertTrue(file_exists($honeypot_css));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cron-based CSS file regeneration
|
||||
*/
|
||||
public function testHoneypotCssRegenerationOnCron() {
|
||||
$honeypot_css = honeypot_get_css_file_path();
|
||||
|
||||
// Delete the Honeypot CSS file (if it exists).
|
||||
file_unmanaged_delete($honeypot_css);
|
||||
|
||||
// Make sure the Honeypot CSS file doesn't exist.
|
||||
$this->assertFalse(file_exists($honeypot_css));
|
||||
|
||||
// Run cron.
|
||||
honeypot_cron();
|
||||
|
||||
// Make sure the Honeypot CSS file exists.
|
||||
$this->assertTrue(file_exists($honeypot_css));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the functionality of the Honeypot module's integration with Trigger.
|
||||
*/
|
||||
|
Reference in New Issue
Block a user