updated imce, colorbox, admin_menu_source, honey_pot
This commit is contained in:
@@ -171,6 +171,11 @@ function honeypot_admin_form_validate($form, &$form_state) {
|
||||
form_set_error('honeypot_element_name', t("The element name cannot contain spaces or other special characters."));
|
||||
}
|
||||
|
||||
// Make sure Honeypot element name starts with a letter.
|
||||
if (!preg_match("/^[a-zA-Z].+$/", $form_state['values']['honeypot_element_name'])) {
|
||||
form_set_error('honeypot_element_name', t("The element name must start with a letter."));
|
||||
}
|
||||
|
||||
// Make sure Honeypot element name isn't one of the reserved names.
|
||||
$reserved_element_names = array(
|
||||
'name',
|
||||
|
@@ -6,9 +6,9 @@ package = "Spam control"
|
||||
|
||||
files[] = honeypot.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-09-04
|
||||
version = "7.x-1.21"
|
||||
; Information added by Drupal.org packaging script on 2016-03-11
|
||||
version = "7.x-1.22"
|
||||
core = "7.x"
|
||||
project = "honeypot"
|
||||
datestamp = "1441334340"
|
||||
datestamp = "1457672041"
|
||||
|
||||
|
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements of hook_schema().
|
||||
* Implements hook_schema().
|
||||
*/
|
||||
function honeypot_schema() {
|
||||
$schema['honeypot_user'] = array(
|
||||
@@ -18,6 +18,12 @@ function honeypot_schema() {
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'hostname' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
'description' => 'Hostname of user that that triggered honeypot.',
|
||||
),
|
||||
'timestamp' => array(
|
||||
'description' => 'Date/time when the form submission failed, as Unix timestamp.',
|
||||
'type' => 'int',
|
||||
@@ -146,3 +152,34 @@ function honeypot_update_7004() {
|
||||
module_load_include('inc', 'honeypot', 'honeypot.admin');
|
||||
honeypot_create_css(variable_get('honeypot_element_name', 'url'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the 'hostname' column to the {honeypot_user} table.
|
||||
*/
|
||||
function honeypot_update_7100() {
|
||||
$schema = honeypot_schema();
|
||||
$spec = $schema['honeypot_user']['fields']['hostname'];
|
||||
$spec['initial'] = '';
|
||||
db_add_field('honeypot_user', 'hostname', $spec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer previous honeypot trigger info from {flood} to {honeypot_user}.
|
||||
*/
|
||||
function honeypot_update_7101() {
|
||||
// Move all 'honeypot' events, which are honeypot captures for anonymous
|
||||
// users, to the {honeypot_user}-table, since the latter now supports
|
||||
// tracking based on ip/hostname for anonymous users.
|
||||
$query = db_select('flood', 'f')
|
||||
->condition('event', 'honeypot');
|
||||
$query->addExpression('0', 'uid');
|
||||
$query->addField('f', 'identifier', 'hostname');
|
||||
$query->addField('f', 'timestamp');
|
||||
db_insert('honeypot_user')
|
||||
->from($query)
|
||||
->execute();
|
||||
|
||||
// Clean up the flood table by removing our events, since we are no longer
|
||||
// relying on the flood mechanism to track anonymous honeypot captures.
|
||||
flood_clear_event('honeypot');
|
||||
}
|
||||
|
@@ -38,18 +38,19 @@ function honeypot_permission() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements of hook_cron().
|
||||
* Implements hook_cron().
|
||||
*/
|
||||
function honeypot_cron() {
|
||||
// Delete {honeypot_user} entries older than the value of honeypot_expire.
|
||||
db_delete('honeypot_user')
|
||||
->condition('timestamp', time() - variable_get('honeypot_expire', 300), '<')
|
||||
->condition('timestamp', REQUEST_TIME - variable_get('honeypot_expire', 300), '<')
|
||||
->execute();
|
||||
|
||||
// Regenerate the honeypot css file if it does not exist.
|
||||
// Regenerate the honeypot css file if it does not exist or is outdated.
|
||||
$honeypot_css = honeypot_get_css_file_path();
|
||||
if (!file_exists($honeypot_css)) {
|
||||
honeypot_create_css(variable_get('honeypot_element_name', 'url'));
|
||||
$honeypot_element_name = variable_get('honeypot_element_name', 'url');
|
||||
if (!file_exists($honeypot_css) || !honeypot_check_css($honeypot_element_name)) {
|
||||
honeypot_create_css($honeypot_element_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +112,7 @@ function honeypot_trigger_info() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_rules_event_info()
|
||||
* Implements hook_rules_event_info().
|
||||
*/
|
||||
function honeypot_rules_event_info() {
|
||||
return array(
|
||||
@@ -227,7 +228,7 @@ function honeypot_add_form_protection(&$form, &$form_state, $options = array())
|
||||
$form['honeypot_time'] = array(
|
||||
'#type' => 'hidden',
|
||||
'#title' => t('Timestamp'),
|
||||
'#default_value' => honeypot_get_signed_timestamp(time()),
|
||||
'#default_value' => honeypot_get_signed_timestamp(REQUEST_TIME),
|
||||
'#element_validate' => array('_honeypot_time_restriction_validate'),
|
||||
);
|
||||
|
||||
@@ -261,6 +262,11 @@ function _honeypot_honeypot_validate($element, &$form_state) {
|
||||
* Validate honeypot's time restriction field.
|
||||
*/
|
||||
function _honeypot_time_restriction_validate($element, &$form_state) {
|
||||
if (!empty($form_state['programmed'])) {
|
||||
// Don't do anything if the form was submitted programmatically.
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't do anything if the triggering element is a preview button.
|
||||
if ($form_state['triggering_element']['#value'] == t('Preview')) {
|
||||
return;
|
||||
@@ -274,11 +280,11 @@ function _honeypot_time_restriction_validate($element, &$form_state) {
|
||||
|
||||
// Make sure current time - (time_limit + form time value) is greater than 0.
|
||||
// If not, throw an error.
|
||||
if (!$honeypot_time || time() < ($honeypot_time + $time_limit)) {
|
||||
if (!$honeypot_time || REQUEST_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'] = honeypot_get_signed_timestamp(time());
|
||||
$form_state['values']['honeypot_time'] = honeypot_get_signed_timestamp(REQUEST_TIME);
|
||||
form_set_error('', t('There was a problem with your form submission. Please wait @limit seconds and try again.', array('@limit' => $time_limit)));
|
||||
}
|
||||
}
|
||||
@@ -317,21 +323,18 @@ 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 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() - $expire_time,
|
||||
))->fetchField();
|
||||
// Query the {honeypot_user} table to determine the number of failed
|
||||
// submissions for the current user.
|
||||
$query = db_select('honeypot_user', 'hs')
|
||||
->condition('uid', $user->uid)
|
||||
->condition('timestamp', REQUEST_TIME - $expire_time, '>');
|
||||
|
||||
// For anonymous users, take the hostname into account.
|
||||
if ($user->uid === 0) {
|
||||
$query->condition('hostname', ip_address());
|
||||
}
|
||||
$number = $query->countQuery()->execute()->fetchField();
|
||||
|
||||
// Don't add more than 30 days' worth of extra time.
|
||||
$honeypot_time_limit = (int) min($honeypot_time_limit + exp($number) - 1, 2592000);
|
||||
$additions = module_invoke_all('honeypot_time_limit', $honeypot_time_limit, $form_values, $number);
|
||||
@@ -339,11 +342,12 @@ function honeypot_get_time_limit($form_values = array()) {
|
||||
$honeypot_time_limit += array_sum($additions);
|
||||
}
|
||||
}
|
||||
|
||||
return $honeypot_time_limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the failed submision with timestamp.
|
||||
* Log the failed submision with timestamp and hostname.
|
||||
*
|
||||
* @param string $form_id
|
||||
* Form ID for the rejected form submission.
|
||||
@@ -355,19 +359,13 @@ function honeypot_get_time_limit($form_values = array()) {
|
||||
function honeypot_log_failure($form_id, $type) {
|
||||
global $user;
|
||||
|
||||
// Log failed submissions for authenticated users.
|
||||
if ($user->uid) {
|
||||
db_insert('honeypot_user')
|
||||
->fields(array(
|
||||
'uid' => $user->uid,
|
||||
'timestamp' => time(),
|
||||
))
|
||||
->execute();
|
||||
}
|
||||
// Register flood event for anonymous users.
|
||||
else {
|
||||
flood_register_event('honeypot');
|
||||
}
|
||||
db_insert('honeypot_user')
|
||||
->fields(array(
|
||||
'uid' => $user->uid,
|
||||
'hostname' => ip_address(),
|
||||
'timestamp' => REQUEST_TIME,
|
||||
))
|
||||
->execute();
|
||||
|
||||
// Allow other modules to react to honeypot rejections.
|
||||
module_invoke_all('honeypot_reject', $form_id, $user->uid, $type);
|
||||
@@ -422,6 +420,30 @@ function honeypot_create_css($element_name) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Honeypot's CSS file for a given Honeypot element name.
|
||||
*
|
||||
* This function assumes the Honeypot CSS file already exists.
|
||||
*
|
||||
* @param string $element_name
|
||||
* The honeypot element class name (e.g. 'url').
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if CSS is has element class name, FALSE if not.
|
||||
*/
|
||||
function honeypot_check_css($element_name) {
|
||||
$path = honeypot_get_css_file_path();
|
||||
$handle = fopen($path, 'r');
|
||||
$contents = fread($handle, filesize($path));
|
||||
fclose($handle);
|
||||
|
||||
if (strpos($contents, $element_name) === 1) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign the timestamp $time.
|
||||
*
|
||||
|
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test the functionality of the Honeypot module for an admin user.
|
||||
* Test the functionality of the Honeypot module for forms.
|
||||
*/
|
||||
class HoneypotFormTestCase extends DrupalWebTestCase {
|
||||
protected $adminUser;
|
||||
@@ -23,7 +23,7 @@ class HoneypotFormTestCase extends DrupalWebTestCase {
|
||||
|
||||
public function setUp() {
|
||||
// Enable modules required for this test.
|
||||
parent::setUp(array('honeypot', 'comment'));
|
||||
parent::setUp(array('honeypot', 'comment', 'honeypot_test'));
|
||||
|
||||
// Set up required Honeypot variables.
|
||||
variable_set('honeypot_element_name', 'url');
|
||||
@@ -169,6 +169,114 @@ class HoneypotFormTestCase extends DrupalWebTestCase {
|
||||
$this->drupalPost('node/add/article', $edit, t('Preview'));
|
||||
$this->assertNoText(t('There was a problem with your form submission.'), 'Honeypot not blocking node form previews.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test programmatic submission.
|
||||
*/
|
||||
public function testProgrammaticSubmission() {
|
||||
// Enable time limit protection.
|
||||
variable_set('honeypot_time_limit', 5);
|
||||
|
||||
// Create a user for which we are going to trigger the password reset.
|
||||
$edit = array();
|
||||
$edit['name'] = 'robo-user';
|
||||
$edit['mail'] = $edit['name'] . '@example.com';
|
||||
$edit['status'] = 1;
|
||||
user_save(drupal_anonymous_user(), $edit);
|
||||
|
||||
// Trigger the password reset through a programmatic submission.
|
||||
$this->drupalGet('honeypot_test/submit_form');
|
||||
|
||||
// Verify that the submission did not return any validation errors.
|
||||
$form_errors = drupal_json_decode($this->content);
|
||||
$this->assertNoRaw('There was a problem with your form submission. Please wait 6 seconds and try again.');
|
||||
$this->assertFalse($form_errors, 'The were no validation errors when submitting the form.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the functionality of the Honeypot module for an admin user.
|
||||
*/
|
||||
class HoneypotAdminFormTestCase extends DrupalWebTestCase {
|
||||
protected $adminUser;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Honeypot admin form',
|
||||
'description' => 'Ensure the Honeypot admin form functions properly.',
|
||||
'group' => 'Form API',
|
||||
);
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
// Enable modules required for this test.
|
||||
parent::setUp(array('honeypot'));
|
||||
|
||||
// Set up admin user.
|
||||
$this->adminUser = $this->drupalCreateUser(array(
|
||||
'administer honeypot',
|
||||
'bypass honeypot protection',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a valid element name.
|
||||
*/
|
||||
public function testElementNameUpdateSuccess() {
|
||||
// Log in the web user.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Set up form and submit it.
|
||||
$edit['honeypot_element_name'] = "test";
|
||||
$this->drupalPost('admin/config/content/honeypot', $edit, t('Save configuration'));
|
||||
|
||||
// Form should have been submitted successfully.
|
||||
$this->assertText(t('The configuration options have been saved.'), 'Honeypot element name assertion works for valid names.');
|
||||
|
||||
// Set up form and submit it.
|
||||
$edit['honeypot_element_name'] = "test-1";
|
||||
$this->drupalPost('admin/config/content/honeypot', $edit, t('Save configuration'));
|
||||
|
||||
// Form should have been submitted successfully.
|
||||
$this->assertText(t('The configuration options have been saved.'), 'Honeypot element name assertion works for valid names with dashes and numbers.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test an invalid element name (invalid first character).
|
||||
*/
|
||||
public function testElementNameUpdateFirstCharacterFail() {
|
||||
// Log in the admin user.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Set up form and submit it.
|
||||
$edit['honeypot_element_name'] = "1test";
|
||||
$this->drupalPost('admin/config/content/honeypot', $edit, t('Save configuration'));
|
||||
|
||||
// Form submission should fail.
|
||||
$this->assertText(t('The element name must start with a letter.'), 'Honeypot element name assertion works for invalid names.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test an invalid element name (invalid character in name).
|
||||
*/
|
||||
public function testElementNameUpdateInvalidCharacterFail() {
|
||||
// Log in the admin user.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Set up form and submit it.
|
||||
$edit['honeypot_element_name'] = "special-character-&";
|
||||
$this->drupalPost('admin/config/content/honeypot', $edit, t('Save configuration'));
|
||||
|
||||
// Form submission should fail.
|
||||
$this->assertText(t('The element name cannot contain spaces or other special characters.'), 'Honeypot element name assertion works for invalid names with special characters.');
|
||||
|
||||
// Set up form and submit it.
|
||||
$edit['honeypot_element_name'] = "space in name";
|
||||
$this->drupalPost('admin/config/content/honeypot', $edit, t('Save configuration'));
|
||||
|
||||
// Form submission should fail.
|
||||
$this->assertText(t('The element name cannot contain spaces or other special characters.'), 'Honeypot element name assertion works for invalid names with spaces.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,7 +319,7 @@ class HoneypotCssTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cron-based CSS file regeneration
|
||||
* Test cron-based CSS file regeneration.
|
||||
*/
|
||||
public function testHoneypotCssRegenerationOnCron() {
|
||||
$honeypot_css = honeypot_get_css_file_path();
|
||||
@@ -228,6 +336,36 @@ class HoneypotCssTestCase extends DrupalWebTestCase {
|
||||
// Make sure the Honeypot CSS file exists.
|
||||
$this->assertTrue(file_exists($honeypot_css));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cron-based CSS file update.
|
||||
*/
|
||||
public function testHoneypotCssUpdateOnCron() {
|
||||
$honeypot_css = honeypot_get_css_file_path();
|
||||
$original_element_name = variable_get('honeypot_element_name', 'url');
|
||||
|
||||
// Update the honeypot element name.
|
||||
variable_set('honeypot_element_name', 'test');
|
||||
|
||||
// Make sure the Honeypot CSS file still exists.
|
||||
$this->assertTrue(file_exists($honeypot_css));
|
||||
|
||||
// Run cron.
|
||||
honeypot_cron();
|
||||
|
||||
// Make sure the Honeypot CSS file was updated with the new element name.
|
||||
$handle = fopen($honeypot_css, 'r');
|
||||
$contents = fread($handle, filesize($honeypot_css));
|
||||
fclose($handle);
|
||||
$updated_element_name_in_css = (strpos($contents, 'test') === 1);
|
||||
$this->assertTrue($updated_element_name_in_css);
|
||||
|
||||
// For debug.
|
||||
$this->verbose($contents);
|
||||
|
||||
// Revert the honeypot element name back to the original.
|
||||
variable_set('honeypot_element_name', $original_element_name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,12 @@
|
||||
name = honepot_test
|
||||
description = Support module for Honeypot internal testing purposes.
|
||||
core = 7.x
|
||||
package = Testing
|
||||
hidden = true
|
||||
|
||||
; Information added by Drupal.org packaging script on 2016-03-11
|
||||
version = "7.x-1.22"
|
||||
core = "7.x"
|
||||
project = "honeypot"
|
||||
datestamp = "1457672041"
|
||||
|
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_menu().
|
||||
*/
|
||||
function honeypot_test_menu() {
|
||||
return array(
|
||||
'honeypot_test/submit_form' => array(
|
||||
'page callback' => 'honeypot_test_submit_form',
|
||||
'access callback' => TRUE,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Page callback: programmatically submit a form.
|
||||
*/
|
||||
function honeypot_test_submit_form() {
|
||||
module_load_include('inc', 'user', 'user.pages');
|
||||
$form_state = array();
|
||||
$form_state['values'] = array(
|
||||
'name' => 'robo-user',
|
||||
'mail' => 'robouser@example.com',
|
||||
'op' => t('E-mail new password'),
|
||||
);
|
||||
drupal_form_submit('user_pass', $form_state);
|
||||
$errors = form_get_errors();
|
||||
print drupal_json_encode($errors);
|
||||
exit();
|
||||
}
|
Reference in New Issue
Block a user