diff --git a/sites/all/modules/contrib/admin/admin_menu_source/CHANGELOG.txt b/sites/all/modules/contrib/admin/admin_menu_source/CHANGELOG.txt new file mode 100644 index 00000000..3c43ba9f --- /dev/null +++ b/sites/all/modules/contrib/admin/admin_menu_source/CHANGELOG.txt @@ -0,0 +1,3 @@ +Admin Menu Source 7.x-1.1, 2016-04-01 +------------------- +- Issue #2634278 by Tommy Cox: Missed dependency of Menu module diff --git a/sites/all/modules/contrib/admin/admin_menu_source/admin_menu_source.inc b/sites/all/modules/contrib/admin/admin_menu_source/admin_menu_source.inc index d17c3cfc..8fe6245b 100644 --- a/sites/all/modules/contrib/admin/admin_menu_source/admin_menu_source.inc +++ b/sites/all/modules/contrib/admin/admin_menu_source/admin_menu_source.inc @@ -1,5 +1,4 @@ roles, TRUE)); - $source_menu = _admin_menu_source_get_role_menu($rid); - - if (!empty($source_menu)) { - $content['menu'] = admin_menu_links_menu(admin_menu_tree($source_menu)); - $content['menu']['#theme'] = 'admin_menu_links'; - $content['menu']['#weight'] = 0; - $content['menu']['#sorted'] = TRUE; + // $rid = key(array_reverse($user->roles, TRUE)); + + // Find the user role rid. + $roles_ids = array_keys(user_roles(TRUE, 'access administration menu')); + $user_roles_ids = array_keys($user->roles); + $user_roles = array_reverse(array_intersect($roles_ids, $user_roles_ids)); + + if (count($user_roles)) { + $rid = $user_roles[0]; + $source_menu = _admin_menu_source_get_role_menu($rid); + + if (!empty($source_menu)) { + $content['menu'] = admin_menu_links_menu(admin_menu_tree($source_menu)); + $content['menu']['#theme'] = 'admin_menu_links'; + $content['menu']['#weight'] = 0; + $content['menu']['#sorted'] = TRUE; + } } } @@ -97,20 +105,20 @@ function theme_admin_menu_source_settings_form($variables) { } /** - * Helper function to get settings for admin_menu_source + * Helper function to get settings for admin_menu_source. */ function _admin_menu_source_get_settings() { return variable_get('admin_menu_source_settings', array()); } /** - * Helper function to get source menu per role + * Helper function to get source menu per role. * * @param $rid * the user role id */ function _admin_menu_source_get_role_menu($rid) { - //load the settings + // Load the settings. $settings = _admin_menu_source_get_settings(); return isset($settings[$rid]['source']) ? $settings[$rid]['source'] : ''; diff --git a/sites/all/modules/contrib/files/imce/imce/README.txt b/sites/all/modules/contrib/files/imce/imce/README.txt index ac82c125..11515ee5 100644 --- a/sites/all/modules/contrib/files/imce/imce/README.txt +++ b/sites/all/modules/contrib/files/imce/imce/README.txt @@ -87,7 +87,7 @@ INTEGRATION BY URL When IMCE is opened using an url that contains &app=applicationName|fileProperty1@FieldId1|fileProperty2@FieldId2|... the specified fields are filled with the specified properties of the selected file. -Avaliable file properties are: url, name, size(formatted), width, height, date(formatted), bytes(integer size in bytes), time(integer date timestamp), id(file id for newly uploaded files, 0 or integer), relpath(rawurlencoded path relative to file directory path.) +Available file properties are: url, name, size(formatted), width, height, date(formatted), bytes(integer size in bytes), time(integer date timestamp), id(file id for newly uploaded files, 0 or integer), relpath(rawurlencoded path relative to file directory path.) In our CASE, we should open IMCE using this URL: /imce?app=myApp|url@urlField which contains our application name and our url field id @@ -177,5 +177,5 @@ imce.setMessage(msg, type): logs a message of the type(status, warning, error) NOTES: - All URL strings in the examples start with "/" considering the base path is "/". In case your drupal is running on a sub directory e.g, http://localhost/drupal, these URLs should start with "/drupal/". -There is a safer solution that does not require manual URL fixing: If the Drupal javascript object is avaliable in your page you can use Drupal.settings.basePath at the beginning of URLs (Drupal.settings.basePath+'?q=imce....'). Note that, this won't work with multilingual paths with language prefixes. +There is a safer solution that does not require manual URL fixing: If the Drupal javascript object is available in your page you can use Drupal.settings.basePath at the beginning of URLs (Drupal.settings.basePath+'?q=imce....'). Note that, this won't work with multilingual paths with language prefixes. - file and directory ids(names) used in imce.js are url encoded forms of original names. They are decoded using imce.decode and displayed in the lists. \ No newline at end of file diff --git a/sites/all/modules/contrib/files/imce/imce/imce.info b/sites/all/modules/contrib/files/imce/imce/imce.info index 9fd852c5..ac23626d 100644 --- a/sites/all/modules/contrib/files/imce/imce/imce.info +++ b/sites/all/modules/contrib/files/imce/imce/imce.info @@ -4,9 +4,9 @@ core = "7.x" package = "Media" configure = "admin/config/media/imce" -; Information added by Drupal.org packaging script on 2014-05-16 -version = "7.x-1.9" +; Information added by Drupal.org packaging script on 2016-03-30 +version = "7.x-1.10" core = "7.x" project = "imce" -datestamp = "1400275428" +datestamp = "1459346870" diff --git a/sites/all/modules/contrib/files/imce/imce/inc/imce.admin.inc b/sites/all/modules/contrib/files/imce/imce/inc/imce.admin.inc index c2d3625c..587aa474 100644 --- a/sites/all/modules/contrib/files/imce/imce/inc/imce.admin.inc +++ b/sites/all/modules/contrib/files/imce/imce/inc/imce.admin.inc @@ -247,14 +247,14 @@ function imce_profile_form($form, &$form_state, $pid = 0) { '#type' => 'textfield', '#title' => t('Maximum file size per upload'), '#default_value' => $profile['filesize'], - '#description' => t('Set to 0 to use the maximum value avaliable.') . ' ' . t('Your PHP settings limit the maximum file size per upload to %size.', array('%size' => format_size(file_upload_max_size()))), + '#description' => t('Set to 0 to use the maximum value available.') . ' ' . t('Your PHP settings limit the maximum file size per upload to %size.', array('%size' => format_size(file_upload_max_size()))), '#field_suffix' => t('MB'), ); $form['quota'] = array( '#type' => 'textfield', '#title' => t('Directory quota'), '#default_value' => $profile['quota'], - '#description' => t('Define the upload quota per directory.') . ' ' . t('Set to 0 to use the maximum value avaliable.'), + '#description' => t('Define the upload quota per directory.') . ' ' . t('Set to 0 to use the maximum value available.'), '#field_suffix' => t('MB'), ); $form['tuquota'] = array( diff --git a/sites/all/modules/contrib/files/imce/imce/inc/imce.js.inc b/sites/all/modules/contrib/files/imce/imce/inc/imce.js.inc index fce9d729..7e500c5e 100644 --- a/sites/all/modules/contrib/files/imce/imce/inc/imce.js.inc +++ b/sites/all/modules/contrib/files/imce/imce/inc/imce.js.inc @@ -12,7 +12,7 @@ function imce_js_navigate(&$imce) { return array( 'files' => theme('imce_file_list', array('imce_ref' => array('imce' => &$imce))), 'dirsize' => format_size($imce['dirsize']), - 'subdirectories' => array_map('rawurlencode', $imce['subdirectories']), + 'subdirectories' => array_map('rawurlencode', array_values($imce['subdirectories'])), 'perm' => $imce['perm'] ); } diff --git a/sites/all/modules/contrib/files/imce/imce/inc/imce.page.inc b/sites/all/modules/contrib/files/imce/imce/inc/imce.page.inc index ab52aa78..32e267c6 100644 --- a/sites/all/modules/contrib/files/imce/imce/inc/imce.page.inc +++ b/sites/all/modules/contrib/files/imce/imce/inc/imce.page.inc @@ -297,7 +297,7 @@ function imce_upload_submit($form, &$form_state) { //core bug #54223. if ($replace == FILE_EXISTS_RENAME) { - $name = basename($file->uri); + $name = drupal_basename($file->uri); if ($name != $file->filename) { $file->filename = $name; drupal_set_message(t('The file has been renamed to %filename.', array('%filename' => $file->filename))); @@ -494,7 +494,7 @@ function imce_resize_image($filename, &$imce, $width, $height, $copy = TRUE, $de if (!$destname || $destname == $filename) { $file->uri = $copy ? file_create_filename($filename, $destdir) : $imguri; } - $file->filename = basename($file->uri); + $file->filename = drupal_basename($file->uri); //check if a file having the same properties exists already. if (isset($imce['files'][$file->filename])) { @@ -807,7 +807,7 @@ function imce_process_directories(&$imce, $user) { } /** - * Return an avaliable directory for the profile. + * Return an available directory for the profile. */ function imce_working_directory(&$imce) { //Do not use session if there is only one directory assigned. @@ -923,7 +923,10 @@ function imce_subdirectories_accessible(&$imce) { return TRUE; } //checking only the first one is sufficient. - $dirname = ($imce['dir'] == '.' ? '' : $imce['dir'] . '/') . $imce['subdirectories'][0]; + $dirname = reset($imce['subdirectories']); + if ($imce['dir'] !== '.') { + $dirname = $imce['dir'] . '/' . $dirname; + } //check if any setting is applicable for this subdirectory through any directory in the list. foreach ($imce['directories'] as $name => $info) { @@ -1082,7 +1085,15 @@ function imce_dir_uri($imce, $dir = NULL) { if (!isset($dir)) { $dir = $imce['dir']; } - return $imce['scheme'] . '://' . ($dir == '.' ? '' : $dir . '/'); + $target = $dir === '.' ? '' : $dir; + $uri = $imce['scheme'] . '://' . $target; + // Uri is already normalized. Call alterers. + drupal_alter('file_stream_wrapper_uri_normalize', $uri, $imce['scheme'], $target); + // Add the slash + if (substr($uri, -1) !== '/') { + $uri .= '/'; + } + return $uri; } /** diff --git a/sites/all/modules/contrib/files/imce/imce/js/imce.js b/sites/all/modules/contrib/files/imce/imce/js/imce.js index 4e8948d0..49cc1569 100644 --- a/sites/all/modules/contrib/files/imce/imce/js/imce.js +++ b/sites/all/modules/contrib/files/imce/imce/js/imce.js @@ -161,19 +161,26 @@ fileRemove: function(fid) { //return a file object containing all properties. fileGet: function (fid) { + var file = imce.fileProps(fid); + if (file) { + file.name = imce.decode(fid); + file.url = imce.getURL(fid); + file.relpath = imce.getRelpath(fid); + file.id = imce.urlId[file.url] || 0; //file id for newly uploaded files + } + return file; +}, + +//return file properties embedded in html. +fileProps: function (fid) { var row = imce.fids[fid]; - var url = imce.getURL(fid); return row ? { - name: imce.decode(fid), - url: url, size: row.cells[1].innerHTML, bytes: row.cells[1].id * 1, width: row.cells[2].innerHTML * 1, height: row.cells[3].innerHTML * 1, date: row.cells[4].innerHTML, - time: row.cells[4].id * 1, - id: imce.urlId[url] || 0, //file id for newly uploaded files - relpath: (imce.conf.dir == '.' ? '' : imce.conf.dir +'/') + fid //rawurlencoded path relative to file directory path. + time: row.cells[4].id * 1 } : null; }, @@ -514,7 +521,8 @@ fopSettings: function (fop) { fopLoading: function(fop, state) { var el = imce.el('edit-'+ fop), func = state ? 'addClass' : 'removeClass'; if (el) { - $(el)[func]('loading').attr('disabled', state); + $(el)[func]('loading'); + el.disabled = state; } else { $(imce.ops[fop].li)[func]('loading'); @@ -626,7 +634,7 @@ resMsgs: function (msgs) { //return img markup imgHtml: function (fid, width, height) { - return ''+ imce.decodePlain(fid) +''; + return ''+ imce.decodePlain(fid) +''; }, //check if the file is an image @@ -675,9 +683,23 @@ serialNames: function () { }, //get file url. re-encode & and # for mod rewrite -getURL: function (fid) { - var path = (imce.conf.dir == '.' ? '' : imce.conf.dir +'/') + fid; - return imce.conf.furl + (imce.conf.modfix ? path.replace(/%(23|26)/g, '%25$1') : path); +getURL: function (fid, uncached) { + var url = imce.getRelpath(fid); + if (imce.conf.modfix) { + url = url.replace(/%(23|26)/g, '%25$1'); + } + url = imce.conf.furl + url; + if (uncached) { + var file = imce.fileProps(fid); + url += (url.indexOf('?') === -1 ? '?' : '&') + 's' + file.bytes + 'd' + file.time; + } + return url; +}, + +//get encoded file path relative to root. +getRelpath: function (fid) { + var dir = imce.conf.dir; + return (dir === '.' ? '' : dir + '/') + fid; }, //el. by id diff --git a/sites/all/modules/contrib/files/imce/imce/tpl/imce-file-list.tpl.php b/sites/all/modules/contrib/files/imce/imce/tpl/imce-file-list.tpl.php index 9447fa08..189eed42 100644 --- a/sites/all/modules/contrib/files/imce/imce/tpl/imce-file-list.tpl.php +++ b/sites/all/modules/contrib/files/imce/imce/tpl/imce-file-list.tpl.php @@ -2,7 +2,7 @@ $imce =& $imce_ref['imce'];//keep this line. /* - * Although the file list table here is avaliable for theming, + * Although the file list table here is available for theming, * it is not recommended to change the table structure, because * it is read and manipulated by javascript assuming this is the deafult structure. * You can always change the data created by format functions diff --git a/sites/all/modules/contrib/form/honeypot/honeypot.admin.inc b/sites/all/modules/contrib/form/honeypot/honeypot.admin.inc index f76edd4a..64e3ae42 100644 --- a/sites/all/modules/contrib/form/honeypot/honeypot.admin.inc +++ b/sites/all/modules/contrib/form/honeypot/honeypot.admin.inc @@ -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', diff --git a/sites/all/modules/contrib/form/honeypot/honeypot.info b/sites/all/modules/contrib/form/honeypot/honeypot.info index 92ba90d3..857d242e 100644 --- a/sites/all/modules/contrib/form/honeypot/honeypot.info +++ b/sites/all/modules/contrib/form/honeypot/honeypot.info @@ -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" diff --git a/sites/all/modules/contrib/form/honeypot/honeypot.install b/sites/all/modules/contrib/form/honeypot/honeypot.install index 7dd0f942..5a560525 100644 --- a/sites/all/modules/contrib/form/honeypot/honeypot.install +++ b/sites/all/modules/contrib/form/honeypot/honeypot.install @@ -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'); +} diff --git a/sites/all/modules/contrib/form/honeypot/honeypot.module b/sites/all/modules/contrib/form/honeypot/honeypot.module index 3fb54ad0..46f83ae6 100644 --- a/sites/all/modules/contrib/form/honeypot/honeypot.module +++ b/sites/all/modules/contrib/form/honeypot/honeypot.module @@ -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. * diff --git a/sites/all/modules/contrib/form/honeypot/honeypot.test b/sites/all/modules/contrib/form/honeypot/honeypot.test index 23fae24e..dd136b93 100644 --- a/sites/all/modules/contrib/form/honeypot/honeypot.test +++ b/sites/all/modules/contrib/form/honeypot/honeypot.test @@ -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); + } } /** diff --git a/sites/all/modules/contrib/form/honeypot/tests/honeypot_test.info b/sites/all/modules/contrib/form/honeypot/tests/honeypot_test.info new file mode 100644 index 00000000..7b0226ad --- /dev/null +++ b/sites/all/modules/contrib/form/honeypot/tests/honeypot_test.info @@ -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" + diff --git a/sites/all/modules/contrib/form/honeypot/tests/honeypot_test.module b/sites/all/modules/contrib/form/honeypot/tests/honeypot_test.module new file mode 100644 index 00000000..9e5918af --- /dev/null +++ b/sites/all/modules/contrib/form/honeypot/tests/honeypot_test.module @@ -0,0 +1,30 @@ + 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(); +} \ No newline at end of file diff --git a/sites/all/modules/contrib/theming/colorbox/colorbox-insert-image.tpl.php b/sites/all/modules/contrib/theming/colorbox/colorbox-insert-image.tpl.php index 623db20e..6144fc30 100644 --- a/sites/all/modules/contrib/theming/colorbox/colorbox-insert-image.tpl.php +++ b/sites/all/modules/contrib/theming/colorbox/colorbox-insert-image.tpl.php @@ -27,4 +27,6 @@ * use the file's name. i.e. __title_or_filename__. */ ?> -width="" height="" alt="__alt__" title="__title__" class="" /> + + width="" height="" alt="__alt__" title="__title__" class="" /> + diff --git a/sites/all/modules/contrib/theming/colorbox/colorbox.admin.inc b/sites/all/modules/contrib/theming/colorbox/colorbox.admin.inc index 002c50bb..44b030a2 100644 --- a/sites/all/modules/contrib/theming/colorbox/colorbox.admin.inc +++ b/sites/all/modules/contrib/theming/colorbox/colorbox.admin.inc @@ -250,12 +250,19 @@ function colorbox_admin_settings() { '#collapsible' => TRUE, '#collapsed' => TRUE, ); + $form['colorbox_advanced_settings']['colorbox_unique_token'] = array( + '#type' => 'radios', + '#title' => t('Unique per-request gallery token'), + '#options' => array(1 => t('On'), 0 => t('Off')), + '#default_value' => variable_get('colorbox_unique_token', 1), + '#description' => t('If On (default), Colorbox will add a unique per-request token to the gallery id to avoid images being added manually to galleries. The token was added as a security fix but some see the old behavoiur as an feature and this settings makes it possible to remove the token.'), + ); $form['colorbox_advanced_settings']['colorbox_mobile_detect'] = array( '#type' => 'radios', '#title' => t('Mobile detection'), '#options' => array(1 => t('On'), 0 => t('Off')), '#default_value' => variable_get('colorbox_mobile_detect', 1), - '#description' => t('If on (default) Colorbox will not be active for devices with a the max width set below.'), + '#description' => t('If On (default), Colorbox will not be active for devices with the max width set below.'), ); $form['colorbox_advanced_settings']['colorbox_mobile_device_width'] = array( '#type' => 'textfield', diff --git a/sites/all/modules/contrib/theming/colorbox/colorbox.api.php b/sites/all/modules/contrib/theming/colorbox/colorbox.api.php index 61495bab..9dbf4cd4 100644 --- a/sites/all/modules/contrib/theming/colorbox/colorbox.api.php +++ b/sites/all/modules/contrib/theming/colorbox/colorbox.api.php @@ -10,11 +10,11 @@ * * Implements hook_colorbox_settings_alter(). * - * @param $settings + * @param array $settings * An associative array of Colorbox settings. See the * @link http://colorpowered.com/colorbox/ Colorbox documentation @endlink * for the full list of supported parameters. - * @param $style + * @param string $style * The name of the active style plugin. If $style is 'none', no Colorbox * theme will be loaded. */ @@ -29,9 +29,9 @@ function hook_colorbox_settings_alter(&$settings, &$style) { } /** - * Allows to override activation of Colobox for the current URL. + * Allows to override activation of Colorbox for the current URL. * - * @param $active + * @param bool $active * A boolean indicating whether colorbox should be active for the current * URL or not. */ diff --git a/sites/all/modules/contrib/theming/colorbox/colorbox.info b/sites/all/modules/contrib/theming/colorbox/colorbox.info index 4b5fda87..23b153d3 100644 --- a/sites/all/modules/contrib/theming/colorbox/colorbox.info +++ b/sites/all/modules/contrib/theming/colorbox/colorbox.info @@ -6,9 +6,9 @@ configure = admin/config/media/colorbox files[] = views/colorbox_handler_field_colorbox.inc -; Information added by Drupal.org packaging script on 2015-10-01 -version = "7.x-2.10" +; Information added by Drupal.org packaging script on 2016-06-06 +version = "7.x-2.12" core = "7.x" project = "colorbox" -datestamp = "1443691449" +datestamp = "1465255741" diff --git a/sites/all/modules/contrib/theming/colorbox/colorbox.module b/sites/all/modules/contrib/theming/colorbox/colorbox.module index e3d94d23..23e2a037 100644 --- a/sites/all/modules/contrib/theming/colorbox/colorbox.module +++ b/sites/all/modules/contrib/theming/colorbox/colorbox.module @@ -6,9 +6,9 @@ */ /** - * The default path to the Colorbox directory. + * The minimum required version of the Colorbox plugin. */ -define('COLORBOX_MIN_PLUGIN_VERSION', '1.3.21.1'); +define('COLORBOX_MIN_PLUGIN_VERSION', '1.6.1'); /** @@ -56,8 +56,8 @@ function colorbox_theme() { */ function colorbox_init() { // Do not load colorbox during the Drupal installation process, e.g. if part - // of installation profiles. - if (!drupal_installation_attempted()) { + // of installation profiles. Only add the JavaScript and CSS on specified paths. + if (!drupal_installation_attempted() && _colorbox_active()) { _colorbox_doheader(); } } @@ -132,7 +132,7 @@ function colorbox_menu() { /** * Check if Colorbox should be active for the current URL. * - * @return + * @return bool * TRUE if Colorbox should be active for the current page. */ function _colorbox_active() { @@ -166,9 +166,6 @@ function _colorbox_doheader() { if ($already_added) { return; // Don't add the JavaScript and CSS multiple times. } - if (!_colorbox_active()) { - return; // Don't add the JavaScript and CSS on specified paths. - } // Insert options and translated strings as javascript settings. if (variable_get('colorbox_custom_settings_activate', 0)) { @@ -371,7 +368,7 @@ function colorbox_field_formatter_settings_form($field, $instance, $view_mode, $ '#type' => 'fieldset', '#title' => t('Replacement patterns'), '#theme' => 'token_tree', - '#token_types' => array($instance['entity_type'], 'file'), + '#token_types' => array_merge(array_keys($field['bundles']),array('file')), '#recursion_limit' => $recursion_limit, '#dialog' => TRUE, '#states' => array( @@ -495,6 +492,8 @@ function colorbox_field_formatter_view($entity_type, $entity, $field, $instance, /** * Implements hook_insert_styles(). + * + * @return array */ function colorbox_insert_styles() { $insert_styles = array(); @@ -517,7 +516,7 @@ function colorbox_insert_content($item, $style, $widget) { /** * Machine names normally need to be unique but that does not apply to galleries. * - * @return + * @return false * Always FALSE */ function colorbox_gallery_exists() { diff --git a/sites/all/modules/contrib/theming/colorbox/colorbox.theme.inc b/sites/all/modules/contrib/theming/colorbox/colorbox.theme.inc index 74ceaf88..76c4c0c3 100644 --- a/sites/all/modules/contrib/theming/colorbox/colorbox.theme.inc +++ b/sites/all/modules/contrib/theming/colorbox/colorbox.theme.inc @@ -8,12 +8,15 @@ /** * Returns HTML for an Colorbox image field formatter. * - * @param $variables + * @param array $variables * An associative array containing: * - item: An array of image data. * - image_style: An optional image style. * - path: An array containing the link 'path' and link 'options'. * + * @return string + * An HTML string representing the themed output. + * * @ingroup themeable */ function theme_colorbox_image_formatter($variables) { @@ -125,8 +128,8 @@ function theme_colorbox_image_formatter($variables) { } // If gallery id is not empty add unique per-request token to avoid images being added manually to galleries. - if (!empty($gallery_id)) { - // Check if gallery token has alrady been set, we need to reuse the token for the whole request. + if (!empty($gallery_id) && variable_get('colorbox_unique_token', 1)) { + // Check if gallery token has already been set, we need to reuse the token for the whole request. if (is_null($gallery_token)) { // We use a short token since randomness is not critical. $gallery_token = drupal_random_key(8); @@ -147,13 +150,16 @@ function theme_colorbox_image_formatter($variables) { /** * Returns HTML for an image using a specific Colorbox image style. * - * @param $variables + * @param array $variables * An associative array containing: * - image: image item as array. * - path: The path of the image that should be displayed in the Colorbox. * - title: The title text that will be used as a caption in the Colorbox. * - gid: Gallery id for Colorbox image grouping. * + * @return string + * An HTML string containing a link to the given path. + * * @ingroup themeable */ function theme_colorbox_imagefield($variables) { @@ -176,9 +182,8 @@ function theme_colorbox_imagefield($variables) { 'attributes' => array( 'title' => $variables['title'], 'class' => $class, - 'rel' => $variables['gid'], + 'data-colorbox-gallery' => $variables['gid'], ), - 'language' => array('language' => NULL), ); return l($image, $options['path'], $options); @@ -186,6 +191,8 @@ function theme_colorbox_imagefield($variables) { /** * Preprocess variables for the colorbox-insert-image.tpl.php file. + * + * @param array $variables */ function template_preprocess_colorbox_insert_image(&$variables) { $item = $variables['item']; diff --git a/sites/all/modules/contrib/theming/colorbox/drush/colorbox.drush.inc b/sites/all/modules/contrib/theming/colorbox/drush/colorbox.drush.inc index e45c40fe..2ff34424 100644 --- a/sites/all/modules/contrib/theming/colorbox/drush/colorbox.drush.inc +++ b/sites/all/modules/contrib/theming/colorbox/drush/colorbox.drush.inc @@ -23,7 +23,7 @@ define('COLORBOX_DOWNLOAD_PREFIX', 'colorbox-'); * * See `drush topic docs-commands` for a list of recognized keys. * - * @return + * @return array * An associative array describing your command(s). */ function colorbox_drush_command() { @@ -49,10 +49,10 @@ function colorbox_drush_command() { * This function is called whenever a drush user calls * 'drush help ' * - * @param + * @param string $section * A string with the help section (prepend with 'drush:') * - * @return + * @return string * A string with the help text for your command. */ function colorbox_drush_help($section) { @@ -63,14 +63,14 @@ function colorbox_drush_help($section) { } /** - * Implements drush_MODULE_post_pm_enable(). + * Implements drush_MODULE_pre_pm_enable(). */ -// function drush_colorbox_post_pm_enable() { -// $modules = func_get_args(); -// if (in_array('colorbox', $modules)) { -// drush_colorbox_plugin(); -// } -// } +function drush_colorbox_pre_pm_enable() { + $modules = drush_get_context('PM_ENABLE_MODULES'); + if (in_array('colorbox', $modules) && !drush_get_option('skip')) { + drush_colorbox_plugin(); + } +} /** * Command to download the Colorbox plugin. diff --git a/sites/all/modules/contrib/theming/colorbox/js/colorbox.js b/sites/all/modules/contrib/theming/colorbox/js/colorbox.js index cd0520bb..d17133b4 100644 --- a/sites/all/modules/contrib/theming/colorbox/js/colorbox.js +++ b/sites/all/modules/contrib/theming/colorbox/js/colorbox.js @@ -14,6 +14,16 @@ Drupal.behaviors.initColorbox = { } } + // Use "data-colorbox-gallery" if set otherwise use "rel". + settings.colorbox.rel = function () { + if ($(this).data('colorbox-gallery')) { + return $(this).data('colorbox-gallery'); + } + else { + return $(this).attr('rel'); + } + }; + $('.colorbox', context) .once('init-colorbox') .colorbox(settings.colorbox); diff --git a/sites/all/modules/contrib/theming/colorbox/js/colorbox_inline.js b/sites/all/modules/contrib/theming/colorbox/js/colorbox_inline.js index 0b27b655..2354ef87 100644 --- a/sites/all/modules/contrib/theming/colorbox/js/colorbox_inline.js +++ b/sites/all/modules/contrib/theming/colorbox/js/colorbox_inline.js @@ -5,6 +5,15 @@ Drupal.behaviors.initColorboxInline = { if (!$.isFunction($.colorbox) || typeof settings.colorbox === 'undefined') { return; } + + if (settings.colorbox.mobiledetect && window.matchMedia) { + // Disable Colorbox for small screens. + var mq = window.matchMedia("(max-device-width: " + settings.colorbox.mobiledevicewidth + ")"); + if (mq.matches) { + return; + } + } + $.urlParam = function(name, url){ if (name == 'fragment') { var results = new RegExp('(#[^&#]*)').exec(url); diff --git a/sites/all/modules/contrib/theming/colorbox/js/colorbox_load.js b/sites/all/modules/contrib/theming/colorbox/js/colorbox_load.js index 30e99a77..6d3c6767 100644 --- a/sites/all/modules/contrib/theming/colorbox/js/colorbox_load.js +++ b/sites/all/modules/contrib/theming/colorbox/js/colorbox_load.js @@ -5,6 +5,15 @@ Drupal.behaviors.initColorboxLoad = { if (!$.isFunction($.colorbox) || typeof settings.colorbox === 'undefined') { return; } + + if (settings.colorbox.mobiledetect && window.matchMedia) { + // Disable Colorbox for small screens. + var mq = window.matchMedia("(max-device-width: " + settings.colorbox.mobiledevicewidth + ")"); + if (mq.matches) { + return; + } + } + $.urlParams = function (url) { var p = {}, e,