# HG changeset patch # User Franck Deroche # Date 1230039139 -3600 # Node ID 589fb7c0232763c00ee83ae32b3f80674d830346 # Parent 6f15c9d74937d086eaeddf7f582514605cffa5af Drupal 6.5 diff -r 6f15c9d74937 -r 589fb7c02327 CHANGELOG.txt --- a/CHANGELOG.txt Tue Dec 23 14:32:08 2008 +0100 +++ b/CHANGELOG.txt Tue Dec 23 14:32:19 2008 +0100 @@ -1,4 +1,10 @@ -// $Id: CHANGELOG.txt,v 1.253.2.11 2008/08/13 23:59:12 drumm Exp $ +// $Id: CHANGELOG.txt,v 1.253.2.13 2008/10/08 20:12:17 goba Exp $ + +Drupal 6.5, 2008-10-08 +---------------------- +- Fixed security issues, (File upload access bypass, Access rules bypass, + BlogAPI access bypass), see SA-2008-060. +- Fixed a variety of small bugs. Drupal 6.4, 2008-08-13 ---------------------- @@ -131,6 +137,12 @@ - Removed old system updates. Updates from Drupal versions prior to 5.x will require upgrading to 5.x before upgrading to 6.x. +Drupal 5.11, 2008-10-08 +----------------------- +- fixed a variety of small bugs. +- fixed security issues, (File upload access bypass, Access rules bypass, + BlogAPI access bypass, Node validation bypass), see SA-2008-060 + Drupal 5.10, 2008-08-13 ----------------------- - fixed a variety of small bugs. diff -r 6f15c9d74937 -r 589fb7c02327 includes/actions.inc --- a/includes/actions.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/includes/actions.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ callback; $context = array_merge($context, unserialize($action->parameters)); $result[$action_ids] = $function($object, $context, $a1, $a2); @@ -238,7 +238,7 @@ } // Must be an instance; must check database. - $aid = db_result(db_query("SELECT aid FROM {actions} WHERE MD5(aid) = '%s' AND parameters != ''", $hash)); + $aid = db_result(db_query("SELECT aid FROM {actions} WHERE MD5(aid) = '%s' AND parameters <> ''", $hash)); return $aid; } @@ -325,7 +325,7 @@ function actions_save($function, $type, $params, $desc, $aid = NULL) { $serialized = serialize($params); if ($aid) { - db_query("UPDATE {actions} SET callback = '%s', type = '%s', parameters = '%s', description = '%s' WHERE aid = %d", $function, $type, $serialized, $desc, $aid); + db_query("UPDATE {actions} SET callback = '%s', type = '%s', parameters = '%s', description = '%s' WHERE aid = '%s'", $function, $type, $serialized, $desc, $aid); watchdog('actions', 'Action %action saved.', array('%action' => $desc)); } else { @@ -333,7 +333,7 @@ // separate table for numeric aids. db_query('INSERT INTO {actions_aid} VALUES (default)'); $aid = db_last_insert_id('actions_aid', 'aid'); - db_query("INSERT INTO {actions} (aid, callback, type, parameters, description) VALUES (%d, '%s', '%s', '%s', '%s')", $aid, $function, $type, $serialized, $desc); + db_query("INSERT INTO {actions} (aid, callback, type, parameters, description) VALUES ('%s', '%s', '%s', '%s', '%s')", $aid, $function, $type, $serialized, $desc); watchdog('actions', 'Action %action created.', array('%action' => $desc)); } @@ -350,7 +350,7 @@ * The appropriate action row from the database as an object. */ function actions_load($aid) { - return db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = %d", $aid)); + return db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = '%s'", $aid)); } /** @@ -360,6 +360,6 @@ * integer The ID of the action to delete. */ function actions_delete($aid) { - db_query("DELETE FROM {actions} WHERE aid = %d", $aid); + db_query("DELETE FROM {actions} WHERE aid = '%s'", $aid); module_invoke_all('actions_delete', $aid); } diff -r 6f15c9d74937 -r 589fb7c02327 includes/bootstrap.inc --- a/includes/bootstrap.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/includes/bootstrap.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ \n"; + foreach ($javascript as $type => $data) { if (!$data) continue; switch ($type) { case 'setting': - $output .= '\n"; + $output .= '\n"; break; case 'inline': foreach ($data as $info) { - $output .= '\n"; + $output .= '\n"; } break; default: diff -r 6f15c9d74937 -r 589fb7c02327 includes/file.inc --- a/includes/file.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/includes/file.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ 'textfield', '#title' => t('Language domain'), - '#maxlength' => 64, + '#maxlength' => 128, '#default_value' => @$language->domain, '#description' => t('Language-specific URL, with protocol. With language negotiation set to Domain name only, the site is presented in this language when the URL accessing the site references this domain. For the default language, this value may be left blank. This value must include a protocol as part of the string. Example: Specifying "http://example.de" or "http://de.example.com" as language domains for German results in URLs in the forms "http://example.de/node" and "http://de.example.com/node", respectively.'), ); @@ -853,6 +853,7 @@ drupal_set_message(t('The string has been saved.')); // Clear locale cache. + _locale_invalidate_js(); cache_clear_all('locale:', 'cache', TRUE); $form_state['redirect'] = 'admin/build/translate/search'; @@ -2376,7 +2377,7 @@ "pi" => array("Pali"), "pl" => array("Polish", "Polski"), "ps" => array("Pashto", /* Left-to-right marker "‭" */ "پښتو", LANGUAGE_RTL), - "pt" => array("Portuguese, Portugal", "Português"), + "pt-pt" => array("Portuguese, Portugal", "Português"), "pt-br" => array("Portuguese, Brazil", "Português"), "qu" => array("Quechua"), "rm" => array("Rhaeto-Romance"), diff -r 6f15c9d74937 -r 589fb7c02327 includes/mail.inc --- a/includes/mail.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/includes/mail.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ mail, user_preferred_language($account), $params); + * drupal_mail('example', 'notice', $account->mail, user_preferred_language($account), $params); * } * } * @@ -435,7 +435,7 @@ function _drupal_html_to_mail_urls($match = NULL, $reset = FALSE) { global $base_url, $base_path; static $urls = array(), $regexp; - + if ($reset) { // Reset internal URL list. $urls = array(); diff -r 6f15c9d74937 -r 589fb7c02327 includes/menu.inc --- a/includes/menu.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/includes/menu.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ uid || $value || count($_COOKIE)) { - db_query("INSERT INTO {sessions} (sid, uid, cache, hostname, session, timestamp) VALUES ('%s', %d, %d, '%s', '%s', %d)", $key, $user->uid, isset($user->cache) ? $user->cache : '', ip_address(), $value, time()); - } - } - else { - db_query("UPDATE {sessions} SET uid = %d, cache = %d, hostname = '%s', session = '%s', timestamp = %d WHERE sid = '%s'", $user->uid, isset($user->cache) ? $user->cache : '', ip_address(), $value, time(), $key); - + db_query("UPDATE {sessions} SET uid = %d, cache = %d, hostname = '%s', session = '%s', timestamp = %d WHERE sid = '%s'", $user->uid, isset($user->cache) ? $user->cache : '', ip_address(), $value, time(), $key); + if (db_affected_rows()) { // Last access time is updated no more frequently than once every 180 seconds. // This reduces contention in the users table. if ($user->uid && time() - $user->access > variable_get('session_write_interval', 180)) { db_query("UPDATE {users} SET access = %d WHERE uid = %d", time(), $user->uid); } } + else { + // If this query fails, another parallel request probably got here first. + // In that case, any session data generated in this request is discarded. + @db_query("INSERT INTO {sessions} (sid, uid, cache, hostname, session, timestamp) VALUES ('%s', %d, %d, '%s', '%s', %d)", $key, $user->uid, isset($user->cache) ? $user->cache : '', ip_address(), $value, time()); + } return TRUE; } diff -r 6f15c9d74937 -r 589fb7c02327 includes/theme.inc --- a/includes/theme.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/includes/theme.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ Theme system + * @see Theme guide * @see themeable */ @@ -247,8 +247,8 @@ /** * Process a single invocation of the theme hook. $type will be one - * of 'module', 'theme_engine' or 'theme' and it tells us some - * important information. + * of 'module', 'theme_engine', 'base_theme_engine', 'theme', or 'base_theme' + * and it tells us some important information. * * Because $cache is a reference, the cache will be continually * expanded upon; new entries will replace old entries in the @@ -314,7 +314,7 @@ // to provide preprocess functions even if they are not the owner of the current hook. $prefixes += module_list(); } - elseif ($type == 'theme_engine') { + elseif ($type == 'theme_engine' || $type == 'base_theme_engine') { // Theme engines get an extra set that come before the normally named preprocessors. $prefixes[] = $name .'_engine'; // The theme engine also registers on behalf of the theme. The theme or engine name can be used. @@ -381,7 +381,7 @@ // Process each base theme. foreach ($base_theme as $base) { - // If the theme uses a theme engine, process its hooks. + // If the base theme uses a theme engine, process its hooks. $base_path = dirname($base->filename); if ($theme_engine) { _theme_process_registry($cache, $theme_engine, 'base_theme_engine', $base->name, $base_path); @@ -957,18 +957,19 @@ /** * Render a system default template, which is essentially a PHP template. * - * @param $file - * The filename of the template to render. + * @param $template_file + * The filename of the template to render. Note that this will overwrite + * anything stored in $variables['template_file'] if using a preprocess hook. * @param $variables * A keyed array of variables that will appear in the output. * * @return * The output generated by the template. */ -function theme_render_template($file, $variables) { +function theme_render_template($template_file, $variables) { extract($variables, EXTR_SKIP); // Extract the variables to a local namespace ob_start(); // Start output buffering - include "./$file"; // Include the file + include "./$template_file"; // Include the template file $contents = ob_get_contents(); // Get the contents of the buffer ob_end_clean(); // End buffering and discard return $contents; // Return the contents diff -r 6f15c9d74937 -r 589fb7c02327 includes/xmlrpc.inc --- a/includes/xmlrpc.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/includes/xmlrpc.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ message = $message; module_invoke('system', 'check_http_request'); } + elseif ($reset) { + $xmlrpc_error = NULL; + } return $xmlrpc_error; } @@ -427,6 +430,7 @@ function _xmlrpc() { $args = func_get_args(); $url = array_shift($args); + xmlrpc_clear_error(); if (is_array($args[0])) { $method = 'system.multicall'; $multicall_args = array(); @@ -475,3 +479,10 @@ $error = xmlrpc_error(); return ($error != NULL ? $error->message : NULL); } + +/** + * Clears any previous error. + */ +function xmlrpc_clear_error() { + xmlrpc_error(NULL, NULL, TRUE); +} diff -r 6f15c9d74937 -r 589fb7c02327 install.php --- a/install.php Tue Dec 23 14:32:08 2008 +0100 +++ b/install.php Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ 0 && vOffset < e.vLength) ? 'visible' : 'hidden'; $(e).css({left: -hScroll + e.hPosition +'px', visibility: visState}); + + // Check the previous anchor to see if we need to scroll to make room for the header. + // Get the height of the header table and scroll up that amount. + if (prevAnchor != location.hash) { + if (location.hash != '') { + var scrollLocation = $('td'+ location.hash).offset().top - $(e).height(); + $('body, html').scrollTop(scrollLocation); + } + prevAnchor = location.hash; + } } // Only attach to scrollbars once, even if Drupal.attachBehaviors is called diff -r 6f15c9d74937 -r 589fb7c02327 modules/aggregator/aggregator.pages.inc --- a/modules/aggregator/aggregator.pages.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/aggregator/aggregator.pages.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ status; $node->status = $publish; // check for bloggerAPI vs. metaWeblogAPI @@ -275,6 +281,11 @@ node_invoke_nodeapi($node, 'blogapi edit'); + $valid = blogapi_status_error_check($node, $original_status); + if ($valid !== TRUE) { + return $valid; + } + node_validate($node); if ($errors = form_get_errors()) { return blogapi_error(implode("\n", $errors)); @@ -308,6 +319,33 @@ } /** + * Check that the user has permission to save the node with the chosen status. + * + * @return + * TRUE if no error, or the blogapi_error(). + */ +function blogapi_status_error_check($node, $original_status) { + + $node = (object) $node; + + $node_type_default = variable_get('node_options_'. $node->type, array('status', 'promote')); + + // If we don't have the 'administer nodes' permission and the status is + // changing or for a new node the status is not the content type's default, + // then return an error. + if (!user_access('administer nodes') && (($node->status != $original_status) || (empty($node->nid) && $node->status != in_array('status', $node_type_default)))) { + if ($node->status) { + return blogapi_error(t('You do not have permission to publish this type of post. Please save it as a draft instead.')); + } + else { + return blogapi_error(t('You do not have permission to save this post as a draft. Please publish it instead.')); + } + } + return TRUE; +} + + +/** * Blogging API callback. Removes the specified blog node. */ function blogapi_blogger_delete_post($appkey, $postid, $username, $password, $publish) { @@ -437,6 +475,11 @@ * associated with a blog node. */ function blogapi_metaweblog_get_category_list($blogid, $username, $password) { + $user = blogapi_validate_user($username, $password); + if (!$user->uid) { + return blogapi_error($user); + } + if (($error = _blogapi_validate_blogid($blogid)) !== TRUE) { // Return an error if not configured type. return $error; @@ -509,11 +552,59 @@ foreach ($categories as $category) { $node->taxonomy[] = $category['categoryId']; } + $validated = blogapi_mt_validate_terms($node); + if ($validated !== TRUE) { + return $validated; + } node_save($node); return TRUE; } /** + * Blogging API helper - find allowed taxonomy terms for a node type. + */ +function blogapi_mt_validate_terms($node) { + // We do a lot of heavy lifting here since taxonomy module doesn't have a + // stand-alone validation function. + if (module_exists('taxonomy')) { + $found_terms = array(); + if (!empty($node->taxonomy)) { + $term_list = array_unique($node->taxonomy); + $params = $term_list; + $params[] = $node->type; + $result = db_query(db_rewrite_sql("SELECT t.tid, t.vid FROM {term_data} t INNER JOIN {vocabulary_node_types} n ON t.vid = n.vid WHERE t.tid IN (". db_placeholders($term_list) .") AND n.type = '%s'", 't', 'tid'), $params); + $found_terms = array(); + $found_count = 0; + while ($term = db_fetch_object($result)) { + $found_terms[$term->vid][$term->tid] = $term->tid; + $found_count++; + } + // If the counts don't match, some terms are invalid or not accessible to this user. + if (count($term_list) != $found_count) { + return blogapi_error(t('Invalid categories submitted.')); + } + } + // Look up all the vocabularies for this node type. + $result2 = db_query(db_rewrite_sql("SELECT v.vid, v.name, v.required, v.multiple FROM {vocabulary} v INNER JOIN {vocabulary_node_types} n ON v.vid = n.vid WHERE n.type = '%s'", 'v', 'vid'), $node->type); + // Check each vocabulary associated with this node type. + while ($vocabulary = db_fetch_object($result2)) { + // Required vocabularies must have at least one term. + if ($vocabulary->required && empty($found_terms[$vocabulary->vid])) { + return blogapi_error(t('A category from the @vocabulary_name vocabulary is required.', array('@vocabulary_name' => $vocabulary->name))); + } + // Vocabularies that don't allow multiple terms may have at most one. + if (!($vocabulary->multiple) && (isset($found_terms[$vocabulary->vid]) && count($found_terms[$vocabulary->vid]) > 1)) { + return blogapi_error(t('You may only choose one category from the @vocabulary_name vocabulary.'), array('@vocabulary_name' => $vocabulary->name)); + } + } + } + elseif (!empty($node->taxonomy)) { + return blogapi_error(t('Error saving categories. This feature is not available.')); + } + return TRUE; +} + +/** * Blogging API callback. Sends a list of available input formats. */ function blogapi_mt_supported_text_filters() { @@ -544,11 +635,16 @@ return blogapi_error(t('Invalid post.')); } - $node->status = 1; - if (!node_access('update', $node)) { + // Nothing needs to be done if already published. + if ($node->status) { + return; + } + + if (!node_access('update', $node) || !user_access('administer nodes')) { return blogapi_error(t('You do not have permission to update this post.')); } + $node->status = 1; node_save($node); return TRUE; diff -r 6f15c9d74937 -r 589fb7c02327 modules/comment/comment.module --- a/modules/comment/comment.module Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/comment/comment.module Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ uid) { // '===' because we want to modify anonymous users too $edit['name'] = $user->name; diff -r 6f15c9d74937 -r 589fb7c02327 modules/dblog/dblog-rtl.css --- a/modules/dblog/dblog-rtl.css Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/dblog/dblog-rtl.css Tue Dec 23 14:32:19 2008 +0100 @@ -1,6 +1,6 @@ -/* $Id: dblog-rtl.css,v 1.2 2007/11/27 12:09:26 goba Exp $ */ +/* $Id: dblog-rtl.css,v 1.2.2.1 2008/09/02 16:56:49 dries Exp $ */ -#dblog-filter-form .form-item { +#edit-type-wrapper, #edit-severity-wrapper { float: right; padding-right: 0; padding-left: .8em; diff -r 6f15c9d74937 -r 589fb7c02327 modules/dblog/dblog.admin.inc --- a/modules/dblog/dblog.admin.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/dblog/dblog.admin.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ '', - WATCHDOG_WARNING => theme('image', 'misc/watchdog-warning.png', t('warning'), t('warning')), - WATCHDOG_ERROR => theme('image', 'misc/watchdog-error.png', t('error'), t('error')), + WATCHDOG_DEBUG => '', + WATCHDOG_INFO => '', + WATCHDOG_NOTICE => '', + WATCHDOG_WARNING => theme('image', 'misc/watchdog-warning.png', t('warning'), t('warning')), + WATCHDOG_ERROR => theme('image', 'misc/watchdog-error.png', t('error'), t('error')), + WATCHDOG_CRITICAL => theme('image', 'misc/watchdog-error.png', t('critical'), t('critical')), + WATCHDOG_ALERT => theme('image', 'misc/watchdog-error.png', t('alert'), t('alert')), + WATCHDOG_EMERG => theme('image', 'misc/watchdog-error.png', t('emergency'), t('emergency')), ); $classes = array( - WATCHDOG_NOTICE => 'dblog-notice', - WATCHDOG_WARNING => 'dblog-warning', - WATCHDOG_ERROR => 'dblog-error', + WATCHDOG_DEBUG => 'dblog-debug', + WATCHDOG_INFO => 'dblog-info', + WATCHDOG_NOTICE => 'dblog-notice', + WATCHDOG_WARNING => 'dblog-warning', + WATCHDOG_ERROR => 'dblog-error', + WATCHDOG_CRITICAL => 'dblog-critical', + WATCHDOG_ALERT => 'dblog-alert', + WATCHDOG_EMERG => 'dblog-emerg', ); $output = drupal_get_form('dblog_filter_form'); diff -r 6f15c9d74937 -r 589fb7c02327 modules/dblog/dblog.css --- a/modules/dblog/dblog.css Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/dblog/dblog.css Tue Dec 23 14:32:19 2008 +0100 @@ -1,6 +1,6 @@ -/* $Id: dblog.css,v 1.4 2007/09/01 05:27:04 dries Exp $ */ +/* $Id: dblog.css,v 1.4.2.1 2008/09/02 16:56:49 dries Exp $ */ -#dblog-filter-form .form-item { +#edit-type-wrapper, #edit-severity-wrapper { float: left; /* LTR */ padding-right: .8em; /* LTR */ margin: 0.1em; diff -r 6f15c9d74937 -r 589fb7c02327 modules/filter/filter.module --- a/modules/filter/filter.module Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/filter/filter.module Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ '. t("Language negotiation settings determine the site's presentation language. Available options include:") .'

