core security update
This commit is contained in:
@@ -7,8 +7,8 @@ files[] = aggregator.test
|
||||
configure = admin/config/services/aggregator/settings
|
||||
stylesheets[all][] = aggregator.css
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -72,7 +72,7 @@ function aggregator_aggregator_remove($feed) {
|
||||
*/
|
||||
function aggregator_form_aggregator_admin_form_alter(&$form, $form_state) {
|
||||
if (in_array('aggregator', variable_get('aggregator_processors', array('aggregator')))) {
|
||||
$info = module_invoke('aggregator', 'aggregator_process', 'info');
|
||||
$info = module_invoke('aggregator', 'aggregator_process_info');
|
||||
$items = drupal_map_assoc(array(3, 5, 10, 15, 20, 25), '_aggregator_items');
|
||||
$period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval');
|
||||
$period[AGGREGATOR_CLEAR_NEVER] = t('Never');
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -363,6 +363,31 @@ function hook_block_list_alter(&$blocks) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Act on block cache ID (cid) parts before the cid is generated.
|
||||
*
|
||||
* This hook allows you to add, remove or modify the custom keys used to
|
||||
* generate a block cache ID (by default, these keys are set to the block
|
||||
* module and delta). These keys will be combined with the standard ones
|
||||
* provided by drupal_render_cid_parts() to generate the final block cache ID.
|
||||
*
|
||||
* To change the cache granularity used by drupal_render_cid_parts(), this hook
|
||||
* cannot be used; instead, set the 'cache' key in the block's definition in
|
||||
* hook_block_info().
|
||||
*
|
||||
* @params $cid_parts
|
||||
* An array of elements used to build the cid.
|
||||
* @param $block
|
||||
* The block object being acted on.
|
||||
*
|
||||
* @see _block_get_cache_id()
|
||||
*/
|
||||
function hook_block_cid_parts_alter(&$cid_parts, $block) {
|
||||
global $user;
|
||||
// This example shows how to cache a block based on the user's timezone.
|
||||
$cid_parts[] = $user->timezone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup hooks".
|
||||
*/
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
files[] = block.test
|
||||
configure = admin/structure/block
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -24,7 +24,7 @@ Drupal.behaviors.blockSettingsSummary = {
|
||||
$('fieldset#edit-node-type', context).drupalSetSummary(function (context) {
|
||||
var vals = [];
|
||||
$('input[type="checkbox"]:checked', context).each(function () {
|
||||
vals.push($.trim($(this).next('label').text()));
|
||||
vals.push($.trim($(this).next('label').html()));
|
||||
});
|
||||
if (!vals.length) {
|
||||
vals.push(Drupal.t('Not restricted'));
|
||||
@@ -35,7 +35,7 @@ Drupal.behaviors.blockSettingsSummary = {
|
||||
$('fieldset#edit-role', context).drupalSetSummary(function (context) {
|
||||
var vals = [];
|
||||
$('input[type="checkbox"]:checked', context).each(function () {
|
||||
vals.push($.trim($(this).next('label').text()));
|
||||
vals.push($.trim($(this).next('label').html()));
|
||||
});
|
||||
if (!vals.length) {
|
||||
vals.push(Drupal.t('Not restricted'));
|
||||
@@ -49,7 +49,7 @@ Drupal.behaviors.blockSettingsSummary = {
|
||||
return Drupal.t('Not customizable');
|
||||
}
|
||||
else {
|
||||
return $radio.next('label').text();
|
||||
return $radio.next('label').html();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@ define('BLOCK_REGION_NONE', -1);
|
||||
define('BLOCK_CUSTOM_FIXED', 0);
|
||||
|
||||
/**
|
||||
* Shows this block by default, but lets individual users hide it.
|
||||
* Shows this block by default, but lets individual users hide it.
|
||||
*/
|
||||
define('BLOCK_CUSTOM_ENABLED', 1);
|
||||
|
||||
@@ -59,6 +59,7 @@ function block_help($path, $arg) {
|
||||
$output .= '<dd>' . t('Users with the <em>Administer blocks</em> permission can <a href="@block-add">add custom blocks</a>, which are then listed on the <a href="@blocks">Blocks administration page</a>. Once created, custom blocks behave just like default and module-generated blocks.', array('@blocks' => url('admin/structure/block'), '@block-add' => url('admin/structure/block/add'))) . '</dd>';
|
||||
$output .= '</dl>';
|
||||
return $output;
|
||||
|
||||
case 'admin/structure/block/add':
|
||||
return '<p>' . t('Use this page to create a new custom block.') . '</p>';
|
||||
}
|
||||
@@ -189,6 +190,7 @@ function _block_themes_access($theme) {
|
||||
* @param $theme
|
||||
* The theme whose blocks are being configured. If not set, the default theme
|
||||
* is assumed.
|
||||
*
|
||||
* @return
|
||||
* The theme that should be used for the block configuration page, or NULL
|
||||
* to indicate that the default theme should be used.
|
||||
@@ -283,8 +285,7 @@ function block_page_build(&$page) {
|
||||
// Append region description if we are rendering the regions demo page.
|
||||
$item = menu_get_item();
|
||||
if ($item['path'] == 'admin/structure/block/demo/' . $theme) {
|
||||
$visible_regions = array_keys(system_region_list($theme, REGIONS_VISIBLE));
|
||||
foreach ($visible_regions as $region) {
|
||||
foreach (system_region_list($theme, REGIONS_VISIBLE, FALSE) as $region) {
|
||||
$description = '<div class="block-region">' . $all_regions[$region] . '</div>';
|
||||
$page[$region]['block_description'] = array(
|
||||
'#markup' => $description,
|
||||
@@ -343,14 +344,17 @@ function _block_get_renderable_array($list = array()) {
|
||||
// to perform contextual actions on the help block, and the links needlessly
|
||||
// draw attention on it.
|
||||
if ($key != 'system_main' && $key != 'system_help') {
|
||||
$build[$key]['#contextual_links']['block'] = array('admin/structure/block/manage', array($block->module, $block->delta));
|
||||
$build[$key]['#contextual_links']['block'] = array(
|
||||
'admin/structure/block/manage',
|
||||
array($block->module, $block->delta),
|
||||
);
|
||||
}
|
||||
|
||||
$build[$key] += array(
|
||||
'#block' => $block,
|
||||
'#weight' => ++$weight,
|
||||
);
|
||||
$build[$key]['#theme_wrappers'][] ='block';
|
||||
$build[$key]['#theme_wrappers'][] = 'block';
|
||||
}
|
||||
$build['#sorted'] = TRUE;
|
||||
return $build;
|
||||
@@ -386,18 +390,20 @@ function _block_rehash($theme = NULL) {
|
||||
// Gather the blocks defined by modules.
|
||||
foreach (module_implements('block_info') as $module) {
|
||||
$module_blocks = module_invoke($module, 'block_info');
|
||||
$delta_list = array();
|
||||
foreach ($module_blocks as $delta => $block) {
|
||||
// Compile a condition to retrieve this block from the database.
|
||||
$condition = db_and()
|
||||
->condition('module', $module)
|
||||
->condition('delta', $delta);
|
||||
$or->condition($condition);
|
||||
// Add identifiers.
|
||||
$delta_list[] = $delta;
|
||||
$block['module'] = $module;
|
||||
$block['delta'] = $delta;
|
||||
$block['theme'] = $theme;
|
||||
$block['delta'] = $delta;
|
||||
$block['theme'] = $theme;
|
||||
$current_blocks[$module][$delta] = $block;
|
||||
}
|
||||
if (!empty($delta_list)) {
|
||||
$condition = db_and()->condition('module', $module)->condition('delta', $delta_list);
|
||||
$or->condition($condition);
|
||||
}
|
||||
}
|
||||
// Save the blocks defined in code for alter context.
|
||||
$code_blocks = $current_blocks;
|
||||
@@ -644,7 +650,8 @@ function block_theme_initialize($theme) {
|
||||
$regions = system_region_list($theme, REGIONS_VISIBLE);
|
||||
$result = db_query("SELECT * FROM {block} WHERE theme = :theme", array(':theme' => $default_theme), array('fetch' => PDO::FETCH_ASSOC));
|
||||
foreach ($result as $block) {
|
||||
// If the region isn't supported by the theme, assign the block to the theme's default region.
|
||||
// If the region isn't supported by the theme, assign the block to the
|
||||
// theme's default region.
|
||||
if ($block['status'] && !isset($regions[$block['region']])) {
|
||||
$block['region'] = system_default_region($theme);
|
||||
}
|
||||
@@ -812,17 +819,18 @@ function block_block_list_alter(&$blocks) {
|
||||
// with different case. Ex: /Page, /page, /PAGE.
|
||||
$pages = drupal_strtolower($block->pages);
|
||||
if ($block->visibility < BLOCK_VISIBILITY_PHP) {
|
||||
// Convert the Drupal path to lowercase
|
||||
// Convert the Drupal path to lowercase.
|
||||
$path = drupal_strtolower(drupal_get_path_alias($_GET['q']));
|
||||
// Compare the lowercase internal and lowercase path alias (if any).
|
||||
$page_match = drupal_match_path($path, $pages);
|
||||
if ($path != $_GET['q']) {
|
||||
$page_match = $page_match || drupal_match_path($_GET['q'], $pages);
|
||||
}
|
||||
// When $block->visibility has a value of 0 (BLOCK_VISIBILITY_NOTLISTED),
|
||||
// the block is displayed on all pages except those listed in $block->pages.
|
||||
// When set to 1 (BLOCK_VISIBILITY_LISTED), it is displayed only on those
|
||||
// pages listed in $block->pages.
|
||||
// When $block->visibility has a value of 0
|
||||
// (BLOCK_VISIBILITY_NOTLISTED), the block is displayed on all pages
|
||||
// except those listed in $block->pages. When set to 1
|
||||
// (BLOCK_VISIBILITY_LISTED), it is displayed only on those pages
|
||||
// listed in $block->pages.
|
||||
$page_match = !($block->visibility xor $page_match);
|
||||
}
|
||||
elseif (module_exists('php')) {
|
||||
@@ -845,7 +853,8 @@ function block_block_list_alter(&$blocks) {
|
||||
* Render the content and subject for a set of blocks.
|
||||
*
|
||||
* @param $region_blocks
|
||||
* An array of block objects such as returned for one region by _block_load_blocks().
|
||||
* An array of block objects such as returned for one region by
|
||||
* _block_load_blocks().
|
||||
*
|
||||
* @return
|
||||
* An array of visible blocks as expected by drupal_render().
|
||||
@@ -953,6 +962,8 @@ function _block_render_blocks($region_blocks) {
|
||||
* Theme and language contexts are automatically differentiated.
|
||||
*
|
||||
* @param $block
|
||||
* The block to get the cache_id from.
|
||||
*
|
||||
* @return
|
||||
* The string used as cache_id for the block.
|
||||
*/
|
||||
@@ -967,6 +978,7 @@ function _block_get_cache_id($block) {
|
||||
// Start with common sub-patterns: block identification, theme, language.
|
||||
$cid_parts[] = $block->module;
|
||||
$cid_parts[] = $block->delta;
|
||||
drupal_alter('block_cid_parts', $cid_parts, $block);
|
||||
$cid_parts = array_merge($cid_parts, drupal_render_cid_parts($block->cache));
|
||||
|
||||
return implode(':', $cid_parts);
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -13,8 +13,8 @@ regions[footer] = Footer
|
||||
regions[highlighted] = Highlighted
|
||||
regions[help] = Help
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = blog.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -152,7 +152,7 @@ function blog_menu_local_tasks_alter(&$data, $router_item, $root_path) {
|
||||
}
|
||||
}
|
||||
// Provide a helper action link to the author on the 'blog/%' page.
|
||||
elseif ($root_path == 'blog/%' && $router_item['page_arguments'][0]->uid == $user->uid) {
|
||||
elseif ($root_path == 'blog/%' && isset($router_item['page_arguments'][0]->uid) && $router_item['page_arguments'][0]->uid == $user->uid) {
|
||||
$data['actions']['output']['blog'] = array(
|
||||
'#theme' => 'menu_local_action',
|
||||
);
|
||||
|
@@ -7,8 +7,8 @@ files[] = book.test
|
||||
configure = admin/content/book/settings
|
||||
stylesheets[all][] = book.css
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = color.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -9,8 +9,8 @@ files[] = comment.test
|
||||
configure = admin/content/comment
|
||||
stylesheets[all][] = comment.css
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -13,7 +13,7 @@ class CommentHelperCase extends DrupalWebTestCase {
|
||||
function setUp() {
|
||||
parent::setUp('comment', 'search');
|
||||
// Create users and test node.
|
||||
$this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer comments', 'administer blocks', 'administer actions'));
|
||||
$this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer comments', 'administer blocks', 'administer actions', 'administer fields'));
|
||||
$this->web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'create article content', 'edit own comments'));
|
||||
$this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'uid' => $this->web_user->uid));
|
||||
}
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
files[] = contact.test
|
||||
configure = admin/structure/contact
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = contextual.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -7,8 +7,8 @@ files[] = dashboard.test
|
||||
dependencies[] = block
|
||||
configure = admin/dashboard/customize
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -294,11 +294,18 @@ function theme_dblog_message($variables) {
|
||||
else {
|
||||
$output = t($event->message, unserialize($event->variables));
|
||||
}
|
||||
// If the output is expected to be a link, strip all the tags and
|
||||
// special characters by using filter_xss() without any allowed tags.
|
||||
// If not, use filter_xss_admin() to allow some tags.
|
||||
if ($variables['link'] && isset($event->wid)) {
|
||||
// Truncate message to 56 chars.
|
||||
// Truncate message to 56 chars after stripping all the tags.
|
||||
$output = truncate_utf8(filter_xss($output, array()), 56, TRUE, TRUE);
|
||||
$output = l($output, 'admin/reports/event/' . $event->wid, array('html' => TRUE));
|
||||
}
|
||||
else {
|
||||
// Prevent XSS in log detail pages.
|
||||
$output = filter_xss_admin($output);
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = dblog.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -154,6 +154,15 @@ function dblog_update_7002() {
|
||||
db_add_index('watchdog', 'severity', array('severity'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Account for possible legacy systems where dblog was not installed.
|
||||
*/
|
||||
function dblog_update_7003() {
|
||||
if (!db_table_exists('watchdog')) {
|
||||
db_create_table('watchdog', drupal_get_schema_unprocessed('dblog', 'watchdog'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup updates-7.x-extra".
|
||||
*/
|
||||
|
@@ -144,20 +144,30 @@ function _dblog_get_message_types() {
|
||||
* Note: Some values may be truncated to meet database column size restrictions.
|
||||
*/
|
||||
function dblog_watchdog(array $log_entry) {
|
||||
Database::getConnection('default', 'default')->insert('watchdog')
|
||||
->fields(array(
|
||||
'uid' => $log_entry['uid'],
|
||||
'type' => substr($log_entry['type'], 0, 64),
|
||||
'message' => $log_entry['message'],
|
||||
'variables' => serialize($log_entry['variables']),
|
||||
'severity' => $log_entry['severity'],
|
||||
'link' => substr($log_entry['link'], 0, 255),
|
||||
'location' => $log_entry['request_uri'],
|
||||
'referer' => $log_entry['referer'],
|
||||
'hostname' => substr($log_entry['ip'], 0, 128),
|
||||
'timestamp' => $log_entry['timestamp'],
|
||||
))
|
||||
->execute();
|
||||
if (!function_exists('drupal_substr')) {
|
||||
require_once DRUPAL_ROOT . '/includes/unicode.inc';
|
||||
}
|
||||
try {
|
||||
Database::getConnection('default', 'default')->insert('watchdog')
|
||||
->fields(array(
|
||||
'uid' => $log_entry['uid'],
|
||||
'type' => drupal_substr($log_entry['type'], 0, 64),
|
||||
'message' => $log_entry['message'],
|
||||
'variables' => serialize($log_entry['variables']),
|
||||
'severity' => $log_entry['severity'],
|
||||
'link' => drupal_substr($log_entry['link'], 0, 255),
|
||||
'location' => $log_entry['request_uri'],
|
||||
'referer' => $log_entry['referer'],
|
||||
'hostname' => drupal_substr($log_entry['ip'], 0, 128),
|
||||
'timestamp' => $log_entry['timestamp'],
|
||||
))
|
||||
->execute();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// Exception is ignored so that watchdog does not break pages during the
|
||||
// installation process or is not able to create the watchdog table during
|
||||
// installation.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -119,13 +119,18 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
private function generateLogEntries($count, $type = 'custom', $severity = WATCHDOG_NOTICE) {
|
||||
global $base_root;
|
||||
|
||||
// This long URL makes it just a little bit harder to pass the link part of
|
||||
// the test with a mix of English words and a repeating series of random
|
||||
// percent-encoded Chinese characters.
|
||||
$link = urldecode('/content/xo%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A-lake-isabelle');
|
||||
|
||||
// Prepare the fields to be logged
|
||||
$log = array(
|
||||
'type' => $type,
|
||||
'message' => 'Log entry added to test the dblog row limit.',
|
||||
'variables' => array(),
|
||||
'severity' => $severity,
|
||||
'link' => NULL,
|
||||
'link' => $link,
|
||||
'user' => $this->big_user,
|
||||
'uid' => isset($this->big_user->uid) ? $this->big_user->uid : 0,
|
||||
'request_uri' => $base_root . request_uri(),
|
||||
@@ -515,6 +520,33 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
$this->assertText(t('Database log cleared.'), 'Confirmation message found');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that exceptions are caught in dblog_watchdog().
|
||||
*/
|
||||
protected function testDBLogException() {
|
||||
$log = array(
|
||||
'type' => 'custom',
|
||||
'message' => 'Log entry added to test watchdog handling of Exceptions.',
|
||||
'variables' => array(),
|
||||
'severity' => WATCHDOG_NOTICE,
|
||||
'link' => NULL,
|
||||
'user' => $this->big_user,
|
||||
'uid' => isset($this->big_user->uid) ? $this->big_user->uid : 0,
|
||||
'request_uri' => request_uri(),
|
||||
'referer' => $_SERVER['HTTP_REFERER'],
|
||||
'ip' => ip_address(),
|
||||
'timestamp' => REQUEST_TIME,
|
||||
);
|
||||
|
||||
// Remove watchdog table temporarily to simulate it missing during
|
||||
// installation.
|
||||
db_query("DROP TABLE {watchdog}");
|
||||
|
||||
// Add a watchdog entry.
|
||||
// This should not throw an Exception, but fail silently.
|
||||
dblog_watchdog($log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the database log event information from the browser page.
|
||||
*
|
||||
@@ -633,5 +665,32 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
// Document Object Model (DOM).
|
||||
$this->assertLink(html_entity_decode($message_text), 0, $message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure HTML tags are filtered out in the log detail page.
|
||||
*/
|
||||
public function testLogMessageSanitized() {
|
||||
$this->drupalLogin($this->big_user);
|
||||
|
||||
// Make sure dangerous HTML tags are filtered out in log detail page.
|
||||
$log = array(
|
||||
'uid' => 0,
|
||||
'type' => 'custom',
|
||||
'message' => "<script>alert('foo');</script> <strong>Lorem ipsum</strong>",
|
||||
'variables' => NULL,
|
||||
'severity' => WATCHDOG_NOTICE,
|
||||
'link' => 'foo/bar',
|
||||
'request_uri' => 'http://example.com?dblog=1',
|
||||
'referer' => 'http://example.org?dblog=2',
|
||||
'ip' => '0.0.1.0',
|
||||
'timestamp' => REQUEST_TIME,
|
||||
);
|
||||
dblog_watchdog($log);
|
||||
|
||||
$wid = db_query('SELECT MAX(wid) FROM {watchdog}')->fetchField();
|
||||
$this->drupalGet('admin/reports/event/' . $wid);
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoRaw("<script>alert('foo');</script>");
|
||||
$this->assertRaw("alert('foo'); <strong>Lorem ipsum</strong>");
|
||||
}
|
||||
}
|
||||
|
@@ -189,7 +189,7 @@ function field_create_field($field) {
|
||||
}
|
||||
|
||||
// Clear caches
|
||||
field_cache_clear(TRUE);
|
||||
field_cache_clear();
|
||||
|
||||
// Invoke external hooks after the cache is cleared for API consistency.
|
||||
module_invoke_all('field_create_field', $field);
|
||||
@@ -288,7 +288,7 @@ function field_update_field($field) {
|
||||
drupal_write_record('field_config', $field, $primary_key);
|
||||
|
||||
// Clear caches
|
||||
field_cache_clear(TRUE);
|
||||
field_cache_clear();
|
||||
|
||||
// Invoke external hooks after the cache is cleared for API consistency.
|
||||
module_invoke_all('field_update_field', $field, $prior_field, $has_data);
|
||||
@@ -430,7 +430,7 @@ function field_delete_field($field_name) {
|
||||
->execute();
|
||||
|
||||
// Clear the cache.
|
||||
field_cache_clear(TRUE);
|
||||
field_cache_clear();
|
||||
|
||||
module_invoke_all('field_delete_field', $field);
|
||||
}
|
||||
|
@@ -11,8 +11,8 @@ dependencies[] = field_sql_storage
|
||||
required = TRUE
|
||||
stylesheets[all][] = theme/field.css
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -612,10 +612,12 @@ class FieldInfo {
|
||||
// Fill in default values.
|
||||
$display += array(
|
||||
'label' => 'above',
|
||||
'type' => $field_type_info['default_formatter'],
|
||||
'settings' => array(),
|
||||
'weight' => 0,
|
||||
);
|
||||
if (empty($display['type'])) {
|
||||
$display['type'] = $field_type_info['default_formatter'];
|
||||
}
|
||||
if ($display['type'] != 'hidden') {
|
||||
$formatter_type_info = field_info_formatter_types($display['type']);
|
||||
// Fall back to default formatter if formatter type is not available.
|
||||
|
@@ -467,6 +467,27 @@ function field_update_7003() {
|
||||
// Empty update to force a rebuild of the registry.
|
||||
}
|
||||
|
||||
/**
|
||||
* Grant the new "administer fields" permission to trusted users.
|
||||
*/
|
||||
function field_update_7004() {
|
||||
// Assign the permission to anyone that already has a trusted core permission
|
||||
// that would have previously let them administer fields on an entity type.
|
||||
$rids = array();
|
||||
$permissions = array(
|
||||
'administer site configuration',
|
||||
'administer content types',
|
||||
'administer users',
|
||||
);
|
||||
foreach ($permissions as $permission) {
|
||||
$rids = array_merge($rids, array_keys(user_roles(FALSE, $permission)));
|
||||
}
|
||||
$rids = array_unique($rids);
|
||||
foreach ($rids as $rid) {
|
||||
_update_7000_user_role_grant_permissions($rid, array('administer fields'), 'field');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup updates-7.x-extra".
|
||||
*/
|
||||
|
@@ -316,6 +316,21 @@ function field_help($path, $arg) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_permission().
|
||||
*/
|
||||
function field_permission() {
|
||||
return array(
|
||||
'administer fields' => array(
|
||||
'title' => t('Administer fields'),
|
||||
'description' => t('Additional permissions are required based on what the fields are attached to (for example, <a href="@url">administer content types</a> to manage fields attached to content).', array(
|
||||
'@url' => '#module-node',
|
||||
)),
|
||||
'restrict access' => TRUE,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_theme().
|
||||
*/
|
||||
|
@@ -7,8 +7,8 @@ dependencies[] = field
|
||||
files[] = field_sql_storage.test
|
||||
required = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -223,7 +223,17 @@ function _field_sql_storage_schema($field) {
|
||||
foreach ($field['indexes'] as $index_name => $columns) {
|
||||
$real_name = _field_sql_storage_indexname($field['field_name'], $index_name);
|
||||
foreach ($columns as $column_name) {
|
||||
$current['indexes'][$real_name][] = _field_sql_storage_columnname($field['field_name'], $column_name);
|
||||
// Indexes can be specified as either a column name or an array with
|
||||
// column name and length. Allow for either case.
|
||||
if (is_array($column_name)) {
|
||||
$current['indexes'][$real_name][] = array(
|
||||
_field_sql_storage_columnname($field['field_name'], $column_name[0]),
|
||||
$column_name[1],
|
||||
);
|
||||
}
|
||||
else {
|
||||
$current['indexes'][$real_name][] = _field_sql_storage_columnname($field['field_name'], $column_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +342,17 @@ function field_sql_storage_field_storage_update_field($field, $prior_field, $has
|
||||
$real_name = _field_sql_storage_indexname($field['field_name'], $name);
|
||||
$real_columns = array();
|
||||
foreach ($columns as $column_name) {
|
||||
$real_columns[] = _field_sql_storage_columnname($field['field_name'], $column_name);
|
||||
// Indexes can be specified as either a column name or an array with
|
||||
// column name and length. Allow for either case.
|
||||
if (is_array($column_name)) {
|
||||
$real_columns[] = array(
|
||||
_field_sql_storage_columnname($field['field_name'], $column_name[0]),
|
||||
$column_name[1],
|
||||
);
|
||||
}
|
||||
else {
|
||||
$real_columns[] = _field_sql_storage_columnname($field['field_name'], $column_name);
|
||||
}
|
||||
}
|
||||
db_add_index($table, $real_name, $real_columns);
|
||||
db_add_index($revision_table, $real_name, $real_columns);
|
||||
|
@@ -355,14 +355,14 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
|
||||
field_attach_insert('test_entity', $entity);
|
||||
|
||||
// Add an index
|
||||
$field = array('field_name' => $field_name, 'indexes' => array('value' => array('value')));
|
||||
$field = array('field_name' => $field_name, 'indexes' => array('value' => array(array('value', 255))));
|
||||
field_update_field($field);
|
||||
foreach ($tables as $table) {
|
||||
$this->assertTrue(Database::getConnection()->schema()->indexExists($table, "{$field_name}_value"), format_string("Index on value created in %table", array('%table' => $table)));
|
||||
}
|
||||
|
||||
// Add a different index, removing the existing custom one.
|
||||
$field = array('field_name' => $field_name, 'indexes' => array('value_format' => array('value', 'format')));
|
||||
$field = array('field_name' => $field_name, 'indexes' => array('value_format' => array(array('value', 127), array('format', 127))));
|
||||
field_update_field($field);
|
||||
foreach ($tables as $table) {
|
||||
$this->assertTrue(Database::getConnection()->schema()->indexExists($table, "{$field_name}_value_format"), format_string("Index on value_format created in %table", array('%table' => $table)));
|
||||
|
@@ -7,8 +7,8 @@ dependencies[] = field
|
||||
dependencies[] = options
|
||||
files[] = tests/list.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -212,7 +212,7 @@ class ListFieldUITestCase extends FieldTestCase {
|
||||
parent::setUp('field_test', 'field_ui');
|
||||
|
||||
// Create test user.
|
||||
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy'));
|
||||
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy', 'administer fields'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Create content type, with underscores.
|
||||
|
@@ -5,8 +5,8 @@ package = Testing
|
||||
version = VERSION
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
dependencies[] = field
|
||||
files[] = number.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -188,7 +188,7 @@ function number_field_formatter_info() {
|
||||
'label' => t('Default'),
|
||||
'field types' => array('number_integer'),
|
||||
'settings' => array(
|
||||
'thousand_separator' => ' ',
|
||||
'thousand_separator' => '',
|
||||
// The 'decimal_separator' and 'scale' settings are not configurable
|
||||
// through the UI, and will therefore keep their default values. They
|
||||
// are only present so that the 'number_integer' and 'number_decimal'
|
||||
@@ -202,7 +202,7 @@ function number_field_formatter_info() {
|
||||
'label' => t('Default'),
|
||||
'field types' => array('number_decimal', 'number_float'),
|
||||
'settings' => array(
|
||||
'thousand_separator' => ' ',
|
||||
'thousand_separator' => '',
|
||||
'decimal_separator' => '.',
|
||||
'scale' => 2,
|
||||
'prefix_suffix' => TRUE,
|
||||
@@ -222,6 +222,8 @@ function number_field_formatter_settings_form($field, $instance, $view_mode, $fo
|
||||
$display = $instance['display'][$view_mode];
|
||||
$settings = $display['settings'];
|
||||
|
||||
$element = array();
|
||||
|
||||
if ($display['type'] == 'number_decimal' || $display['type'] == 'number_integer') {
|
||||
$options = array(
|
||||
'' => t('<none>'),
|
||||
|
@@ -23,7 +23,7 @@ class NumberFieldTestCase extends DrupalWebTestCase {
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('field_test');
|
||||
$this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer content types'));
|
||||
$this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer content types', 'administer fields'));
|
||||
$this->drupalLogin($this->web_user);
|
||||
}
|
||||
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
dependencies[] = field
|
||||
files[] = options.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -185,6 +185,7 @@ function _options_properties($type, $multiple, $required, $has_value) {
|
||||
$base = array(
|
||||
'filter_xss' => FALSE,
|
||||
'strip_tags' => FALSE,
|
||||
'strip_tags_and_unescape' => FALSE,
|
||||
'empty_option' => FALSE,
|
||||
'optgroups' => FALSE,
|
||||
);
|
||||
@@ -195,7 +196,7 @@ function _options_properties($type, $multiple, $required, $has_value) {
|
||||
case 'select':
|
||||
$properties = array(
|
||||
// Select boxes do not support any HTML tag.
|
||||
'strip_tags' => TRUE,
|
||||
'strip_tags_and_unescape' => TRUE,
|
||||
'optgroups' => TRUE,
|
||||
);
|
||||
if ($multiple) {
|
||||
@@ -271,9 +272,16 @@ function _options_prepare_options(&$options, $properties) {
|
||||
_options_prepare_options($options[$value], $properties);
|
||||
}
|
||||
else {
|
||||
// The 'strip_tags' option is deprecated. Use 'strip_tags_and_unescape'
|
||||
// when plain text is required (and where the output will be run through
|
||||
// check_plain() before being inserted back into HTML) or 'filter_xss'
|
||||
// when HTML is required.
|
||||
if ($properties['strip_tags']) {
|
||||
$options[$value] = strip_tags($label);
|
||||
}
|
||||
if ($properties['strip_tags_and_unescape']) {
|
||||
$options[$value] = decode_entities(strip_tags($label));
|
||||
}
|
||||
if ($properties['filter_xss']) {
|
||||
$options[$value] = field_filter_xss($label);
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
|
||||
'cardinality' => 1,
|
||||
'settings' => array(
|
||||
// Make sure that 0 works as an option.
|
||||
'allowed_values' => array(0 => 'Zero', 1 => 'One', 2 => 'Some <script>dangerous</script> & unescaped <strong>markup</strong>'),
|
||||
'allowed_values' => array(0 => 'Zero', 1 => 'One', 2 => 'Some <script>dangerous</script> & unescaped <strong>markup</strong>', 3 => 'Some HTML encoded markup with < & >'),
|
||||
),
|
||||
);
|
||||
$this->card_1 = field_create_field($this->card_1);
|
||||
@@ -54,7 +54,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
|
||||
$this->bool = field_create_field($this->bool);
|
||||
|
||||
// Create a web user.
|
||||
$this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content'));
|
||||
$this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer fields'));
|
||||
$this->drupalLogin($this->web_user);
|
||||
}
|
||||
|
||||
@@ -233,6 +233,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
|
||||
$this->assertNoOptionSelected("edit-card-1-$langcode", 1);
|
||||
$this->assertNoOptionSelected("edit-card-1-$langcode", 2);
|
||||
$this->assertRaw('Some dangerous & unescaped markup', 'Option text was properly filtered.');
|
||||
$this->assertRaw('Some HTML encoded markup with < & >', 'HTML entities in option text were properly handled and not double-encoded');
|
||||
|
||||
// Submit form: select invalid 'none' option.
|
||||
$edit = array("card_1[$langcode]" => '_none');
|
||||
@@ -459,7 +460,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
|
||||
$this->assertNoFieldChecked("edit-bool-$langcode");
|
||||
|
||||
// Create admin user.
|
||||
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy'));
|
||||
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy', 'administer fields'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Create a test field instance.
|
||||
|
@@ -7,8 +7,8 @@ dependencies[] = field
|
||||
files[] = text.test
|
||||
required = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -223,11 +223,13 @@ function text_field_formatter_settings_form($field, $instance, $view_mode, $form
|
||||
|
||||
if (strpos($display['type'], '_trimmed') !== FALSE) {
|
||||
$element['trim_length'] = array(
|
||||
'#title' => t('Trim length'),
|
||||
'#title' => t('Trimmed limit'),
|
||||
'#type' => 'textfield',
|
||||
'#field_suffix' => t('characters'),
|
||||
'#size' => 10,
|
||||
'#default_value' => $settings['trim_length'],
|
||||
'#element_validate' => array('element_validate_integer_positive'),
|
||||
'#description' => t('If the summary is not set, the trimmed %label field will be shorter than this character limit.', array('%label' => $instance['label'])),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
}
|
||||
@@ -245,7 +247,7 @@ function text_field_formatter_settings_summary($field, $instance, $view_mode) {
|
||||
$summary = '';
|
||||
|
||||
if (strpos($display['type'], '_trimmed') !== FALSE) {
|
||||
$summary = t('Trim length') . ': ' . check_plain($settings['trim_length']);
|
||||
$summary = t('Trimmed limit: @trim_length characters', array('@trim_length' => $settings['trim_length']));
|
||||
}
|
||||
|
||||
return $summary;
|
||||
|
@@ -424,6 +424,7 @@ class TextTranslationTestCase extends DrupalWebTestCase {
|
||||
'administer content types',
|
||||
'access administration pages',
|
||||
'bypass node access',
|
||||
'administer fields',
|
||||
filter_permission_name($full_html_format),
|
||||
));
|
||||
$this->translator = $this->drupalCreateUser(array('create article content', 'edit own article content', 'translate content'));
|
||||
|
@@ -6,8 +6,8 @@ files[] = field_test.entity.inc
|
||||
version = VERSION
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -2105,6 +2105,10 @@ function field_ui_next_destination($entity_type, $bundle) {
|
||||
$destinations = !empty($_REQUEST['destinations']) ? $_REQUEST['destinations'] : array();
|
||||
if (!empty($destinations)) {
|
||||
unset($_REQUEST['destinations']);
|
||||
}
|
||||
// Remove any external URLs.
|
||||
$destinations = array_diff($destinations, array_filter($destinations, 'url_is_external'));
|
||||
if ($destinations) {
|
||||
return field_ui_get_destinations($destinations);
|
||||
}
|
||||
$admin_path = _field_ui_bundle_admin_path($entity_type, $bundle);
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
dependencies[] = field
|
||||
files[] = field_ui.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -106,9 +106,19 @@ function field_ui_menu() {
|
||||
$access = array_intersect_key($bundle_info['admin'], drupal_map_assoc(array('access callback', 'access arguments')));
|
||||
$access += array(
|
||||
'access callback' => 'user_access',
|
||||
'access arguments' => array('administer site configuration'),
|
||||
'access arguments' => array('administer fields'),
|
||||
);
|
||||
|
||||
// Add the "administer fields" permission on top of the access
|
||||
// restriction because the field UI should only be accessible to
|
||||
// trusted users.
|
||||
if ($access['access callback'] != 'user_access' || $access['access arguments'] != array('administer fields')) {
|
||||
$access = array(
|
||||
'access callback' => 'field_ui_admin_access',
|
||||
'access arguments' => array($access['access callback'], $access['access arguments']),
|
||||
);
|
||||
}
|
||||
|
||||
$items["$path/fields"] = array(
|
||||
'title' => 'Manage fields',
|
||||
'page callback' => 'drupal_get_form',
|
||||
@@ -392,3 +402,13 @@ function field_ui_form_node_type_form_submit($form, &$form_state) {
|
||||
$form_state['redirect'] = _field_ui_bundle_admin_path('node', $form_state['values']['type']) .'/fields';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Access callback to determine if a user is allowed to use the field UI.
|
||||
*
|
||||
* Only grant access if the user has both the "administer fields" permission and
|
||||
* is granted access by the entity specific restrictions.
|
||||
*/
|
||||
function field_ui_admin_access($access_callback, $access_arguments) {
|
||||
return user_access('administer fields') && call_user_func_array($access_callback, $access_arguments);
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ class FieldUITestCase extends DrupalWebTestCase {
|
||||
parent::setUp($modules);
|
||||
|
||||
// Create test user.
|
||||
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy'));
|
||||
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy', 'administer fields'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Create content type, with underscores.
|
||||
@@ -445,6 +445,19 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
|
||||
$this->assertText(t('The machine-readable name is already in use. It must be unique.'));
|
||||
$this->assertUrl($url, array(), 'Stayed on the same page.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that external URLs in the 'destinations' query parameter are blocked.
|
||||
*/
|
||||
function testExternalDestinations() {
|
||||
$path = 'admin/structure/types/manage/article/fields/field_tags/field-settings';
|
||||
$options = array(
|
||||
'query' => array('destinations' => array('http://example.com')),
|
||||
);
|
||||
$this->drupalPost($path, NULL, t('Save field settings'), $options);
|
||||
|
||||
$this->assertUrl('admin/structure/types/manage/article/fields', array(), 'Stayed on the same site.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -682,7 +695,7 @@ class FieldUIAlterTestCase extends DrupalWebTestCase {
|
||||
parent::setUp(array('field_test'));
|
||||
|
||||
// Create test user.
|
||||
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer users'));
|
||||
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer users', 'administer fields'));
|
||||
$this->drupalLogin($admin_user);
|
||||
}
|
||||
|
||||
|
@@ -632,7 +632,7 @@ function file_field_widget_process($element, &$form_state, $form) {
|
||||
$element['#theme'] = 'file_widget';
|
||||
|
||||
// Add the display field if enabled.
|
||||
if (!empty($field['settings']['display_field']) && $item['fid']) {
|
||||
if (!empty($field['settings']['display_field'])) {
|
||||
$element['display'] = array(
|
||||
'#type' => empty($item['fid']) ? 'hidden' : 'checkbox',
|
||||
'#title' => t('Include file in display'),
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
dependencies[] = field
|
||||
files[] = tests/file.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -92,7 +92,7 @@ function file_theme() {
|
||||
'variables' => array('file' => NULL, 'icon_directory' => NULL),
|
||||
),
|
||||
'file_icon' => array(
|
||||
'variables' => array('file' => NULL, 'icon_directory' => NULL),
|
||||
'variables' => array('file' => NULL, 'icon_directory' => NULL, 'alt' => ''),
|
||||
),
|
||||
'file_managed_file' => array(
|
||||
'render element' => 'element',
|
||||
@@ -457,6 +457,17 @@ function file_managed_file_process($element, &$form_state, $form) {
|
||||
'#markup' => theme('file_link', array('file' => $element['#file'])) . ' ',
|
||||
'#weight' => -10,
|
||||
);
|
||||
// Anonymous users who have uploaded a temporary file need a
|
||||
// non-session-based token added so file_managed_file_value() can check
|
||||
// that they have permission to use this file on subsequent submissions of
|
||||
// the same form (for example, after an Ajax upload or form validation
|
||||
// error).
|
||||
if (!$GLOBALS['user']->uid && $element['#file']->status != FILE_STATUS_PERMANENT) {
|
||||
$element['fid_token'] = array(
|
||||
'#type' => 'hidden',
|
||||
'#value' => drupal_hmac_base64('file-' . $fid, drupal_get_private_key() . drupal_get_hash_salt()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the extension list to the page as JavaScript settings.
|
||||
@@ -529,14 +540,30 @@ function file_managed_file_value(&$element, $input = FALSE, $form_state = NULL)
|
||||
// publicly accessible, with no download restrictions; for security
|
||||
// reasons all other schemes must go through the file_download_access()
|
||||
// check.
|
||||
if (in_array(file_uri_scheme($file->uri), variable_get('file_public_schema', array('public'))) || file_download_access($file->uri)) {
|
||||
$fid = $file->fid;
|
||||
}
|
||||
// If the current user doesn't have access, don't let the file be
|
||||
// changed.
|
||||
else {
|
||||
if (!in_array(file_uri_scheme($file->uri), variable_get('file_public_schema', array('public'))) && !file_download_access($file->uri)) {
|
||||
$force_default = TRUE;
|
||||
}
|
||||
// Temporary files that belong to other users should never be allowed.
|
||||
elseif ($file->status != FILE_STATUS_PERMANENT) {
|
||||
if ($GLOBALS['user']->uid && $file->uid != $GLOBALS['user']->uid) {
|
||||
$force_default = TRUE;
|
||||
}
|
||||
// Since file ownership can't be determined for anonymous users, they
|
||||
// are not allowed to reuse temporary files at all. But they do need
|
||||
// to be able to reuse their own files from earlier submissions of
|
||||
// the same form, so to allow that, check for the token added by
|
||||
// file_managed_file_process().
|
||||
elseif (!$GLOBALS['user']->uid) {
|
||||
$token = drupal_array_get_nested_value($form_state['input'], array_merge($element['#parents'], array('fid_token')));
|
||||
if ($token !== drupal_hmac_base64('file-' . $file->fid, drupal_get_private_key() . drupal_get_hash_salt())) {
|
||||
$force_default = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If all checks pass, allow the file to be changed.
|
||||
if (!$force_default) {
|
||||
$fid = $file->fid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -749,7 +776,32 @@ function theme_file_link($variables) {
|
||||
$icon_directory = $variables['icon_directory'];
|
||||
|
||||
$url = file_create_url($file->uri);
|
||||
$icon = theme('file_icon', array('file' => $file, 'icon_directory' => $icon_directory));
|
||||
|
||||
// Human-readable names, for use as text-alternatives to icons.
|
||||
$mime_name = array(
|
||||
'application/msword' => t('Microsoft Office document icon'),
|
||||
'application/vnd.ms-excel' => t('Office spreadsheet icon'),
|
||||
'application/vnd.ms-powerpoint' => t('Office presentation icon'),
|
||||
'application/pdf' => t('PDF icon'),
|
||||
'video/quicktime' => t('Movie icon'),
|
||||
'audio/mpeg' => t('Audio icon'),
|
||||
'audio/wav' => t('Audio icon'),
|
||||
'image/jpeg' => t('Image icon'),
|
||||
'image/png' => t('Image icon'),
|
||||
'image/gif' => t('Image icon'),
|
||||
'application/zip' => t('Package icon'),
|
||||
'text/html' => t('HTML icon'),
|
||||
'text/plain' => t('Plain text icon'),
|
||||
'application/octet-stream' => t('Binary Data'),
|
||||
);
|
||||
|
||||
$mimetype = file_get_mimetype($file->uri);
|
||||
|
||||
$icon = theme('file_icon', array(
|
||||
'file' => $file,
|
||||
'icon_directory' => $icon_directory,
|
||||
'alt' => !empty($mime_name[$mimetype]) ? $mime_name[$mimetype] : t('File'),
|
||||
));
|
||||
|
||||
// Set options as per anchor format described at
|
||||
// http://microformats.org/wiki/file-format-examples
|
||||
@@ -779,16 +831,19 @@ function theme_file_link($variables) {
|
||||
* - file: A file object for which to make an icon.
|
||||
* - icon_directory: (optional) A path to a directory of icons to be used for
|
||||
* files. Defaults to the value of the "file_icon_directory" variable.
|
||||
* - alt: (optional) The alternative text to represent the icon in text-based
|
||||
* browsers. Defaults to an empty string.
|
||||
*
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_file_icon($variables) {
|
||||
$file = $variables['file'];
|
||||
$alt = $variables['alt'];
|
||||
$icon_directory = $variables['icon_directory'];
|
||||
|
||||
$mime = check_plain($file->filemime);
|
||||
$icon_url = file_icon_url($file, $icon_directory);
|
||||
return '<img class="file-icon" alt="" title="' . $mime . '" src="' . $icon_url . '" />';
|
||||
return '<img class="file-icon" alt="' . check_plain($alt) . '" title="' . $mime . '" src="' . $icon_url . '" />';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -22,7 +22,7 @@ class FileFieldTestCase extends DrupalWebTestCase {
|
||||
$modules[] = 'file';
|
||||
$modules[] = 'file_module_test';
|
||||
parent::setUp($modules);
|
||||
$this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer nodes', 'bypass node access'));
|
||||
$this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer nodes', 'bypass node access', 'administer fields'));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
}
|
||||
|
||||
@@ -218,6 +218,30 @@ class FileFieldTestCase extends DrupalWebTestCase {
|
||||
$message = isset($message) ? $message : format_string('File %file is permanent.', array('%file' => $file->uri));
|
||||
$this->assertTrue($file->status == FILE_STATUS_PERMANENT, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a temporary file, for a specific user.
|
||||
*
|
||||
* @param string $data
|
||||
* A string containing the contents of the file.
|
||||
* @param int $uid
|
||||
* The user ID of the file owner.
|
||||
*
|
||||
* @return object
|
||||
* A file object, or FALSE on error.
|
||||
*/
|
||||
function createTemporaryFile($data, $uid = NULL) {
|
||||
$file = file_save_data($data, NULL, NULL);
|
||||
|
||||
if ($file) {
|
||||
$file->uid = isset($uid) ? $uid : $this->admin_user->uid;
|
||||
// Change the file status to be temporary.
|
||||
$file->status = NULL;
|
||||
return file_save($file);
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,6 +401,18 @@ class FileManagedFileElementTestCase extends FileFieldTestCase {
|
||||
$this->drupalPost($path, array(), t('Save'));
|
||||
$this->assertRaw(t('The file id is %fid.', array('%fid' => 0)), 'Submitted without a file.');
|
||||
|
||||
// Submit with a file, but with an invalid form token. Ensure the file
|
||||
// was not saved.
|
||||
$last_fid_prior = $this->getLastFileId();
|
||||
$edit = array(
|
||||
'files[' . $input_base_name . ']' => drupal_realpath($test_file->uri),
|
||||
'form_token' => 'invalid token',
|
||||
);
|
||||
$this->drupalPost($path, $edit, t('Save'));
|
||||
$this->assertText('The form has become outdated. Copy any unsaved work in the form below');
|
||||
$last_fid = $this->getLastFileId();
|
||||
$this->assertEqual($last_fid_prior, $last_fid, 'File was not saved when uploaded with an invalid form token.');
|
||||
|
||||
// Submit a new file, without using the Upload button.
|
||||
$last_fid_prior = $this->getLastFileId();
|
||||
$edit = array('files[' . $input_base_name . ']' => drupal_realpath($test_file->uri));
|
||||
@@ -514,6 +550,120 @@ class FileFieldWidgetTestCase extends FileFieldTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests exploiting the temporary file removal of another user using fid.
|
||||
*/
|
||||
function testTemporaryFileRemovalExploit() {
|
||||
// Create a victim user.
|
||||
$victim_user = $this->drupalCreateUser();
|
||||
|
||||
// Create an attacker user.
|
||||
$attacker_user = $this->drupalCreateUser(array(
|
||||
'access content',
|
||||
'create page content',
|
||||
'edit any page content',
|
||||
));
|
||||
|
||||
// Log in as the attacker user.
|
||||
$this->drupalLogin($attacker_user);
|
||||
|
||||
// Perform tests using the newly created users.
|
||||
$this->doTestTemporaryFileRemovalExploit($victim_user->uid, $attacker_user->uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests exploiting the temporary file removal for anonymous users using fid.
|
||||
*/
|
||||
public function testTemporaryFileRemovalExploitAnonymous() {
|
||||
// Set up an anonymous victim user.
|
||||
$victim_uid = 0;
|
||||
|
||||
// Set up an anonymous attacker user.
|
||||
$attacker_uid = 0;
|
||||
|
||||
// Set up permissions for anonymous attacker user.
|
||||
user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
|
||||
'access content' => TRUE,
|
||||
'create page content' => TRUE,
|
||||
'edit any page content' => TRUE,
|
||||
));
|
||||
|
||||
// In order to simulate being the anonymous attacker user, we need to log
|
||||
// out here since setUp() has logged in the admin.
|
||||
$this->drupalLogout();
|
||||
|
||||
// Perform tests using the newly set up users.
|
||||
$this->doTestTemporaryFileRemovalExploit($victim_uid, $attacker_uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for testing exploiting the temporary file removal using fid.
|
||||
*
|
||||
* @param int $victim_uid
|
||||
* The victim user ID.
|
||||
* @param int $attacker_uid
|
||||
* The attacker user ID.
|
||||
*/
|
||||
protected function doTestTemporaryFileRemovalExploit($victim_uid, $attacker_uid) {
|
||||
// Use 'page' instead of 'article', so that the 'article' image field does
|
||||
// not conflict with this test. If in the future the 'page' type gets its
|
||||
// own default file or image field, this test can be made more robust by
|
||||
// using a custom node type.
|
||||
$type_name = 'page';
|
||||
$field_name = 'test_file_field';
|
||||
$this->createFileField($field_name, $type_name);
|
||||
|
||||
$test_file = $this->getTestFile('text');
|
||||
foreach (array('nojs', 'js') as $type) {
|
||||
// Create a temporary file owned by the anonymous victim user. This will be
|
||||
// as if they had uploaded the file, but not saved the node they were
|
||||
// editing or creating.
|
||||
$victim_tmp_file = $this->createTemporaryFile('some text', $victim_uid);
|
||||
$victim_tmp_file = file_load($victim_tmp_file->fid);
|
||||
$this->assertTrue($victim_tmp_file->status != FILE_STATUS_PERMANENT, 'New file saved to disk is temporary.');
|
||||
$this->assertFalse(empty($victim_tmp_file->fid), 'New file has a fid');
|
||||
$this->assertEqual($victim_uid, $victim_tmp_file->uid, 'New file belongs to the victim user');
|
||||
|
||||
// Have attacker create a new node with a different uploaded file and
|
||||
// ensure it got uploaded successfully.
|
||||
// @todo Can we test AJAX? See https://www.drupal.org/node/2538260
|
||||
$edit = array(
|
||||
'title' => $type . '-title',
|
||||
);
|
||||
|
||||
// Attach a file to a node.
|
||||
$langcode = LANGUAGE_NONE;
|
||||
$edit['files[' . $field_name . '_' . $langcode . '_0]'] = drupal_realpath($test_file->uri);
|
||||
$this->drupalPost("node/add/$type_name", $edit, 'Save');
|
||||
$node = $this->drupalGetNodeByTitle($edit['title']);
|
||||
$node_file = file_load($node->{$field_name}[$langcode][0]['fid']);
|
||||
$this->assertFileExists($node_file, 'New file saved to disk on node creation.');
|
||||
$this->assertEqual($attacker_uid, $node_file->uid, 'New file belongs to the attacker.');
|
||||
|
||||
// Ensure the file can be downloaded.
|
||||
$this->drupalGet(file_create_url($node_file->uri));
|
||||
$this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.');
|
||||
|
||||
// "Click" the remove button (emulating either a nojs or js submission).
|
||||
// In this POST request, the attacker "guesses" the fid of the victim's
|
||||
// temporary file and uses that to remove this file.
|
||||
$this->drupalGet('node/' . $node->nid . '/edit');
|
||||
switch ($type) {
|
||||
case 'nojs':
|
||||
$this->drupalPost(NULL, array("{$field_name}[$langcode][0][fid]" => (string) $victim_tmp_file->fid), 'Remove');
|
||||
break;
|
||||
case 'js':
|
||||
$button = $this->xpath('//input[@type="submit" and @value="Remove"]');
|
||||
$this->drupalPostAJAX(NULL, array("{$field_name}[$langcode][0][fid]" => (string) $victim_tmp_file->fid), array((string) $button[0]['name'] => (string) $button[0]['value']));
|
||||
break;
|
||||
}
|
||||
|
||||
// The victim's temporary file should not be removed by the attacker's
|
||||
// POST request.
|
||||
$this->assertFileExists($victim_tmp_file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests upload and remove buttons for multiple multi-valued File fields.
|
||||
*/
|
||||
@@ -939,6 +1089,34 @@ class FileFieldDisplayTestCase extends FileFieldTestCase {
|
||||
$this->assertRaw($field_name . '[' . LANGUAGE_NONE . '][0][display]', 'First file appears as expected.');
|
||||
$this->assertRaw($field_name . '[' . LANGUAGE_NONE . '][1][display]', 'Second file appears as expected.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests default display of File Field.
|
||||
*/
|
||||
function testDefaultFileFieldDisplay() {
|
||||
$field_name = strtolower($this->randomName());
|
||||
$type_name = 'article';
|
||||
$field_settings = array(
|
||||
'display_field' => '1',
|
||||
'display_default' => '0',
|
||||
);
|
||||
$instance_settings = array(
|
||||
'description_field' => '1',
|
||||
);
|
||||
$widget_settings = array();
|
||||
$this->createFileField($field_name, $type_name, $field_settings, $instance_settings, $widget_settings);
|
||||
$field = field_info_field($field_name);
|
||||
$instance = field_info_instance('node', $field_name, $type_name);
|
||||
|
||||
$test_file = $this->getTestFile('text');
|
||||
|
||||
// Create a new node with the uploaded file.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
|
||||
$this->drupalGet('node/' . $nid . '/edit');
|
||||
$this->assertFieldByXPath('//input[@type="checkbox" and @name="' . $field_name . '[und][0][display]"]', NULL, 'Default file display checkbox field exists.');
|
||||
$this->assertFieldByXPath('//input[@type="checkbox" and @name="' . $field_name . '[und][0][display]" and not(@checked)]', NULL, 'Default file display is off.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1325,3 +1503,178 @@ class FilePrivateTestCase extends FileFieldTestCase {
|
||||
$this->assertResponse(403, 'Confirmed that access is denied for the file without view field access permission after attempting to attach it to a new node.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm that file field submissions work correctly for anonymous visitors.
|
||||
*/
|
||||
class FileFieldAnonymousSubmission extends FileFieldTestCase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'File form anonymous submission',
|
||||
'description' => 'Test anonymous form submission.',
|
||||
'group' => 'File',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Allow node submissions by anonymous users.
|
||||
user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array(
|
||||
'create article content',
|
||||
'access content',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the basic node submission for an anonymous visitor.
|
||||
*/
|
||||
function testAnonymousNode() {
|
||||
$bundle_label = 'Article';
|
||||
$node_title = 'Test page';
|
||||
|
||||
// Load the node form.
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertResponse(200, 'Loaded the article node form.');
|
||||
$this->assertText(strip_tags(t('Create @name', array('@name' => $bundle_label))));
|
||||
|
||||
$edit = array(
|
||||
'title' => $node_title,
|
||||
'body[und][0][value]' => 'Test article',
|
||||
'body[und][0][format]' => 'filtered_html',
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
$this->assertResponse(200);
|
||||
$t_args = array('@type' => $bundle_label, '%title' => $node_title);
|
||||
$this->assertText(strip_tags(t('@type %title has been created.', $t_args)), 'The node was created.');
|
||||
$matches = array();
|
||||
if (preg_match('@node/(\d+)$@', $this->getUrl(), $matches)) {
|
||||
$nid = end($matches);
|
||||
$this->assertNotEqual($nid, 0, 'The node ID was extracted from the URL.');
|
||||
$node = node_load($nid);
|
||||
$this->assertNotEqual($node, NULL, 'The node was loaded successfully.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file submission for an anonymous visitor.
|
||||
*/
|
||||
function testAnonymousNodeWithFile() {
|
||||
$bundle_label = 'Article';
|
||||
$node_title = 'Test page';
|
||||
|
||||
// Load the node form.
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertResponse(200, 'Loaded the article node form.');
|
||||
$this->assertText(strip_tags(t('Create @name', array('@name' => $bundle_label))));
|
||||
|
||||
// Generate an image file.
|
||||
$image = $this->getTestImage();
|
||||
|
||||
// Submit the form.
|
||||
$edit = array(
|
||||
'title' => $node_title,
|
||||
'body[und][0][value]' => 'Test article',
|
||||
'body[und][0][format]' => 'filtered_html',
|
||||
'files[field_image_und_0]' => drupal_realpath($image->uri),
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
$this->assertResponse(200);
|
||||
$t_args = array('@type' => $bundle_label, '%title' => $node_title);
|
||||
$this->assertText(strip_tags(t('@type %title has been created.', $t_args)), 'The node was created.');
|
||||
$matches = array();
|
||||
if (preg_match('@node/(\d+)$@', $this->getUrl(), $matches)) {
|
||||
$nid = end($matches);
|
||||
$this->assertNotEqual($nid, 0, 'The node ID was extracted from the URL.');
|
||||
$node = node_load($nid);
|
||||
$this->assertNotEqual($node, NULL, 'The node was loaded successfully.');
|
||||
$this->assertEqual($node->field_image[LANGUAGE_NONE][0]['filename'], $image->filename, 'The image was uploaded successfully.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file submission for an anonymous visitor with a missing node title.
|
||||
*/
|
||||
function testAnonymousNodeWithFileWithoutTitle() {
|
||||
$this->drupalLogout();
|
||||
$this->_testNodeWithFileWithoutTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file submission for an authenticated user with a missing node title.
|
||||
*/
|
||||
function testAuthenticatedNodeWithFileWithoutTitle() {
|
||||
$admin_user = $this->drupalCreateUser(array(
|
||||
'bypass node access',
|
||||
'access content overview',
|
||||
'administer nodes',
|
||||
));
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->_testNodeWithFileWithoutTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to test file submissions with missing node titles.
|
||||
*/
|
||||
protected function _testNodeWithFileWithoutTitle() {
|
||||
$bundle_label = 'Article';
|
||||
$node_title = 'Test page';
|
||||
|
||||
// Load the node form.
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertResponse(200, 'Loaded the article node form.');
|
||||
$this->assertText(strip_tags(t('Create @name', array('@name' => $bundle_label))));
|
||||
|
||||
// Generate an image file.
|
||||
$image = $this->getTestImage();
|
||||
|
||||
// Submit the form but exclude the title field.
|
||||
$edit = array(
|
||||
'body[und][0][value]' => 'Test article',
|
||||
'body[und][0][format]' => 'filtered_html',
|
||||
'files[field_image_und_0]' => drupal_realpath($image->uri),
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
$this->assertResponse(200);
|
||||
$t_args = array('@type' => $bundle_label, '%title' => $node_title);
|
||||
$this->assertNoText(strip_tags(t('@type %title has been created.', $t_args)), 'The node was created.');
|
||||
$this->assertText(t('!name field is required.', array('!name' => t('Title'))));
|
||||
|
||||
// Submit the form again but this time with the missing title field. This
|
||||
// should still work.
|
||||
$edit = array(
|
||||
'title' => $node_title,
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
|
||||
// Confirm the final submission actually worked.
|
||||
$t_args = array('@type' => $bundle_label, '%title' => $node_title);
|
||||
$this->assertText(strip_tags(t('@type %title has been created.', $t_args)), 'The node was created.');
|
||||
$matches = array();
|
||||
if (preg_match('@node/(\d+)$@', $this->getUrl(), $matches)) {
|
||||
$nid = end($matches);
|
||||
$this->assertNotEqual($nid, 0, 'The node ID was extracted from the URL.');
|
||||
$node = node_load($nid);
|
||||
$this->assertNotEqual($node, NULL, 'The node was loaded successfully.');
|
||||
$this->assertEqual($node->field_image[LANGUAGE_NONE][0]['filename'], $image->filename, 'The image was uploaded successfully.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a test image.
|
||||
*
|
||||
* @return stdClass
|
||||
* A file object.
|
||||
*/
|
||||
function getTestImage() {
|
||||
// Get a file to upload.
|
||||
$file = current($this->drupalGetTestFiles('image'));
|
||||
|
||||
// Add a filesize property to files as would be read by file_load().
|
||||
$file->filesize = filesize($file->uri);
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -7,8 +7,8 @@ files[] = filter.test
|
||||
required = TRUE
|
||||
configure = admin/config/content/formats
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -93,6 +93,14 @@ function filter_menu() {
|
||||
'type' => MENU_SUGGESTED_ITEM,
|
||||
'file' => 'filter.pages.inc',
|
||||
);
|
||||
$items['filter/tips/%filter_format'] = array(
|
||||
'title' => 'Compose tips',
|
||||
'page callback' => 'filter_tips_long',
|
||||
'page arguments' => array(2),
|
||||
'access callback' => 'filter_access',
|
||||
'access arguments' => array(2),
|
||||
'file' => 'filter.pages.inc',
|
||||
);
|
||||
$items['admin/config/content/formats'] = array(
|
||||
'title' => 'Text formats',
|
||||
'description' => 'Configure how content input by users is filtered, including allowed HTML tags. Also allows enabling of module-provided filters.',
|
||||
@@ -340,6 +348,7 @@ function filter_admin_format_title($format) {
|
||||
function filter_permission() {
|
||||
$perms['administer filters'] = array(
|
||||
'title' => t('Administer text formats and filters'),
|
||||
'description' => t('Define how text is handled by combining filters into <a href="@url">text formats</a>.', array('@url' => url('admin/config/content/formats'))),
|
||||
'restrict access' => TRUE,
|
||||
);
|
||||
|
||||
@@ -1118,18 +1127,23 @@ function filter_dom_serialize($dom_document) {
|
||||
$body_node = $dom_document->getElementsByTagName('body')->item(0);
|
||||
$body_content = '';
|
||||
|
||||
foreach ($body_node->getElementsByTagName('script') as $node) {
|
||||
filter_dom_serialize_escape_cdata_element($dom_document, $node);
|
||||
}
|
||||
if ($body_node !== NULL) {
|
||||
foreach ($body_node->getElementsByTagName('script') as $node) {
|
||||
filter_dom_serialize_escape_cdata_element($dom_document, $node);
|
||||
}
|
||||
|
||||
foreach ($body_node->getElementsByTagName('style') as $node) {
|
||||
filter_dom_serialize_escape_cdata_element($dom_document, $node, '/*', '*/');
|
||||
}
|
||||
foreach ($body_node->getElementsByTagName('style') as $node) {
|
||||
filter_dom_serialize_escape_cdata_element($dom_document, $node, '/*', '*/');
|
||||
}
|
||||
|
||||
foreach ($body_node->childNodes as $child_node) {
|
||||
$body_content .= $dom_document->saveXML($child_node);
|
||||
foreach ($body_node->childNodes as $child_node) {
|
||||
$body_content .= $dom_document->saveXML($child_node);
|
||||
}
|
||||
return preg_replace('|<([^> ]*)/>|i', '<$1 />', $body_content);
|
||||
}
|
||||
else {
|
||||
return $body_content;
|
||||
}
|
||||
return preg_replace('|<([^> ]*)/>|i', '<$1 />', $body_content);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1483,7 +1497,7 @@ function _filter_url($text, $filter) {
|
||||
$tasks['_filter_url_parse_full_links'] = $pattern;
|
||||
|
||||
// Match e-mail addresses.
|
||||
$url_pattern = "[A-Za-z0-9._-]{1,254}@(?:$domain)";
|
||||
$url_pattern = "[A-Za-z0-9._+-]{1,254}@(?:$domain)";
|
||||
$pattern = "`($url_pattern)`";
|
||||
$tasks['_filter_url_parse_email_links'] = $pattern;
|
||||
|
||||
|
@@ -14,10 +14,9 @@
|
||||
* @see filter_menu()
|
||||
* @see theme_filter_tips()
|
||||
*/
|
||||
function filter_tips_long() {
|
||||
$format_id = arg(2);
|
||||
if ($format_id) {
|
||||
$output = theme('filter_tips', array('tips' => _filter_tips($format_id, TRUE), 'long' => TRUE));
|
||||
function filter_tips_long($format = NULL) {
|
||||
if (!empty($format)) {
|
||||
$output = theme('filter_tips', array('tips' => _filter_tips($format->format, TRUE), 'long' => TRUE));
|
||||
}
|
||||
else {
|
||||
$output = theme('filter_tips', array('tips' => _filter_tips(-1, TRUE), 'long' => TRUE));
|
||||
|
@@ -555,6 +555,27 @@ class FilterFormatAccessTestCase extends DrupalWebTestCase {
|
||||
$this->assertTrue(isset($options[$this->allowed_format->format]), 'The allowed text format appears as an option when adding a new node.');
|
||||
$this->assertFalse(isset($options[$this->disallowed_format->format]), 'The disallowed text format does not appear as an option when adding a new node.');
|
||||
$this->assertTrue(isset($options[filter_fallback_format()]), 'The fallback format appears as an option when adding a new node.');
|
||||
|
||||
// Check regular user access to the filter tips pages.
|
||||
$this->drupalGet('filter/tips/' . $this->allowed_format->format);
|
||||
$this->assertResponse(200);
|
||||
$this->drupalGet('filter/tips/' . $this->disallowed_format->format);
|
||||
$this->assertResponse(403);
|
||||
$this->drupalGet('filter/tips/' . filter_fallback_format());
|
||||
$this->assertResponse(200);
|
||||
$this->drupalGet('filter/tips/invalid-format');
|
||||
$this->assertResponse(404);
|
||||
|
||||
// Check admin user access to the filter tips pages.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->drupalGet('filter/tips/' . $this->allowed_format->format);
|
||||
$this->assertResponse(200);
|
||||
$this->drupalGet('filter/tips/' . $this->disallowed_format->format);
|
||||
$this->assertResponse(200);
|
||||
$this->drupalGet('filter/tips/' . filter_fallback_format());
|
||||
$this->assertResponse(200);
|
||||
$this->drupalGet('filter/tips/invalid-format');
|
||||
$this->assertResponse(404);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1099,8 +1120,12 @@ class FilterUnitTestCase extends DrupalUnitTestCase {
|
||||
$f = filter_xss("<img src=\"jav\0a\0\0cript:alert(0)\">", array('img'));
|
||||
$this->assertNoNormalized($f, 'cript', 'HTML scheme clearing evasion -- embedded nulls.');
|
||||
|
||||
$f = filter_xss('<img src="  javascript:alert(0)">', array('img'));
|
||||
$this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing evasion -- spaces and metacharacters before scheme.');
|
||||
// @todo This dataset currently fails under 5.4 because of
|
||||
// https://www.drupal.org/node/1210798. Restore after it's fixed.
|
||||
if (version_compare(PHP_VERSION, '5.4.0', '<')) {
|
||||
$f = filter_xss('<img src="  javascript:alert(0)">', array('img'));
|
||||
$this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing evasion -- spaces and metacharacters before scheme.');
|
||||
}
|
||||
|
||||
$f = filter_xss('<img src="vbscript:msgbox(0)">', array('img'));
|
||||
$this->assertNoNormalized($f, 'vbscript', 'HTML scheme clearing evasion -- another scheme.');
|
||||
@@ -1148,7 +1173,7 @@ class FilterUnitTestCase extends DrupalUnitTestCase {
|
||||
// Setup dummy filter object.
|
||||
$filter = new stdClass();
|
||||
$filter->settings = array(
|
||||
'allowed_html' => '<a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>',
|
||||
'allowed_html' => '<a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd> <test-element>',
|
||||
'filter_html_help' => 1,
|
||||
'filter_html_nofollow' => 0,
|
||||
);
|
||||
@@ -1184,6 +1209,10 @@ class FilterUnitTestCase extends DrupalUnitTestCase {
|
||||
|
||||
$f = _filter_html('<code onerror> </code>', $filter);
|
||||
$this->assertNoNormalized($f, 'onerror', 'HTML filter should remove empty on* attributes on default.');
|
||||
|
||||
// Custom tags are supported and should be allowed through.
|
||||
$f = _filter_html('<test-element></test-element>', $filter);
|
||||
$this->assertNormalized($f, 'test-element', 'HTML filter should allow custom elements.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1269,6 +1298,7 @@ class FilterUnitTestCase extends DrupalUnitTestCase {
|
||||
// Create a e-mail that is too long.
|
||||
$long_email = str_repeat('a', 254) . '@example.com';
|
||||
$too_long_email = str_repeat('b', 255) . '@example.com';
|
||||
$email_with_plus_sign = 'one+two@example.com';
|
||||
|
||||
|
||||
// Filter selection/pattern matching.
|
||||
@@ -1282,12 +1312,13 @@ http://example.com or www.example.com
|
||||
),
|
||||
// MAILTO URLs.
|
||||
'
|
||||
person@example.com or mailto:person2@example.com or ' . $long_email . ' but not ' . $too_long_email . '
|
||||
person@example.com or mailto:person2@example.com or ' . $email_with_plus_sign . ' or ' . $long_email . ' but not ' . $too_long_email . '
|
||||
' => array(
|
||||
'<a href="mailto:person@example.com">person@example.com</a>' => TRUE,
|
||||
'<a href="mailto:person2@example.com">mailto:person2@example.com</a>' => TRUE,
|
||||
'<a href="mailto:' . $long_email . '">' . $long_email . '</a>' => TRUE,
|
||||
'<a href="mailto:' . $too_long_email . '">' . $too_long_email . '</a>' => FALSE,
|
||||
'<a href="mailto:' . $email_with_plus_sign . '">' . $email_with_plus_sign . '</a>' => TRUE,
|
||||
),
|
||||
// URI parts and special characters.
|
||||
'
|
||||
@@ -1979,3 +2010,26 @@ class FilterSettingsTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests DOMDocument serialization.
|
||||
*/
|
||||
class FilterDOMSerializeTestCase extends DrupalWebTestCase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Serialization',
|
||||
'description' => 'Test serialization of DOMDocument objects.',
|
||||
'group' => 'Filter',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests empty DOMDocument object.
|
||||
*/
|
||||
function testFilterEmptyDOMSerialization() {
|
||||
$document = new DOMDocument();
|
||||
$result = filter_dom_serialize($document);
|
||||
$this->assertEqual('', $result);
|
||||
}
|
||||
}
|
||||
|
@@ -9,8 +9,8 @@ files[] = forum.test
|
||||
configure = admin/structure/forum
|
||||
stylesheets[all][] = forum.css
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Hooks provided by the Help module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup hooks
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provide online user help.
|
||||
*
|
||||
* By implementing hook_help(), a module can make documentation available to
|
||||
* the user for the module as a whole, or for specific paths. Help for
|
||||
* developers should usually be provided via function header comments in the
|
||||
* code, or in special API example files.
|
||||
*
|
||||
* For a detailed usage example, see page_example.module.
|
||||
*
|
||||
* @param $path
|
||||
* The router menu path, as defined in hook_menu(), for the help that is
|
||||
* being requested; e.g., 'admin/people' or 'user/register'. If the router
|
||||
* path includes a wildcard, then this will appear in $path as %, even if it
|
||||
* is a named %autoloader wildcard in the hook_menu() implementation; for
|
||||
* example, node pages would have $path equal to 'node/%' or 'node/%/view'.
|
||||
* To provide a help page for a whole module with a listing on admin/help,
|
||||
* your hook implementation should match a path with a special descriptor
|
||||
* after a "#" sign:
|
||||
* 'admin/help#modulename'
|
||||
* The main module help text, displayed on the admin/help/modulename
|
||||
* page and linked to from the admin/help page.
|
||||
* @param $arg
|
||||
* An array that corresponds to the return value of the arg() function, for
|
||||
* modules that want to provide help that is specific to certain values
|
||||
* of wildcards in $path. For example, you could provide help for the path
|
||||
* 'user/1' by looking for the path 'user/%' and $arg[1] == '1'. This given
|
||||
* array should always be used rather than directly invoking arg(), because
|
||||
* your hook implementation may be called for other purposes besides building
|
||||
* the current page's help. Note that depending on which module is invoking
|
||||
* hook_help, $arg may contain only empty strings. Regardless, $arg[0] to
|
||||
* $arg[11] will always be set.
|
||||
*
|
||||
* @return
|
||||
* A localized string containing the help text.
|
||||
*/
|
||||
function hook_help($path, $arg) {
|
||||
switch ($path) {
|
||||
// Main module help for the block module
|
||||
case 'admin/help#block':
|
||||
return '<p>' . t('Blocks are boxes of content rendered into an area, or region, of a web page. The default theme Bartik, for example, implements the regions "Sidebar first", "Sidebar second", "Featured", "Content", "Header", "Footer", etc., and a block may appear in any one of these areas. The <a href="@blocks">blocks administration page</a> provides a drag-and-drop interface for assigning a block to a region, and for controlling the order of blocks within regions.', array('@blocks' => url('admin/structure/block'))) . '</p>';
|
||||
|
||||
// Help for another path in the block module
|
||||
case 'admin/structure/block':
|
||||
return '<p>' . t('This page provides a drag-and-drop interface for assigning a block to a region, and for controlling the order of blocks within regions. Since not all themes implement the same regions, or display regions in the same way, blocks are positioned on a per-theme basis. Remember that your changes will not be saved until you click the <em>Save blocks</em> button at the bottom of the page.') . '</p>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup hooks".
|
||||
*/
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = help.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -7,8 +7,8 @@ dependencies[] = file
|
||||
files[] = image.test
|
||||
configure = admin/config/media/image-styles
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -64,7 +64,7 @@ function image_help($path, $arg) {
|
||||
$effect = image_effect_definition_load($arg[7]);
|
||||
return isset($effect['help']) ? ('<p>' . $effect['help'] . '</p>') : NULL;
|
||||
case 'admin/config/media/image-styles/edit/%/effects/%':
|
||||
$effect = ($arg[5] == 'add') ? image_effect_definition_load($arg[6]) : image_effect_load($arg[6], $arg[4]);
|
||||
$effect = ($arg[5] == 'add') ? image_effect_definition_load($arg[6]) : image_effect_load($arg[7], $arg[5]);
|
||||
return isset($effect['help']) ? ('<p>' . $effect['help'] . '</p>') : NULL;
|
||||
}
|
||||
}
|
||||
@@ -801,6 +801,8 @@ function image_style_options($include_empty = TRUE, $output = CHECK_PLAIN) {
|
||||
*
|
||||
* @param $style
|
||||
* The image style
|
||||
* @param $scheme
|
||||
* The file scheme, for example 'public' for public files.
|
||||
*/
|
||||
function image_style_deliver($style, $scheme) {
|
||||
$args = func_get_args();
|
||||
@@ -833,8 +835,8 @@ function image_style_deliver($style, $scheme) {
|
||||
file_download($scheme, file_uri_target($derivative_uri));
|
||||
}
|
||||
else {
|
||||
$headers = module_invoke_all('file_download', $image_uri);
|
||||
if (in_array(-1, $headers) || empty($headers)) {
|
||||
$headers = file_download_headers($image_uri);
|
||||
if (empty($headers)) {
|
||||
return MENU_ACCESS_DENIED;
|
||||
}
|
||||
if (count($headers)) {
|
||||
|
@@ -32,7 +32,7 @@ class ImageFieldTestCase extends DrupalWebTestCase {
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('image');
|
||||
$this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer content types', 'administer nodes', 'create article content', 'edit any article content', 'delete any article content', 'administer image styles'));
|
||||
$this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer content types', 'administer nodes', 'create article content', 'edit any article content', 'delete any article content', 'administer image styles', 'administer fields'));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
}
|
||||
|
||||
@@ -77,6 +77,24 @@ class ImageFieldTestCase extends DrupalWebTestCase {
|
||||
return field_create_instance($instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a random style.
|
||||
*
|
||||
* @return array
|
||||
* A list containing the details of the generated image style.
|
||||
*/
|
||||
function createRandomStyle() {
|
||||
$style_name = strtolower($this->randomName(10));
|
||||
$style_label = $this->randomString();
|
||||
image_style_save(array('name' => $style_name, 'label' => $style_label));
|
||||
$style_path = 'admin/config/media/image-styles/edit/' . $style_name;
|
||||
return array(
|
||||
'name' => $style_name,
|
||||
'label' => $style_label,
|
||||
'path' => $style_path,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload an image to a node.
|
||||
*
|
||||
@@ -183,6 +201,22 @@ class ImageStylesPathAndUrlTestCase extends DrupalWebTestCase {
|
||||
$this->assertResponse(404, 'Accessing an image style URL with a source image that does not exist provides a 404 error response.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that we do not pass an array to drupal_add_http_header.
|
||||
*/
|
||||
function testImageContentTypeHeaders() {
|
||||
$files = $this->drupalGetTestFiles('image');
|
||||
$file = array_shift($files);
|
||||
// Copy the test file to private folder.
|
||||
$private_file = file_copy($file, 'private://', FILE_EXISTS_RENAME);
|
||||
// Tell image_module_test module to return the headers we want to test.
|
||||
variable_set('image_module_test_invalid_headers', $private_file->uri);
|
||||
// Invoke image_style_deliver so it will try to set headers.
|
||||
$generated_url = image_style_url($this->style_name, $private_file->uri);
|
||||
$this->drupalGet($generated_url);
|
||||
variable_del('image_module_test_invalid_headers');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test image_style_url().
|
||||
*/
|
||||
@@ -251,7 +285,7 @@ class ImageStylesPathAndUrlTestCase extends DrupalWebTestCase {
|
||||
$this->assertEqual($this->drupalGetHeader('Content-Length'), $generated_image_info['file_size'], 'Expected Content-Length was reported.');
|
||||
if ($scheme == 'private') {
|
||||
$this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', 'Expires header was sent.');
|
||||
$this->assertEqual($this->drupalGetHeader('Cache-Control'), 'no-cache, must-revalidate, post-check=0, pre-check=0', 'Cache-Control header was set to prevent caching.');
|
||||
$this->assertEqual($this->drupalGetHeader('Cache-Control'), 'no-cache, must-revalidate', 'Cache-Control header was set to prevent caching.');
|
||||
$this->assertEqual($this->drupalGetHeader('X-Image-Owned-By'), 'image_module_test', 'Expected custom header has been added.');
|
||||
|
||||
// Make sure that a second request to the already existing derivate works
|
||||
@@ -469,6 +503,58 @@ class ImageEffectsUnitTest extends ImageToolkitTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the administrative user interface.
|
||||
*/
|
||||
class ImageAdminUiTestCase extends ImageFieldTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Administrative user interface',
|
||||
'description' => 'Tests the forms used in the administrative user interface.',
|
||||
'group' => 'Image',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('image'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the help text is available on the add effect form.
|
||||
*/
|
||||
function testAddEffectHelpText() {
|
||||
// Create a random image style.
|
||||
$style = $this->createRandomStyle();
|
||||
|
||||
// Open the add effect form and check for the help text.
|
||||
$this->drupalGet($style['path'] . '/add/image_crop');
|
||||
$this->assertText(t('Cropping will remove portions of an image to make it the specified dimensions.'), 'The image style effect help text was displayed on the add effect page.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the help text is available on the edit effect form.
|
||||
*/
|
||||
function testEditEffectHelpText() {
|
||||
// Create a random image style.
|
||||
$random_style = $this->createRandomStyle();
|
||||
|
||||
// Add the crop effect to the image style.
|
||||
$edit = array();
|
||||
$edit['data[width]'] = 20;
|
||||
$edit['data[height]'] = 20;
|
||||
$this->drupalPost($random_style['path'] . '/add/image_crop', $edit, t('Add effect'));
|
||||
|
||||
// Open the edit effect form and check for the help text.
|
||||
drupal_static_reset('image_styles');
|
||||
$style = image_style_load($random_style['name']);
|
||||
|
||||
foreach ($style['effects'] as $ieid => $effect) {
|
||||
$this->drupalGet($random_style['path'] . '/effects/' . $ieid);
|
||||
$this->assertText(t('Cropping will remove portions of an image to make it the specified dimensions.'), 'The image style effect help text was displayed on the edit effect page.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creation, deletion, and editing of image styles and effects.
|
||||
*/
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
files[] = image_module_test.module
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -9,6 +9,9 @@ function image_module_test_file_download($uri) {
|
||||
if (variable_get('image_module_test_file_download', FALSE) == $uri) {
|
||||
return array('X-Image-Owned-By' => 'image_module_test');
|
||||
}
|
||||
if (variable_get('image_module_test_invalid_headers', FALSE) == $uri) {
|
||||
return array('Content-Type' => 'image/png');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1194,7 +1194,7 @@ function locale_translate_edit_form_submit($form, &$form_state) {
|
||||
$translation = db_query("SELECT translation FROM {locales_target} WHERE lid = :lid AND language = :language", array(':lid' => $lid, ':language' => $key))->fetchField();
|
||||
if (!empty($value)) {
|
||||
// Only update or insert if we have a value to use.
|
||||
if (!empty($translation)) {
|
||||
if (is_string($translation)) {
|
||||
db_update('locales_target')
|
||||
->fields(array(
|
||||
'translation' => $value,
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
files[] = locale.test
|
||||
configure = admin/config/regional/language
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -393,6 +393,16 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
|
||||
// The indicator should not be here.
|
||||
$this->assertNoRaw($language_indicator, 'String is translated.');
|
||||
|
||||
// Verify that a translation set which has an empty target string can be
|
||||
// updated without any database error.
|
||||
db_update('locales_target')
|
||||
->fields(array('translation' => ''))
|
||||
->condition('language', $langcode, '=')
|
||||
->condition('lid', $lid, '=')
|
||||
->execute();
|
||||
$this->drupalPost('admin/config/regional/translate/edit/' . $lid, $edit, t('Save translations'));
|
||||
$this->assertText(t('The string has been saved.'), 'The string has been saved.');
|
||||
|
||||
// Try to edit a non-existent string and ensure we're redirected correctly.
|
||||
// Assuming we don't have 999,999 strings already.
|
||||
$random_lid = 999999;
|
||||
@@ -2237,6 +2247,37 @@ class LocaleContentFunctionalTest extends DrupalWebTestCase {
|
||||
|
||||
$this->drupalLogout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that nodes may be created with different languages.
|
||||
*/
|
||||
function testNodeCreationWithLanguage() {
|
||||
// Create an admin user and log them in.
|
||||
$perms = array(
|
||||
// Standard node permissions.
|
||||
'create page content',
|
||||
'administer content types',
|
||||
'administer nodes',
|
||||
'bypass node access',
|
||||
// Locale.
|
||||
'administer languages',
|
||||
);
|
||||
$web_user = $this->drupalCreateUser($perms);
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Create some test nodes using different langcodes.
|
||||
foreach (array(LANGUAGE_NONE, 'en', 'fr') as $langcode) {
|
||||
$node_args = array(
|
||||
'type' => 'page',
|
||||
'promote' => 1,
|
||||
'language' => $langcode,
|
||||
);
|
||||
$node = $this->drupalCreateNode($node_args);
|
||||
$node_reloaded = node_load($node->nid, NULL, TRUE);
|
||||
$this->assertEqual($node_reloaded->language, $langcode, format_string('The language code of the node was successfully set to @langcode.', array('@langcode' => $langcode)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2629,6 +2670,68 @@ class LocaleUrlRewritingTest extends DrupalWebTestCase {
|
||||
$this->drupalGet("$prefix/$path");
|
||||
$this->assertResponse(404, $message2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check URL rewriting when using a domain name and a non-standard port.
|
||||
*/
|
||||
function testDomainNameNegotiationPort() {
|
||||
$language_domain = 'example.fr';
|
||||
$edit = array(
|
||||
'locale_language_negotiation_url_part' => 1,
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/configure/url', $edit, t('Save configuration'));
|
||||
$edit = array(
|
||||
'prefix' => '',
|
||||
'domain' => $language_domain
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/edit/fr', $edit, t('Save language'));
|
||||
|
||||
// Enable domain configuration.
|
||||
variable_set('locale_language_negotiation_url_part', LOCALE_LANGUAGE_NEGOTIATION_URL_DOMAIN);
|
||||
|
||||
// Reset static caching.
|
||||
drupal_static_reset('language_list');
|
||||
drupal_static_reset('language_url_outbound_alter');
|
||||
drupal_static_reset('language_url_rewrite_url');
|
||||
|
||||
// In case index.php is part of the URLs, we need to adapt the asserted
|
||||
// URLs as well.
|
||||
$index_php = strpos(url('', array('absolute' => TRUE)), 'index.php') !== FALSE;
|
||||
|
||||
// Remember current HTTP_HOST.
|
||||
$http_host = $_SERVER['HTTP_HOST'];
|
||||
|
||||
// Fake a different port.
|
||||
$_SERVER['HTTP_HOST'] .= ':88';
|
||||
|
||||
// Create an absolute French link.
|
||||
$languages = language_list();
|
||||
$language = $languages['fr'];
|
||||
$url = url('', array(
|
||||
'absolute' => TRUE,
|
||||
'language' => $language
|
||||
));
|
||||
|
||||
$expected = 'http://example.fr:88/';
|
||||
$expected .= $index_php ? 'index.php/' : '';
|
||||
|
||||
$this->assertEqual($url, $expected, 'The right port is used.');
|
||||
|
||||
// If we set the port explicitly in url(), it should not be overriden.
|
||||
$url = url('', array(
|
||||
'absolute' => TRUE,
|
||||
'language' => $language,
|
||||
'base_url' => $GLOBALS['base_url'] . ':90',
|
||||
));
|
||||
|
||||
$expected = 'http://example.fr:90/';
|
||||
$expected .= $index_php ? 'index.php/' : '';
|
||||
|
||||
$this->assertEqual($url, $expected, 'A given port is not overriden.');
|
||||
|
||||
// Restore HTTP_HOST.
|
||||
$_SERVER['HTTP_HOST'] = $http_host;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3141,3 +3244,46 @@ class LocaleCSSAlterTest extends DrupalWebTestCase {
|
||||
$this->assertRaw('@import url("' . $base_url . '/modules/system/system.messages.css' . $query_string . '");' . "\n" . '@import url("' . $base_url . '/modules/system/system.messages-rtl.css' . $query_string . '");' . "\n", 'CSS: system.messages-rtl.css is added directly after system.messages.css.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests locale translation safe string handling.
|
||||
*/
|
||||
class LocaleStringIsSafeTest extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Test if a string is safe',
|
||||
'description' => 'Tests locale translation safe string handling.',
|
||||
'group' => 'Locale',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('locale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for locale_string_is_safe().
|
||||
*/
|
||||
public function testLocaleStringIsSafe() {
|
||||
// Check a translatable string without HTML.
|
||||
$string = 'Hello world!';
|
||||
$result = locale_string_is_safe($string);
|
||||
$this->assertTrue($result);
|
||||
|
||||
// Check a translatable string which includes trustable HTML.
|
||||
$string = 'Hello <strong>world</strong>!';
|
||||
$result = locale_string_is_safe($string);
|
||||
$this->assertTrue($result);
|
||||
|
||||
// Check an untranslatable string which includes untrustable HTML (according
|
||||
// to the locale_string_is_safe() function definition).
|
||||
$string = 'Hello <img src="world.png" alt="world" />!';
|
||||
$result = locale_string_is_safe($string);
|
||||
$this->assertFalse($result);
|
||||
|
||||
// Check a translatable string which includes a token in an href attribute.
|
||||
$string = 'Hi <a href="[current-user:url]">user</a>';
|
||||
$result = locale_string_is_safe($string);
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
}
|
||||
|
@@ -5,8 +5,8 @@ package = Testing
|
||||
version = VERSION
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -281,6 +281,7 @@ function menu_edit_item($form, &$form_state, $type, $item, $menu) {
|
||||
$form['link_title'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Menu link title'),
|
||||
'#maxlength' => 255,
|
||||
'#default_value' => $item['link_title'],
|
||||
'#description' => t('The text to be used for this link in the menu.'),
|
||||
'#required' => TRUE,
|
||||
@@ -305,7 +306,7 @@ function menu_edit_item($form, &$form_state, $type, $item, $menu) {
|
||||
'#title' => t('Path'),
|
||||
'#maxlength' => 255,
|
||||
'#default_value' => $path,
|
||||
'#description' => t('The path for this menu link. This can be an internal Drupal path such as %add-node or an external URL such as %drupal. Enter %front to link to the front page.', array('%front' => '<front>', '%add-node' => 'node/add', '%drupal' => 'http://drupal.org')),
|
||||
'#description' => t('The path for this menu link. This can be an internal path such as %add-node or an external URL such as %example. Enter %front to link to the front page.', array('%front' => '<front>', '%add-node' => 'node/add', '%example' => 'http://example.com')),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['actions']['delete'] = array(
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
files[] = menu.test
|
||||
configure = admin/structure/menu
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -674,6 +674,7 @@ function menu_form_node_form_alter(&$form, $form_state) {
|
||||
$form['menu']['link']['link_title'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Menu link title'),
|
||||
'#maxlength' => 255,
|
||||
'#default_value' => $link['link_title'],
|
||||
);
|
||||
|
||||
|
@@ -72,6 +72,17 @@ class MenuTestCase extends DrupalWebTestCase {
|
||||
$saved_item = menu_link_load($item['mlid']);
|
||||
$this->assertEqual($description, $saved_item['options']['attributes']['title'], 'Saving an existing link updates the description (title attribute)');
|
||||
$this->resetMenuLink($item, $old_title);
|
||||
|
||||
// Test that the page title is correct when a local task appears in a
|
||||
// top-level menu item. See https://www.drupal.org/node/1973262.
|
||||
$item = $this->addMenuLink(0, 'user/register', 'user-menu');
|
||||
$this->drupalGet('user/password');
|
||||
$this->assertNoTitle('Home | Drupal');
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('user/register');
|
||||
$this->assertTitle($item['link_title'] . ' | Drupal');
|
||||
$this->drupalGet('user');
|
||||
$this->assertNoTitle('Home | Drupal');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -637,7 +648,12 @@ class MenuNodeTestCase extends DrupalWebTestCase {
|
||||
);
|
||||
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
|
||||
// Create a node.
|
||||
// Verify that the menu link title on the node add form has the correct
|
||||
// maxlength.
|
||||
$this->drupalGet('node/add/page');
|
||||
$this->assertPattern('/<input .* id="edit-menu-link-title" .* maxlength="255" .* \/>/', 'Menu link title field has correct maxlength in node add form.');
|
||||
|
||||
// Create a node with menu link disabled.
|
||||
$node_title = $this->randomName();
|
||||
$language = LANGUAGE_NONE;
|
||||
$edit = array(
|
||||
@@ -673,6 +689,10 @@ class MenuNodeTestCase extends DrupalWebTestCase {
|
||||
$this->drupalGet('node/' . $node->nid . '/edit');
|
||||
$this->assertOptionSelected('edit-menu-weight', 17, 'Menu weight correct in edit form');
|
||||
|
||||
// Verify that the menu link title on the node edit form has the correct
|
||||
// maxlength.
|
||||
$this->assertPattern('/<input .* id="edit-menu-link-title" .* maxlength="255" .* \/>/', 'Menu link title field has correct maxlength in node edit form.');
|
||||
|
||||
// Edit the node and remove the menu link.
|
||||
$edit = array(
|
||||
'menu[enabled]' => FALSE,
|
||||
|
@@ -11,7 +11,7 @@
|
||||
function node_overview_types() {
|
||||
$types = node_type_get_types();
|
||||
$names = node_type_get_names();
|
||||
$field_ui = module_exists('field_ui');
|
||||
$field_ui = module_exists('field_ui') && user_access('administer fields');
|
||||
$header = array(t('Name'), array('data' => t('Operations'), 'colspan' => $field_ui ? '4' : '2'));
|
||||
$rows = array();
|
||||
|
||||
|
@@ -329,6 +329,8 @@ function _node_mass_update_helper($nid, $updates) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_operation().
|
||||
*
|
||||
* Executes a batch operation for node_mass_update().
|
||||
*
|
||||
* @param array $nodes
|
||||
@@ -367,7 +369,9 @@ function _node_mass_update_batch_process($nodes, $updates, &$context) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback: Reports the status of batch operation for node_mass_update().
|
||||
* Implements callback_batch_finished().
|
||||
*
|
||||
* Reports the status of batch operation for node_mass_update().
|
||||
*
|
||||
* @param bool $success
|
||||
* A boolean indicating whether the batch mass update operation successfully
|
||||
@@ -504,14 +508,17 @@ function node_admin_nodes() {
|
||||
$options = array();
|
||||
foreach ($nodes as $node) {
|
||||
$langcode = entity_language('node', $node);
|
||||
$l_options = $langcode != LANGUAGE_NONE && isset($languages[$langcode]) ? array('language' => $languages[$langcode]) : array();
|
||||
$uri = entity_uri('node', $node);
|
||||
if ($langcode != LANGUAGE_NONE && isset($languages[$langcode])) {
|
||||
$uri['options']['language'] = $languages[$langcode];
|
||||
}
|
||||
$options[$node->nid] = array(
|
||||
'title' => array(
|
||||
'data' => array(
|
||||
'#type' => 'link',
|
||||
'#title' => $node->title,
|
||||
'#href' => 'node/' . $node->nid,
|
||||
'#options' => $l_options,
|
||||
'#href' => $uri['path'],
|
||||
'#options' => $uri['options'],
|
||||
'#suffix' => ' ' . theme('mark', array('type' => node_mark($node->nid, $node->changed))),
|
||||
),
|
||||
),
|
||||
|
@@ -950,7 +950,7 @@ function hook_node_info() {
|
||||
* 'recent', or 'comments'. The values should be arrays themselves, with the
|
||||
* following keys available:
|
||||
* - title: (required) The human readable name of the ranking mechanism.
|
||||
* - join: (optional) The part of a query string to join to any additional
|
||||
* - join: (optional) An array with information to join any additional
|
||||
* necessary table. This is not necessary if the table required is already
|
||||
* joined to by the base query, such as for the {node} table. Other tables
|
||||
* should use the full table name as an alias to avoid naming collisions.
|
||||
@@ -974,7 +974,12 @@ function hook_ranking() {
|
||||
'title' => t('Average vote'),
|
||||
// Note that we use i.sid, the search index's search item id, rather than
|
||||
// n.nid.
|
||||
'join' => 'LEFT JOIN {vote_node_data} vote_node_data ON vote_node_data.nid = i.sid',
|
||||
'join' => array(
|
||||
'type' => 'LEFT',
|
||||
'table' => 'vote_node_data',
|
||||
'alias' => 'vote_node_data',
|
||||
'on' => 'vote_node_data.nid = i.sid',
|
||||
),
|
||||
// The highest possible score should be 1, and the lowest possible score,
|
||||
// always 0, should be 0.
|
||||
'score' => 'vote_node_data.average / CAST(%f AS DECIMAL)',
|
||||
@@ -1079,19 +1084,9 @@ function hook_delete($node) {
|
||||
* @ingroup node_api_hooks
|
||||
*/
|
||||
function hook_prepare($node) {
|
||||
$file = file_save_upload($field_name, _image_filename($file->filename, NULL, TRUE));
|
||||
if ($file) {
|
||||
if (!image_get_info($file->uri)) {
|
||||
form_set_error($field_name, t('Uploaded file is not a valid image'));
|
||||
return;
|
||||
}
|
||||
if (!isset($node->mymodule_value)) {
|
||||
$node->mymodule_value = 'foo';
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
$node->images['_original'] = $file->uri;
|
||||
_image_build_derivatives($node, TRUE);
|
||||
$node->new_file = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -9,8 +9,8 @@ required = TRUE
|
||||
configure = admin/structure/types
|
||||
stylesheets[all][] = node.css
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -410,6 +410,7 @@ function node_schema() {
|
||||
'nid' => array(
|
||||
'description' => 'The {node}.nid that was read.',
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
@@ -933,6 +934,33 @@ function node_update_7014() {
|
||||
db_add_index('node', 'language', array('language'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable node types that may have been erroneously disabled in Drupal 7.36.
|
||||
*/
|
||||
function node_update_7015() {
|
||||
db_update('node_type')
|
||||
->fields(array('disabled' => 0))
|
||||
->condition('base', 'node_content')
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change {history}.nid to an unsigned int in order to match {node}.nid.
|
||||
*/
|
||||
function node_update_7016() {
|
||||
db_drop_primary_key('history');
|
||||
db_drop_index('history', 'nid');
|
||||
db_change_field('history', 'nid', 'nid', array(
|
||||
'description' => 'The {node}.nid that was read.',
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
));
|
||||
db_add_primary_key('history', array('uid', 'nid'));
|
||||
db_add_index('history', 'nid', array('nid'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup updates-7.x-extra".
|
||||
*/
|
||||
|
@@ -740,9 +740,11 @@ function _node_types_build($rebuild = FALSE) {
|
||||
$type_db = $type_object->type;
|
||||
// Original disabled value.
|
||||
$disabled = $type_object->disabled;
|
||||
// Check for node types either from disabled modules or otherwise not defined
|
||||
// and mark as disabled.
|
||||
if (empty($type_object->custom) && empty($_node_types->types[$type_db])) {
|
||||
// Check for node types from disabled modules and mark their types for removal.
|
||||
// Types defined by the node module in the database (rather than by a separate
|
||||
// module using hook_node_info) have a base value of 'node_content'. The isset()
|
||||
// check prevents errors on old (pre-Drupal 7) databases.
|
||||
if (isset($type_object->base) && $type_object->base != 'node_content' && empty($_node_types->types[$type_db])) {
|
||||
$type_object->disabled = TRUE;
|
||||
}
|
||||
if (isset($_node_types->types[$type_db])) {
|
||||
@@ -2951,7 +2953,10 @@ function node_search_validate($form, &$form_state) {
|
||||
* system. When adding a node listing to your module, be sure to use a dynamic
|
||||
* query created by db_select() and add a tag of "node_access". This will allow
|
||||
* modules dealing with node access to ensure only nodes to which the user has
|
||||
* access are retrieved, through the use of hook_query_TAG_alter().
|
||||
* access are retrieved, through the use of hook_query_TAG_alter(). Tagging a
|
||||
* query with "node_access" does not check the published/unpublished status of
|
||||
* nodes, so the base query is responsible for ensuring that unpublished nodes
|
||||
* are not displayed to inappropriate users.
|
||||
*
|
||||
* Note: Even a single module returning NODE_ACCESS_DENY from hook_node_access()
|
||||
* will block access to the node. Therefore, implementers should take care to
|
||||
@@ -3667,6 +3672,8 @@ function node_access_rebuild($batch_mode = FALSE) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_operation().
|
||||
*
|
||||
* Performs batch operation for node_access_rebuild().
|
||||
*
|
||||
* This is a multistep operation: we go through all nodes by packs of 20. The
|
||||
@@ -3681,7 +3688,7 @@ function _node_access_rebuild_batch_operation(&$context) {
|
||||
// Initiate multistep processing.
|
||||
$context['sandbox']['progress'] = 0;
|
||||
$context['sandbox']['current_node'] = 0;
|
||||
$context['sandbox']['max'] = db_query('SELECT COUNT(DISTINCT nid) FROM {node}')->fetchField();
|
||||
$context['sandbox']['max'] = db_query('SELECT COUNT(nid) FROM {node}')->fetchField();
|
||||
}
|
||||
|
||||
// Process the next 20 nodes.
|
||||
@@ -3705,6 +3712,8 @@ function _node_access_rebuild_batch_operation(&$context) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_finished().
|
||||
*
|
||||
* Performs post-processing for node_access_rebuild().
|
||||
*
|
||||
* @param bool $success
|
||||
|
@@ -396,7 +396,6 @@ function node_preview($node) {
|
||||
|
||||
$cloned_node->changed = REQUEST_TIME;
|
||||
$nodes = array($cloned_node->nid => $cloned_node);
|
||||
field_attach_prepare_view('node', $nodes, 'full');
|
||||
|
||||
// Display a preview of the node.
|
||||
if (!form_get_errors()) {
|
||||
|
@@ -457,10 +457,70 @@ class PagePreviewTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
parent::setUp(array('taxonomy', 'node'));
|
||||
|
||||
$web_user = $this->drupalCreateUser(array('edit own page content', 'create page content'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Add a vocabulary so we can test different view modes.
|
||||
$vocabulary = (object) array(
|
||||
'name' => $this->randomName(),
|
||||
'description' => $this->randomName(),
|
||||
'machine_name' => drupal_strtolower($this->randomName()),
|
||||
'help' => '',
|
||||
'nodes' => array('page' => 'page'),
|
||||
);
|
||||
taxonomy_vocabulary_save($vocabulary);
|
||||
|
||||
$this->vocabulary = $vocabulary;
|
||||
|
||||
// Add a term to the vocabulary.
|
||||
$term = (object) array(
|
||||
'name' => $this->randomName(),
|
||||
'description' => $this->randomName(),
|
||||
// Use the first available text format.
|
||||
'format' => db_query_range('SELECT format FROM {filter_format}', 0, 1)->fetchField(),
|
||||
'vid' => $this->vocabulary->vid,
|
||||
'vocabulary_machine_name' => $vocabulary->machine_name,
|
||||
);
|
||||
taxonomy_term_save($term);
|
||||
|
||||
$this->term = $term;
|
||||
|
||||
// Set up a field and instance.
|
||||
$this->field_name = drupal_strtolower($this->randomName());
|
||||
$this->field = array(
|
||||
'field_name' => $this->field_name,
|
||||
'type' => 'taxonomy_term_reference',
|
||||
'settings' => array(
|
||||
'allowed_values' => array(
|
||||
array(
|
||||
'vocabulary' => $this->vocabulary->machine_name,
|
||||
'parent' => '0',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
field_create_field($this->field);
|
||||
$this->instance = array(
|
||||
'field_name' => $this->field_name,
|
||||
'entity_type' => 'node',
|
||||
'bundle' => 'page',
|
||||
'widget' => array(
|
||||
'type' => 'options_select',
|
||||
),
|
||||
// Hide on full display but render on teaser.
|
||||
'display' => array(
|
||||
'default' => array(
|
||||
'type' => 'hidden',
|
||||
),
|
||||
'teaser' => array(
|
||||
'type' => 'taxonomy_term_reference_link',
|
||||
),
|
||||
),
|
||||
);
|
||||
field_create_instance($this->instance);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -470,21 +530,26 @@ class PagePreviewTestCase extends DrupalWebTestCase {
|
||||
$langcode = LANGUAGE_NONE;
|
||||
$title_key = "title";
|
||||
$body_key = "body[$langcode][0][value]";
|
||||
$term_key = "{$this->field_name}[$langcode]";
|
||||
|
||||
// Fill in node creation form and preview node.
|
||||
$edit = array();
|
||||
$edit[$title_key] = $this->randomName(8);
|
||||
$edit[$body_key] = $this->randomName(16);
|
||||
$edit[$term_key] = $this->term->tid;
|
||||
$this->drupalPost('node/add/page', $edit, t('Preview'));
|
||||
|
||||
// Check that the preview is displaying the title and body.
|
||||
// Check that the preview is displaying the title, body, and term.
|
||||
$this->assertTitle(t('Preview | Drupal'), 'Basic page title is preview.');
|
||||
$this->assertText($edit[$title_key], 'Title displayed.');
|
||||
$this->assertText($edit[$body_key], 'Body displayed.');
|
||||
$this->assertText($this->term->name, 'Term displayed.');
|
||||
|
||||
// Check that the title and body fields are displayed with the correct values.
|
||||
// Check that the title, body, and term fields are displayed with the
|
||||
// correct values.
|
||||
$this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
|
||||
$this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
|
||||
$this->assertFieldByName($term_key, $edit[$term_key], 'Term field displayed.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -494,6 +559,7 @@ class PagePreviewTestCase extends DrupalWebTestCase {
|
||||
$langcode = LANGUAGE_NONE;
|
||||
$title_key = "title";
|
||||
$body_key = "body[$langcode][0][value]";
|
||||
$term_key = "{$this->field_name}[$langcode]";
|
||||
// Force revision on "Basic page" content.
|
||||
variable_set('node_options_page', array('status', 'revision'));
|
||||
|
||||
@@ -501,17 +567,21 @@ class PagePreviewTestCase extends DrupalWebTestCase {
|
||||
$edit = array();
|
||||
$edit[$title_key] = $this->randomName(8);
|
||||
$edit[$body_key] = $this->randomName(16);
|
||||
$edit[$term_key] = $this->term->tid;
|
||||
$edit['log'] = $this->randomName(32);
|
||||
$this->drupalPost('node/add/page', $edit, t('Preview'));
|
||||
|
||||
// Check that the preview is displaying the title and body.
|
||||
// Check that the preview is displaying the title, body, and term.
|
||||
$this->assertTitle(t('Preview | Drupal'), 'Basic page title is preview.');
|
||||
$this->assertText($edit[$title_key], 'Title displayed.');
|
||||
$this->assertText($edit[$body_key], 'Body displayed.');
|
||||
$this->assertText($this->term->name, 'Term displayed.');
|
||||
|
||||
// Check that the title and body fields are displayed with the correct values.
|
||||
// Check that the title, body, and term fields are displayed with the
|
||||
// correct values.
|
||||
$this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
|
||||
$this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
|
||||
$this->assertFieldByName($term_key, $edit[$term_key], 'Term field displayed.');
|
||||
|
||||
// Check that the log field has the correct value.
|
||||
$this->assertFieldByName('log', $edit['log'], 'Log field displayed.');
|
||||
@@ -1448,7 +1518,7 @@ class NodeTypeTestCase extends DrupalWebTestCase {
|
||||
* Tests editing a node type using the UI.
|
||||
*/
|
||||
function testNodeTypeEditing() {
|
||||
$web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types'));
|
||||
$web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer fields'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
$instance = field_info_instance('node', 'body', 'page');
|
||||
@@ -2698,8 +2768,8 @@ class NodeAccessFieldTestCase extends NodeWebTestCase {
|
||||
node_access_rebuild();
|
||||
|
||||
// Create some users.
|
||||
$this->admin_user = $this->drupalCreateUser(array('access content', 'bypass node access'));
|
||||
$this->content_admin_user = $this->drupalCreateUser(array('access content', 'administer content types'));
|
||||
$this->admin_user = $this->drupalCreateUser(array('access content', 'bypass node access', 'administer fields'));
|
||||
$this->content_admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer fields'));
|
||||
|
||||
// Add a custom field to the page content type.
|
||||
$this->field_name = drupal_strtolower($this->randomName() . '_field_name');
|
||||
@@ -2916,3 +2986,36 @@ class NodePageCacheTest extends NodeWebTestCase {
|
||||
$this->assertResponse(404);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that multi-byte UTF-8 characters are stored and retrieved correctly.
|
||||
*/
|
||||
class NodeMultiByteUtf8Test extends NodeWebTestCase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Multi-byte UTF-8',
|
||||
'description' => 'Test that multi-byte UTF-8 characters are stored and retrieved correctly.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that multi-byte UTF-8 characters are stored and retrieved correctly.
|
||||
*/
|
||||
public function testMultiByteUtf8() {
|
||||
$connection = Database::getConnection();
|
||||
// On MySQL, this test will only run if 'charset' is set to 'utf8mb4' in
|
||||
// settings.php.
|
||||
if (!($connection->utf8mb4IsSupported() && $connection->utf8mb4IsActive())) {
|
||||
return;
|
||||
}
|
||||
$title = '🐙';
|
||||
$this->assertTrue(drupal_strlen($title, 'utf-8') < strlen($title), 'Title has multi-byte characters.');
|
||||
$node = $this->drupalCreateNode(array('title' => $title));
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$result = $this->xpath('//h1[@id="page-title"]');
|
||||
$this->assertEqual(trim((string) $result[0]), $title, 'The passed title was returned.');
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -5,8 +5,8 @@ package = Core
|
||||
core = 7.x
|
||||
files[] = openid.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -365,14 +365,20 @@ function openid_complete($response = array()) {
|
||||
// to the OpenID Provider, we need to do discovery on the returned
|
||||
// identififer to make sure that the provider is authorized to
|
||||
// respond on behalf of this.
|
||||
if ($response_claimed_id != $claimed_id) {
|
||||
if ($response_claimed_id != $claimed_id || $response_claimed_id != $response['openid.identity']) {
|
||||
$discovery = openid_discovery($response['openid.claimed_id']);
|
||||
$uris = array();
|
||||
if ($discovery && !empty($discovery['services'])) {
|
||||
$uris = array();
|
||||
foreach ($discovery['services'] as $discovered_service) {
|
||||
if (in_array('http://specs.openid.net/auth/2.0/server', $discovered_service['types']) || in_array('http://specs.openid.net/auth/2.0/signon', $discovered_service['types'])) {
|
||||
$uris[] = $discovered_service['uri'];
|
||||
if (!in_array('http://specs.openid.net/auth/2.0/server', $discovered_service['types']) && !in_array('http://specs.openid.net/auth/2.0/signon', $discovered_service['types'])) {
|
||||
continue;
|
||||
}
|
||||
// The OP-Local Identifier (if different than the Claimed
|
||||
// Identifier) must be present in the XRDS document.
|
||||
if ($response_claimed_id != $response['openid.identity'] && (!isset($discovered_service['identity']) || $discovered_service['identity'] != $response['openid.identity'])) {
|
||||
continue;
|
||||
}
|
||||
$uris[] = $discovered_service['uri'];
|
||||
}
|
||||
}
|
||||
if (!in_array($service['uri'], $uris)) {
|
||||
|
@@ -94,7 +94,7 @@ class OpenIDFunctionalTestCase extends OpenIDWebTestCase {
|
||||
$identity = url('openid-test/yadis/xrds/dummy-user', array('absolute' => TRUE, 'fragment' => $this->randomName()));
|
||||
// Tell openid_test.module to respond with this identifier. If the fragment
|
||||
// part is present in the identifier, it should be retained.
|
||||
variable_set('openid_test_response', array('openid.claimed_id' => $identity));
|
||||
variable_set('openid_test_response', array('openid.claimed_id' => $identity, 'openid.identity' => openid_normalize($identity)));
|
||||
$this->addIdentity(url('openid-test/yadis/xrds/server', array('absolute' => TRUE)), 2, 'http://specs.openid.net/auth/2.0/identifier_select', $identity);
|
||||
variable_set('openid_test_response', array());
|
||||
|
||||
@@ -680,11 +680,11 @@ class OpenIDTestCase extends DrupalWebTestCase {
|
||||
* Test _openid_dh_XXX_to_XXX() functions.
|
||||
*/
|
||||
function testConversion() {
|
||||
$this->assertEqual(_openid_dh_long_to_base64('12345678901234567890123456789012345678901234567890'), 'CHJ/Y2mq+DyhUCZ0evjH8ZbOPwrS', '_openid_dh_long_to_base64() returned expected result.');
|
||||
$this->assertEqual(_openid_dh_base64_to_long('BsH/g8Nrpn2dtBSdu/sr1y8hxwyx'), '09876543210987654321098765432109876543210987654321', '_openid_dh_base64_to_long() returned expected result.');
|
||||
$this->assertIdentical(_openid_dh_long_to_base64('12345678901234567890123456789012345678901234567890'), 'CHJ/Y2mq+DyhUCZ0evjH8ZbOPwrS', '_openid_dh_long_to_base64() returned expected result.');
|
||||
$this->assertIdentical(_openid_dh_base64_to_long('BsH/g8Nrpn2dtBSdu/sr1y8hxwyx'), '9876543210987654321098765432109876543210987654321', '_openid_dh_base64_to_long() returned expected result.');
|
||||
|
||||
$this->assertEqual(_openid_dh_long_to_binary('12345678901234567890123456789012345678901234567890'), "\x08r\x7fci\xaa\xf8<\xa1P&tz\xf8\xc7\xf1\x96\xce?\x0a\xd2", '_openid_dh_long_to_binary() returned expected result.');
|
||||
$this->assertEqual(_openid_dh_binary_to_long("\x06\xc1\xff\x83\xc3k\xa6}\x9d\xb4\x14\x9d\xbb\xfb+\xd7/!\xc7\x0c\xb1"), '09876543210987654321098765432109876543210987654321', '_openid_dh_binary_to_long() returned expected result.');
|
||||
$this->assertIdentical(_openid_dh_long_to_binary('12345678901234567890123456789012345678901234567890'), "\x08r\x7fci\xaa\xf8<\xa1P&tz\xf8\xc7\xf1\x96\xce?\x0a\xd2", '_openid_dh_long_to_binary() returned expected result.');
|
||||
$this->assertIdentical(_openid_dh_binary_to_long("\x06\xc1\xff\x83\xc3k\xa6}\x9d\xb4\x14\x9d\xbb\xfb+\xd7/!\xc7\x0c\xb1"), '9876543210987654321098765432109876543210987654321', '_openid_dh_binary_to_long() returned expected result.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
dependencies[] = openid
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -150,6 +150,7 @@ function openid_test_yadis_xrds() {
|
||||
<Service priority="20">
|
||||
<Type>http://specs.openid.net/auth/2.0/server</Type>
|
||||
<URI>' . url('openid-test/endpoint', array('absolute' => TRUE)) . '</URI>
|
||||
<LocalID>' . url('openid-test/yadis/xrds/server', array('absolute' => TRUE)) . '</LocalID>
|
||||
</Service>';
|
||||
}
|
||||
elseif (arg(3) == 'delegate') {
|
||||
|
@@ -350,7 +350,7 @@ Drupal.overlay.setFocusBefore = function ($element, document) {
|
||||
* TRUE if the URL represents an administrative link, FALSE otherwise.
|
||||
*/
|
||||
Drupal.overlay.isAdminLink = function (url) {
|
||||
if (Drupal.overlay.isExternalLink(url)) {
|
||||
if (!Drupal.urlIsLocal(url)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -378,6 +378,8 @@ Drupal.overlay.isAdminLink = function (url) {
|
||||
/**
|
||||
* Determine whether a link is external to the site.
|
||||
*
|
||||
* Deprecated. Use Drupal.urlIsLocal() instead.
|
||||
*
|
||||
* @param url
|
||||
* The URL to be tested.
|
||||
*
|
||||
@@ -385,8 +387,28 @@ Drupal.overlay.isAdminLink = function (url) {
|
||||
* TRUE if the URL is external to the site, FALSE otherwise.
|
||||
*/
|
||||
Drupal.overlay.isExternalLink = function (url) {
|
||||
var re = RegExp('^((f|ht)tps?:)?//(?!' + window.location.host + ')');
|
||||
return re.test(url);
|
||||
return !Drupal.urlIsLocal(url);
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs an internal URL (relative to this site) from the provided path.
|
||||
*
|
||||
* For example, if the provided path is 'admin' and the site is installed at
|
||||
* http://example.com/drupal, this function will return '/drupal/admin'.
|
||||
*
|
||||
* @param path
|
||||
* The internal path, without any leading slash.
|
||||
*
|
||||
* @return
|
||||
* The internal URL derived from the provided path, or null if a valid
|
||||
* internal path cannot be constructed (for example, if an attempt to create
|
||||
* an external link is detected).
|
||||
*/
|
||||
Drupal.overlay.getInternalUrl = function (path) {
|
||||
var url = Drupal.settings.basePath + path;
|
||||
if (Drupal.urlIsLocal(url)) {
|
||||
return url;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -577,7 +599,7 @@ Drupal.overlay.eventhandlerOverrideLink = function (event) {
|
||||
// If the link contains the overlay-restore class and the overlay-context
|
||||
// state is set, also update the parent window's location.
|
||||
var parentLocation = ($target.hasClass('overlay-restore') && typeof $.bbq.getState('overlay-context') == 'string')
|
||||
? Drupal.settings.basePath + $.bbq.getState('overlay-context')
|
||||
? this.getInternalUrl($.bbq.getState('overlay-context'))
|
||||
: null;
|
||||
href = this.fragmentizeLink($target.get(0), parentLocation);
|
||||
// Only override default behavior when left-clicking and user is not
|
||||
@@ -657,11 +679,15 @@ Drupal.overlay.eventhandlerOperateByURLFragment = function (event) {
|
||||
}
|
||||
|
||||
// Get the overlay URL from the current URL fragment.
|
||||
var internalUrl = null;
|
||||
var state = $.bbq.getState('overlay');
|
||||
if (state) {
|
||||
internalUrl = this.getInternalUrl(state);
|
||||
}
|
||||
if (internalUrl) {
|
||||
// Append render variable, so the server side can choose the right
|
||||
// rendering and add child frame code to the page if needed.
|
||||
var url = $.param.querystring(Drupal.settings.basePath + state, { render: 'overlay' });
|
||||
var url = $.param.querystring(internalUrl, { render: 'overlay' });
|
||||
|
||||
this.open(url);
|
||||
this.resetActiveClass(this.getPath(Drupal.settings.basePath + state));
|
||||
|
@@ -4,8 +4,8 @@ package = Core
|
||||
version = VERSION
|
||||
core = 7.x
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -78,6 +78,20 @@ function overlay_theme() {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_alter().
|
||||
*/
|
||||
function overlay_form_alter(&$form, &$form_state) {
|
||||
// Add a hidden element to prevent dropping out of the overlay when a form is
|
||||
// submitted inside the overlay using a GET method.
|
||||
if (isset($form['#method']) && $form['#method'] == 'get' && isset($_REQUEST['render']) && $_REQUEST['render'] == 'overlay' && !isset($form['render'])) {
|
||||
$form['render'] = array(
|
||||
'#type' => 'hidden',
|
||||
'#value' => 'overlay',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_FORM_ID_alter().
|
||||
*/
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
files[] = path.test
|
||||
configure = admin/config/search/path
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -185,7 +185,7 @@ function path_form_element_validate($element, &$form_state, $complete_form) {
|
||||
* Implements hook_node_insert().
|
||||
*/
|
||||
function path_node_insert($node) {
|
||||
if (isset($node->path)) {
|
||||
if (isset($node->path) && isset($node->path['alias'])) {
|
||||
$path = $node->path;
|
||||
$path['alias'] = trim($path['alias']);
|
||||
// Only save a non-empty alias.
|
||||
@@ -205,9 +205,9 @@ function path_node_insert($node) {
|
||||
function path_node_update($node) {
|
||||
if (isset($node->path)) {
|
||||
$path = $node->path;
|
||||
$path['alias'] = trim($path['alias']);
|
||||
$path['alias'] = isset($path['alias']) ? trim($path['alias']) : '';
|
||||
// Delete old alias if user erased it.
|
||||
if (!empty($path['pid']) && empty($path['alias'])) {
|
||||
if (!empty($path['pid']) && !$path['alias']) {
|
||||
path_delete($path['pid']);
|
||||
}
|
||||
path_node_insert($node);
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = php.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
files[] = poll.test
|
||||
stylesheets[all][] = poll.css
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -191,7 +191,6 @@ function poll_node_info() {
|
||||
'base' => 'poll',
|
||||
'description' => t('A <em>poll</em> is a question with a set of possible responses. A <em>poll</em>, once created, automatically provides a simple running count of the number of votes received for each response.'),
|
||||
'title_label' => t('Question'),
|
||||
'has_body' => FALSE,
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -632,9 +631,6 @@ function poll_delete($node) {
|
||||
* The node object to load.
|
||||
*/
|
||||
function poll_block_latest_poll_view($node) {
|
||||
global $user;
|
||||
$output = '';
|
||||
|
||||
// This is necessary for shared objects because PHP doesn't copy objects, but
|
||||
// passes them by reference. So when the objects are cached it can result in
|
||||
// the wrong output being displayed on subsequent calls. The cloning and
|
||||
@@ -675,9 +671,6 @@ function poll_block_latest_poll_view($node) {
|
||||
* Implements hook_view().
|
||||
*/
|
||||
function poll_view($node, $view_mode) {
|
||||
global $user;
|
||||
$output = '';
|
||||
|
||||
if (!empty($node->allowvotes) && empty($node->show_results)) {
|
||||
$node->content['poll_view_voting'] = drupal_get_form('poll_view_voting', $node);
|
||||
}
|
||||
@@ -695,7 +688,7 @@ function poll_view($node, $view_mode) {
|
||||
function poll_teaser($node) {
|
||||
$teaser = NULL;
|
||||
if (is_array($node->choice)) {
|
||||
foreach ($node->choice as $k => $choice) {
|
||||
foreach ($node->choice as $choice) {
|
||||
if ($choice['chtext'] != '') {
|
||||
$teaser .= '* ' . check_plain($choice['chtext']) . "\n";
|
||||
}
|
||||
|
@@ -11,8 +11,8 @@ configure = admin/config/people/profile
|
||||
; See user_system_info_alter().
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -339,12 +339,22 @@ class ProfileTestAutocomplete extends ProfileTestCase {
|
||||
$this->setProfileField($field, $field['value']);
|
||||
|
||||
// Set some html for what we want to see in the page output later.
|
||||
$autocomplete_html = '<input type="hidden" id="' . drupal_html_id('edit-' . $field['form_name'] . '-autocomplete') . '" value="' . url('profile/autocomplete/' . $field['fid'], array('absolute' => TRUE)) . '" disabled="disabled" class="autocomplete" />';
|
||||
$field_html = '<input type="text" maxlength="255" name="' . $field['form_name'] . '" id="' . drupal_html_id('edit-' . $field['form_name']) . '" size="60" value="' . $field['value'] . '" class="form-text form-autocomplete required" />';
|
||||
// Autocomplete always uses non-clean URLs.
|
||||
$current_clean_url = isset($GLOBALS['conf']['clean_url']) ? $GLOBALS['conf']['clean_url'] : NULL;
|
||||
$GLOBALS['conf']['clean_url'] = 0;
|
||||
$autocomplete_url = url('profile/autocomplete/' . $field['fid'], array('absolute' => TRUE, 'script' => 'index.php'));
|
||||
$GLOBALS['conf']['clean_url'] = $current_clean_url;
|
||||
$autocomplete_id = drupal_html_id('edit-' . $field['form_name'] . '-autocomplete');
|
||||
$autocomplete_html = '<input type="hidden" id="' . $autocomplete_id . '" value="' . $autocomplete_url . '" disabled="disabled" class="autocomplete" />';
|
||||
|
||||
// Check that autocompletion html is found on the user's profile edit page.
|
||||
$this->drupalGet('user/' . $this->admin_user->uid . '/edit/' . $category);
|
||||
$this->assertRaw($autocomplete_html, 'Autocomplete found.');
|
||||
$this->assertFieldByXPath(
|
||||
'//input[@type="text" and @name="' . $field['form_name'] . '" and contains(@class, "form-autocomplete")]',
|
||||
'',
|
||||
'Text input field found'
|
||||
);
|
||||
$this->assertRaw('misc/autocomplete.js', 'Autocomplete JavaScript found.');
|
||||
$this->assertRaw('class="form-text form-autocomplete"', 'Autocomplete form element class found.');
|
||||
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = rdf.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user