'; $output .= ''; $output .= '

'. t('The path prefix or domain name for a language may be set by editing the available languages. In the absence of an appropriate match, the site is displayed in the default language.', array('@languages' => url('admin/settings/language'))) .'

'; return $output; @@ -234,7 +234,7 @@ '#weight' => 1, ); - // Get language negotiation settings. + // Get language negotiation settings. $mode = variable_get('language_negotiation', LANGUAGE_NEGOTIATION_NONE); $form['locale']['language'] = array( '#type' => (count($names) <= 5 ? 'radios' : 'select'), @@ -261,7 +261,7 @@ '#options' => array('' => t('All languages')) + locale_language_list('name'), '#default_value' => $form['language']['#value'], '#weight' => -10, - '#description' => t('A path alias set for a specific language will always be used when displaying this page in that language, and takes precedence over path aliases set for All languages.'), + '#description' => t('A path alias set for a specific language will always be used when displaying this page in that language, and takes precedence over path aliases set for All languages.'), ); break; @@ -337,7 +337,7 @@ // Reset in-memory cache. $locale_t = NULL; } - + if (!isset($string)) { // Return all cached strings if no string was specified return $locale_t; diff -r 6f15c9d74937 -r 589fb7c02327 modules/node/node.pages.inc --- a/modules/node/node.pages.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/node/node.pages.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ 'submit', + '#access' => !variable_get('node_preview', 0) || (!form_get_errors() && isset($form_state['node_preview'])), '#value' => t('Save'), '#weight' => 5, '#submit' => array('node_form_submit'), diff -r 6f15c9d74937 -r 589fb7c02327 modules/search/search-result.tpl.php --- a/modules/search/search-result.tpl.php Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/search/search-result.tpl.php Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ $score) { - // The database will collate similar words (accented and non-accented forms, etc.), - // and the score is additive, so first add and then insert. - db_query("UPDATE {search_index} SET score = score + %d WHERE word = '%s' AND sid = '%d' AND type = '%s'", $score, $word, $sid, $type); + // Try inserting first because this will succeed most times, but because + // the database collates similar words (accented and non-accented), the + // insert can fail, in which case we need to add the word scores together. + @db_query("INSERT INTO {search_index} (word, sid, type, score) VALUES ('%s', %d, '%s', %f)", $word, $sid, $type, $score); if (!db_affected_rows()) { - db_query("INSERT INTO {search_index} (word, sid, type, score) VALUES ('%s', %d, '%s', %f)", $word, $sid, $type, $score); + db_query("UPDATE {search_index} SET score = score + %f WHERE word = '%s' AND sid = %d AND type = '%s'", $score, $word, $sid, $type); } search_dirty($word); } diff -r 6f15c9d74937 -r 589fb7c02327 modules/system/system.install --- a/modules/system/system.install Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/system/system.install Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ $t('Not enabled'), - 'severity' => REQUIREMENT_ERROR, + 'severity' => REQUIREMENT_WARNING, 'description' => $t('Update notifications are not enabled. It is highly recommended that you enable the update status module from the module administration page in order to stay up-to-date on new releases. For more information please read the Update status handbook page.', array('@update' => 'http://drupal.org/handbook/modules/update', '@module' => url('admin/build/modules'))), ); } @@ -676,16 +676,12 @@ 'default' => ''), 'load_functions' => array( 'description' => t('A serialized array of function names (like node_load) to be called to load an object corresponding to a part of the current path.'), - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => ''), + 'type' => 'text', + 'not null' => TRUE,), 'to_arg_functions' => array( 'description' => t('A serialized array of function names (like user_uid_optional_to_arg) to be called to replace a part of the router path with another string.'), - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => ''), + 'type' => 'text', + 'not null' => TRUE,), 'access_callback' => array( 'description' => t('The callback which determines the access to this router path. Defaults to user_access.'), 'type' => 'varchar', @@ -2512,6 +2508,18 @@ } /** +* Increase the size of the 'load_functions' and 'to_arg_functions' fields in table 'menu_router'. +*/ +function system_update_6048() { + $ret = array(); + db_change_field($ret, 'menu_router', 'load_functions', 'load_functions', array('type' => 'text', 'not null' => TRUE,)); + db_change_field($ret, 'menu_router', 'to_arg_functions', 'to_arg_functions', array('type' => 'text', 'not null' => TRUE,)); + + return $ret; +} + + +/** * @} End of "defgroup updates-5.x-to-6.x" * The next series of updates should start at 7000. */ diff -r 6f15c9d74937 -r 589fb7c02327 modules/system/system.module --- a/modules/system/system.module Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/system/system.module Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ ''")); $header = array( array('data' => t('Action type'), 'field' => 'type'), array('data' => t('Description'), 'field' => 'description'), @@ -1431,7 +1431,7 @@ if (is_numeric($action)) { $aid = $action; // Load stored parameter values from database. - $data = db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = %d", intval($aid))); + $data = db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = '%s'", $aid)); $edit['actions_description'] = $data->description; $edit['actions_type'] = $data->type; $function = $data->callback; diff -r 6f15c9d74937 -r 589fb7c02327 modules/taxonomy/taxonomy.admin.inc --- a/modules/taxonomy/taxonomy.admin.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/taxonomy/taxonomy.admin.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ language]); $languages = language_list(); - foreach ($translations as $language => $translation) { - $links["node_translation_$language"] = array( - 'title' => $languages[$language]->native, - 'href' => "node/$translation->nid", - 'language' => $languages[$language], - 'attributes' => array('title' => $translation->title, 'class' => 'translation-link') - ); + foreach ($languages as $langcode => $language) { + if (isset($translations[$langcode])) { + $links["node_translation_$langcode"] = array( + 'title' => $language->native, + 'href' => 'node/'. $translations[$langcode]->nid, + 'language' => $language, + 'attributes' => array('title' => $translations[$langcode]->title, 'class' => 'translation-link') + ); + } } } return $links; diff -r 6f15c9d74937 -r 589fb7c02327 modules/translation/translation.pages.inc --- a/modules/translation/translation.pages.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/translation/translation.pages.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ status ? t('Published') : t('Not published'); $status .= $translation_node->translate ? ' - '. t('outdated') .'' : ''; if ($translation_node->nid == $tnid) { - $language_name = ''. $language_name .' (source)'; + $language_name = t('@language_name (source)', array('@language_name' => $language_name)); } } else { diff -r 6f15c9d74937 -r 589fb7c02327 modules/update/update.compare.inc --- a/modules/update/update.compare.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/update/update.compare.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ $release) { // First, if this is the existing release, check a few conditions. - if ($projects[$project]['existing_version'] == $version) { + if ($projects[$project]['existing_version'] === $version) { if (isset($release['terms']['Release type']) && in_array('Insecure', $release['terms']['Release type'])) { $projects[$project]['status'] = UPDATE_NOT_SECURE; @@ -438,7 +438,7 @@ } // Stop searching once we hit the currently installed version. - if ($projects[$project]['existing_version'] == $version) { + if ($projects[$project]['existing_version'] === $version) { break; } @@ -513,7 +513,7 @@ // Figure out the status, based on what we've seen and the install type. switch ($projects[$project]['install_type']) { case 'official': - if ($projects[$project]['existing_version'] == $projects[$project]['recommended'] || $projects[$project]['existing_version'] == $projects[$project]['latest_version']) { + if ($projects[$project]['existing_version'] === $projects[$project]['recommended'] || $projects[$project]['existing_version'] === $projects[$project]['latest_version']) { $projects[$project]['status'] = UPDATE_CURRENT; } else { diff -r 6f15c9d74937 -r 589fb7c02327 modules/update/update.install --- a/modules/update/update.install Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/update/update.install Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ $interval) { + // Cron should check for updates if there is no update data cached or if the configured + // update interval has elapsed. + if (!cache_get('update_info', 'cache_update') || ((time() - variable_get('update_last_check', 0)) > $interval)) { update_refresh(); _update_cron_notify(); } diff -r 6f15c9d74937 -r 589fb7c02327 modules/update/update.report.inc --- a/modules/update/update.report.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/update/update.report.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ \n"; if (isset($project['recommended'])) { - if ($project['status'] != UPDATE_CURRENT || $project['existing_version'] != $project['recommended']) { + if ($project['status'] != UPDATE_CURRENT || $project['existing_version'] !== $project['recommended']) { // First, figure out what to recommend. // If there's only 1 security update and it has the same version we're // recommending, give it the same CSS class as if it was recommended, // but don't print out a separate "Recommended" line for this project. - if (!empty($project['security updates']) && count($project['security updates']) == 1 && $project['security updates'][0]['version'] == $project['recommended']) { + if (!empty($project['security updates']) && count($project['security updates']) == 1 && $project['security updates'][0]['version'] === $project['recommended']) { $security_class = ' version-recommended version-recommended-strong'; } else { @@ -123,14 +123,14 @@ $version_class = 'version-recommended'; // Apply an extra class if we're displaying both a recommended // version and anything else for an extra visual hint. - if ($project['recommended'] != $project['latest_version'] + if ($project['recommended'] !== $project['latest_version'] || !empty($project['also']) || ($project['install_type'] == 'dev' && isset($project['dev_version']) - && $project['latest_version'] != $project['dev_version'] - && $project['recommended'] != $project['dev_version']) + && $project['latest_version'] !== $project['dev_version'] + && $project['recommended'] !== $project['dev_version']) || (isset($project['security updates'][0]) - && $project['recommended'] != $project['security updates'][0]) + && $project['recommended'] !== $project['security updates'][0]) ) { $version_class .= ' version-recommended-strong'; } @@ -145,13 +145,13 @@ } } - if ($project['recommended'] != $project['latest_version']) { + if ($project['recommended'] !== $project['latest_version']) { $row .= theme('update_version', $project['releases'][$project['latest_version']], t('Latest version:'), 'version-latest'); } if ($project['install_type'] == 'dev' && $project['status'] != UPDATE_CURRENT && isset($project['dev_version']) - && $project['recommended'] != $project['dev_version']) { + && $project['recommended'] !== $project['dev_version']) { $row .= theme('update_version', $project['releases'][$project['dev_version']], t('Development version:'), 'version-latest'); } } diff -r 6f15c9d74937 -r 589fb7c02327 modules/upload/upload.module --- a/modules/upload/upload.module Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/upload/upload.module Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ uid != 1 || user_access('upload files')) && ($file = file_save_upload('upload', $validators, file_directory_path()))) { + if (user_access('upload files') && ($file = file_save_upload('upload', $validators, file_directory_path()))) { $file->list = variable_get('upload_list_default', 1); $file->description = $file->filename; $file->weight = 0; diff -r 6f15c9d74937 -r 589fb7c02327 modules/user/user.module --- a/modules/user/user.module Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/user/user.module Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ $form_values['name'], 'pass' => trim($form_values['pass']), 'status' => 1)); + if ($account && drupal_is_denied('mail', $account->mail)) { + form_set_error('name', t('The name %name is registered using a reserved e-mail address and therefore could not be logged in.', array('%name' => $account->name))); + } + // Name and pass keys are required. - if (!empty($form_values['name']) && !empty($form_values['pass']) && - $account = user_load(array('name' => $form_values['name'], 'pass' => trim($form_values['pass']), 'status' => 1))) { + // The user is about to be logged in, so make sure no error was previously + // encountered in the validation process. + if (!form_get_errors() && !empty($form_values['name']) && !empty($form_values['pass']) && $account) { $user = $account; user_authenticate_finalize($form_values); return $user; @@ -2064,7 +2073,7 @@ '!site' => variable_get('site_name', 'Drupal'), '!login_url' => user_pass_reset_url($account), '!uri' => $base_url, - '!uri_brief' => substr($base_url, strlen('http://')), + '!uri_brief' => preg_replace('!^https?://!', '', $base_url), '!mailto' => $account->mail, '!date' => format_date(time(), 'medium', '', NULL, $language->language), '!login_uri' => url('user', array('absolute' => TRUE, 'language' => $language)), diff -r 6f15c9d74937 -r 589fb7c02327 modules/user/user.pages.inc --- a/modules/user/user.pages.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/user/user.pages.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ $name))); + } + // Try to load by email. $account = user_load(array('mail' => $name, 'status' => 1)); if (!$account) { @@ -87,6 +94,12 @@ $current = time(); // Some redundant checks for extra security ? if ($timestamp < $current && $account = user_load(array('uid' => $uid, 'status' => 1)) ) { + // Deny one-time login to blocked accounts. + if (drupal_is_denied('user', $account->name) || drupal_is_denied('mail', $account->mail)) { + drupal_set_message(t('You have tried to use a one-time login for an account which has been blocked.'), 'error'); + drupal_goto(); + } + // No time out for first time login. if ($account->login && $current - $timestamp > $timeout) { drupal_set_message(t('You have tried to use a one-time login link that has expired. Please request a new one using the form below.')); diff -r 6f15c9d74937 -r 589fb7c02327 themes/pushbutton/page.tpl.php --- a/themes/pushbutton/page.tpl.php Tue Dec 23 14:32:08 2008 +0100 +++ b/themes/pushbutton/page.tpl.php Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ @@ -10,7 +10,7 @@ - +
.
@@ -112,7 +112,7 @@