Mercurial > defr > drupal > core
changeset 11:589fb7c02327 6.5
Drupal 6.5
line wrap: on
line diff
--- 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.
--- 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 @@ <?php -// $Id: actions.inc,v 1.8.2.3 2008/08/12 06:57:31 dries Exp $ +// $Id: actions.inc,v 1.8.2.4 2008/09/05 09:29:22 dries Exp $ /** * @file @@ -54,7 +54,7 @@ $where_values = array(); foreach ($action_ids as $action_id) { if (is_numeric($action_id)) { - $where[] = 'OR aid = %d'; + $where[] = "OR aid = '%s'"; $where_values[] = $action_id; } elseif (isset($available_actions[$action_id])) { @@ -93,7 +93,7 @@ else { // If it's a configurable action, retrieve stored parameters. if (is_numeric($action_ids)) { - $action = db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = %d", $action_ids)); + $action = db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = '%s'", $action_ids)); $function = $action->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); }
--- 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 @@ <?php -// $Id: bootstrap.inc,v 1.206.2.3 2008/07/09 19:15:59 goba Exp $ +// $Id: bootstrap.inc,v 1.206.2.4 2008/08/18 18:56:30 dries Exp $ /** * @file @@ -329,6 +329,15 @@ $cookie_domain = check_plain($_SERVER['HTTP_HOST']); } } + // To prevent session cookies from being hijacked, a user can configure the + // SSL version of their website to only transfer session cookies via SSL by + // using PHP's session.cookie_secure setting. The browser will then use two + // separate session cookies for the HTTPS and HTTP versions of the site. So we + // must use different session identifiers for HTTPS and HTTP to prevent a + // cookie collision. + if (ini_get('session.cookie_secure')) { + $session_name .= 'SSL'; + } // Strip leading periods, www., and port numbers from cookie domain. $cookie_domain = ltrim($cookie_domain, '.'); if (strpos($cookie_domain, 'www.') === 0) {
--- a/includes/common.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/includes/common.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ <?php -// $Id: common.inc,v 1.756.2.24 2008/08/13 23:59:12 drumm Exp $ +// $Id: common.inc,v 1.756.2.27 2008/10/08 20:12:17 goba Exp $ /** * @file @@ -2061,17 +2061,23 @@ // page request. $query_string = '?'. substr(variable_get('css_js_query_string', '0'), 0, 1); + // For inline Javascript to validate as XHTML, all Javascript containing + // XHTML needs to be wrapped in CDATA. To make that backwards compatible + // with HTML 4, we need to comment out the CDATA-tag. + $embed_prefix = "\n<!--//--><![CDATA[//><!--\n"; + $embed_suffix = "\n//--><!]]>\n"; + foreach ($javascript as $type => $data) { if (!$data) continue; switch ($type) { case 'setting': - $output .= '<script type="text/javascript">jQuery.extend(Drupal.settings, '. drupal_to_js(call_user_func_array('array_merge_recursive', $data)) .");</script>\n"; + $output .= '<script type="text/javascript">' . $embed_prefix . 'jQuery.extend(Drupal.settings, ' . drupal_to_js(call_user_func_array('array_merge_recursive', $data)) . ");" . $embed_suffix . "</script>\n"; break; case 'inline': foreach ($data as $info) { - $output .= '<script type="text/javascript"'. ($info['defer'] ? ' defer="defer"' : '') .'>'. $info['code'] ."</script>\n"; + $output .= '<script type="text/javascript"' . ($info['defer'] ? ' defer="defer"' : '') . '>' . $embed_prefix . $info['code'] . $embed_suffix . "</script>\n"; } break; default:
--- 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 @@ <?php -// $Id: file.inc,v 1.121.2.3 2008/08/13 23:59:12 drumm Exp $ +// $Id: file.inc,v 1.121.2.4 2008/09/17 08:13:07 goba Exp $ /** * @file @@ -884,7 +884,7 @@ $files = array(); if (is_dir($dir) && $handle = opendir($dir)) { - while (false !== ($file = readdir($handle))) { + while (FALSE !== ($file = readdir($handle))) { if (!in_array($file, $nomask) && $file[0] != '.') { if (is_dir("$dir/$file") && $recurse) { // Give priority to files in this folder by merging them in after any subdirectory files.
--- a/includes/form.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/includes/form.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ <?php -// $Id: form.inc,v 1.265.2.10 2008/08/13 23:59:12 drumm Exp $ +// $Id: form.inc,v 1.265.2.12 2008/09/23 10:51:16 goba Exp $ /** * @defgroup forms Form builder functions @@ -782,12 +782,17 @@ * element where the #parents array starts with 'foo'. * @param $message * The error message to present to the user. + * @param $reset + * Reset the form errors static cache. * @return * Never use the return value of this function, use form_get_errors and * form_get_error instead. */ -function form_set_error($name = NULL, $message = '') { +function form_set_error($name = NULL, $message = '', $reset = FALSE) { static $form = array(); + if ($reset) { + $form = array(); + } if (isset($name) && !isset($form[$name])) { $form[$name] = $message; if ($message) { @@ -934,7 +939,7 @@ // If some callback set #cache, we need to flip a static flag so later it // can be found. - if (isset($form['#cache'])) { + if (!empty($form['#cache'])) { $cache = $form['#cache']; } // We are on the top form, we can copy back #cache if it's set.
--- a/includes/install.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/includes/install.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ <?php -// $Id: install.inc,v 1.56.2.2 2008/02/11 15:10:26 goba Exp $ +// $Id: install.inc,v 1.56.2.3 2008/08/14 09:26:43 dries Exp $ define('SCHEMA_UNINSTALLED', -1); define('SCHEMA_INSTALLED', 0); @@ -35,8 +35,8 @@ * @param $module * A module name. * @return - * If the module has updates, an array of available updates. Otherwise, - * FALSE. + * If the module has updates, an array of available updates sorted by version. + * Otherwise, FALSE. */ function drupal_get_schema_versions($module) { $updates = array(); @@ -52,6 +52,7 @@ if (count($updates) == 0) { return FALSE; } + sort($updates, SORT_NUMERIC); return $updates; }
--- a/includes/locale.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/includes/locale.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ <?php -// $Id: locale.inc,v 1.174.2.1 2008/07/09 21:48:28 goba Exp $ +// $Id: locale.inc,v 1.174.2.4 2008/09/17 08:47:04 goba Exp $ /** * @file @@ -267,7 +267,7 @@ ); $form['domain'] = array('#type' => '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 <em>Domain name only</em>, 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. <strong>This value must include a protocol as part of the string.</strong> <em>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.</em>'), ); @@ -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"),
--- 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 @@ <?php -// $Id: mail.inc,v 1.8.2.3 2008/05/19 08:19:00 goba Exp $ +// $Id: mail.inc,v 1.8.2.4 2008/10/06 11:04:08 dries Exp $ /** * Compose and optionally send an e-mail message. @@ -35,7 +35,7 @@ * foreach ($accounts as $account) { * $params['account'] = $account; * // example_mail() will be called based on the first drupal_mail() parameter. - * drupal_mail('example', 'notify', $account->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();
--- 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 @@ <?php -// $Id: menu.inc,v 1.255.2.17 2008/07/09 15:23:50 goba Exp $ +// $Id: menu.inc,v 1.255.2.21 2008/10/08 12:33:55 goba Exp $ /** * @file @@ -335,7 +335,9 @@ if (_menu_site_is_offline()) { return MENU_SITE_OFFLINE; } - if (variable_get('menu_rebuild_needed', FALSE)) { + // Rebuild if we know it's needed, or if the menu masks are missing which + // occurs rarely, likely due to a race condition of multiple rebuilds. + if (variable_get('menu_rebuild_needed', FALSE) || !variable_get('menu_masks', array())) { menu_rebuild(); } if ($router_item = menu_get_item($path)) { @@ -362,7 +364,7 @@ * @return * Returns TRUE for success, FALSE if an object cannot be loaded. * Names of object loading functions are placed in $item['load_functions']. - * Loaded objects are placed in $map[]; keys are the same as keys in the + * Loaded objects are placed in $map[]; keys are the same as keys in the * $item['load_functions'] array. * $item['access'] is set to FALSE if an object cannot be loaded. */ @@ -471,10 +473,10 @@ * @return * No return value. * $item['title'] is localized according to $item['title_callback']. - * If an item's callback is check_plain(), $item['options']['html'] becomes + * If an item's callback is check_plain(), $item['options']['html'] becomes * TRUE. * $item['description'] is translated using t(). - * When doing link translation and the $item['options']['attributes']['title'] + * When doing link translation and the $item['options']['attributes']['title'] * (link title attribute) matches the description, it is translated as well. */ function _menu_item_localize(&$item, $map, $link_translate = FALSE) { @@ -657,14 +659,14 @@ _menu_item_localize($item, $map, TRUE); } } - + // Allow other customizations - e.g. adding a page-specific query string to the // options array. For performance reasons we only invoke this hook if the link // has the 'alter' flag set in the options array. if (!empty($item['options']['alter'])) { drupal_alter('translated_menu_link', $item, $map); } - + return $map; } @@ -1159,6 +1161,10 @@ function menu_get_active_help() { $output = ''; $router_path = menu_tab_root_path(); + // We will always have a path unless we are on a 403 or 404. + if (!$router_path) { + return ''; + } $arg = drupal_help_arg(arg(NULL)); $empty_arg = drupal_help_arg(); @@ -1557,7 +1563,7 @@ */ function menu_get_active_breadcrumb() { $breadcrumb = array(); - + // No breadcrumb for the front page. if (drupal_is_front_page()) { return $breadcrumb; @@ -1735,8 +1741,11 @@ $existing_item = db_fetch_array(db_query("SELECT mlid, menu_name, plid, customized, has_children, updated FROM {menu_links} WHERE link_path = '%s' AND module = '%s'", $item['link_path'], 'system')); if ($existing_item) { $item['mlid'] = $existing_item['mlid']; - $item['menu_name'] = $existing_item['menu_name']; - $item['plid'] = $existing_item['plid']; + // A change in hook_menu may move the link to a different menu + if (empty($item['menu_name']) || ($item['menu_name'] == $existing_item['menu_name'])) { + $item['menu_name'] = $existing_item['menu_name']; + $item['plid'] = $existing_item['plid']; + } $item['has_children'] = $existing_item['has_children']; $item['updated'] = $existing_item['updated']; } @@ -1828,6 +1837,9 @@ * - mlid Set to an existing value, or 0 or NULL to insert a new link. * - plid The mlid of the parent. * - router_path The path of the relevant router item. + * @return + * The mlid of the saved menu link, or FALSE if the menu link could not be + * saved. */ function menu_link_save(&$item) { $menu = menu_router_build(); @@ -2060,7 +2072,10 @@ break; case 'update': db_query("UPDATE {menu_links} SET link_title = '%s' WHERE link_path = '%s' AND customized = 0 AND module = '%s'", $link_title, $link_path, $module); - menu_cache_clear(); + $result = db_query("SELECT menu_name FROM {menu_links} WHERE link_path = '%s' AND customized = 0 AND module = '%s'", $link_path, $module); + while ($item = db_fetch_array($result)) { + menu_cache_clear($item['menu_name']); + } break; case 'delete': menu_link_delete(NULL, $link_path);
--- a/includes/session.inc Tue Dec 23 14:32:08 2008 +0100 +++ b/includes/session.inc Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ <?php -// $Id: session.inc,v 1.44.2.2 2008/08/12 10:29:03 dries Exp $ +// $Id: session.inc,v 1.44.2.3 2008/09/17 07:53:08 goba Exp $ /** * @file @@ -57,31 +57,27 @@ global $user; // If saving of session data is disabled or if the client doesn't have a session, - // and one isn't being created ($value), do nothing. + // and one isn't being created ($value), do nothing. This keeps crawlers out of + // the session table. This reduces memory and server load, and gives more useful + // statistics. We can't eliminate anonymous session table rows without breaking + // the throttle module and the "Who's Online" block. if (!session_save_session() || (empty($_COOKIE[session_name()]) && empty($value))) { return TRUE; } - $result = db_result(db_query("SELECT COUNT(*) FROM {sessions} WHERE sid = '%s'", $key)); - - if (!$result) { - // Only save session data when when the browser sends a cookie. This keeps - // crawlers out of session table. This reduces memory and server load, - // and gives more useful statistics. We can't eliminate anonymous session - // table rows without breaking throttle module and "Who's Online" block. - if ($user->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; }
--- 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 @@ <?php -// $Id: theme.inc,v 1.415.2.9 2008/07/09 21:48:28 goba Exp $ +// $Id: theme.inc,v 1.415.2.12 2008/09/17 08:57:23 goba Exp $ /** * @file @@ -8,7 +8,7 @@ * The theme system allows for nearly all output of the Drupal system to be * customized by user themes. * - * @see <a href="http://drupal.org/node/253">Theme system</a> + * @see <a href="http://drupal.org/node/171179">Theme guide</a> * @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
--- 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 @@ <?php -// $Id: xmlrpc.inc,v 1.47.2.2 2008/04/14 18:01:19 dries Exp $ +// $Id: xmlrpc.inc,v 1.47.2.3 2008/09/17 06:28:54 goba Exp $ /** * @file @@ -342,7 +342,7 @@ } -function xmlrpc_error($code = NULL, $message = NULL) { +function xmlrpc_error($code = NULL, $message = NULL, $reset = FALSE) { static $xmlrpc_error; if (isset($code)) { $xmlrpc_error = new stdClass(); @@ -351,6 +351,9 @@ $xmlrpc_error->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); +}
--- 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 @@ <?php -// $Id: install.php,v 1.113.2.5 2008/07/18 07:17:44 dries Exp $ +// $Id: install.php,v 1.113.2.6 2008/09/17 08:47:04 goba Exp $ require_once './includes/install.inc'; @@ -90,7 +90,7 @@ // Locale selection if (!empty($_GET['locale'])) { - $install_locale = preg_replace('/[^a-zA-Z_0-9]/', '', $_GET['locale']); + $install_locale = preg_replace('/[^a-zA-Z_0-9\-]/', '', $_GET['locale']); } elseif (($install_locale = install_select_locale($profile)) !== FALSE) { install_goto("install.php?profile=$profile&locale=$install_locale");
--- a/misc/tabledrag.js Tue Dec 23 14:32:08 2008 +0100 +++ b/misc/tabledrag.js Tue Dec 23 14:32:19 2008 +0100 @@ -1,4 +1,4 @@ -// $Id: tabledrag.js,v 1.13.2.3 2008/06/12 19:13:25 dries Exp $ +// $Id: tabledrag.js,v 1.13.2.4 2008/09/17 07:59:39 goba Exp $ /** * Drag and drop table rows with field manipulation. @@ -73,10 +73,12 @@ this.indentCount = 1; // Total width of indents, set in makeDraggable. // Find the width of indentations to measure mouse movements against. // Because the table doesn't need to start with any indentations, we - // manually create an empty div, check it's width, then remove. - var indent = $(Drupal.theme('tableDragIndentation')).appendTo('body'); - this.indentAmount = parseInt(indent.css('width')); - indent.remove(); + // manually append 2 indentations in the first draggable row, measure + // the offset, then remove. + var indent = Drupal.theme('tableDragIndentation'); + var testCell = $('tr.draggable:first td:first', table).prepend(indent).prepend(indent); + this.indentAmount = $('.indentation', testCell).get(1).offsetLeft - $('.indentation', testCell).get(0).offsetLeft; + $('.indentation', testCell).slice(0, 2).remove(); } // Make each applicable row draggable. @@ -407,7 +409,7 @@ if (self.indentEnabled) { var xDiff = self.currentMouseCoords.x - self.dragObject.indentMousePos.x; // Set the number of indentations the mouse has been moved left or right. - var indentDiff = parseInt(xDiff / self.indentAmount * self.rtl); + var indentDiff = Math.round(xDiff / self.indentAmount * self.rtl); // Indent the row with our estimated diff, which may be further // restricted according to the rows around this row. var indentChange = self.rowObject.indent(indentDiff);
--- a/misc/tableheader.js Tue Dec 23 14:32:08 2008 +0100 +++ b/misc/tableheader.js Tue Dec 23 14:32:19 2008 +0100 @@ -1,4 +1,4 @@ -// $Id: tableheader.js,v 1.16 2008/01/30 10:17:39 goba Exp $ +// $Id: tableheader.js,v 1.16.2.1 2008/10/01 23:30:36 goba Exp $ Drupal.tableHeaderDoScroll = function() { if (typeof(Drupal.tableHeaderOnScroll)=='function') { @@ -35,6 +35,9 @@ $(this).addClass('tableHeader-processed'); }); + // Define the anchor holding var. + var prevAnchor = ''; + // Track positioning and visibility. function tracker(e) { // Save positioning data. @@ -62,6 +65,16 @@ var vOffset = (document.documentElement.scrollTop || document.body.scrollTop) - e.vPosition; var visState = (vOffset > 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
--- 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 @@ <?php -// $Id: aggregator.pages.inc,v 1.12 2008/01/08 10:35:40 goba Exp $ +// $Id: aggregator.pages.inc,v 1.12.2.1 2008/08/16 21:13:48 dries Exp $ /** * @file @@ -60,7 +60,6 @@ * The items HTML. */ function aggregator_page_category($arg1, $arg2 = NULL) { - drupal_set_breadcrumb(array_merge(drupal_get_breadcrumb(), array(l(t('Categories'), 'aggregator/categories')))); // If there are two arguments then we are called as a form, $arg1 is // $form_state and $arg2 is $category. Otherwise, $arg1 is $category. $category = is_array($arg2) ? $arg2 : $arg1;
--- a/modules/blogapi/blogapi.module Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/blogapi/blogapi.module Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ <?php -// $Id: blogapi.module,v 1.115.2.3 2008/08/13 23:59:13 drumm Exp $ +// $Id: blogapi.module,v 1.115.2.5 2008/10/08 20:12:17 goba Exp $ /** * @file @@ -222,6 +222,11 @@ node_invoke_nodeapi($edit, 'blogapi new'); + $valid = blogapi_status_error_check($edit, $publish); + if ($valid !== TRUE) { + return $valid; + } + node_validate($edit); if ($errors = form_get_errors()) { return blogapi_error(implode("\n", $errors)); @@ -259,7 +264,8 @@ if (!node_access('update', $node)) { return blogapi_error(t('You do not have permission to update this post.')); } - + // Save the original status for validation of permissions. + $original_status = $node->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;
--- 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 @@ <?php -// $Id: comment.module,v 1.617.2.2 2008/04/25 20:58:46 goba Exp $ +// $Id: comment.module,v 1.617.2.3 2008/09/17 06:22:38 goba Exp $ /** * @file @@ -753,7 +753,9 @@ } } - $edit['timestamp'] = time(); + if (empty($edit['timestamp'])) { + $edit['timestamp'] = time(); + } if ($edit['uid'] === $user->uid) { // '===' because we want to modify anonymous users too $edit['name'] = $user->name;
--- 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;
--- 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 @@ <?php -// $Id: dblog.admin.inc,v 1.6 2008/01/08 10:35:41 goba Exp $ +// $Id: dblog.admin.inc,v 1.6.2.1 2008/09/17 05:47:53 goba Exp $ /** * @file @@ -31,14 +31,24 @@ $filter = dblog_build_filter_query(); $rows = array(); $icons = array( - 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_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');
--- 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;
--- 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 @@ <?php -// $Id: filter.module,v 1.204.2.4 2008/08/13 23:59:13 drumm Exp $ +// $Id: filter.module,v 1.204.2.7 2008/09/17 12:47:14 goba Exp $ /** * @file @@ -932,7 +932,7 @@ * for scripts and styles. */ function filter_xss_admin($string) { - return filter_xss($string, array('a', 'abbr', 'acronym', 'address', 'b', 'bdo', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'col', 'colgroup', 'dd', 'del', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'ins', 'kbd', 'li', 'ol', 'p', 'param', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var')); + return filter_xss($string, array('a', 'abbr', 'acronym', 'address', 'b', 'bdo', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'col', 'colgroup', 'dd', 'del', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'ins', 'kbd', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var')); } /** @@ -953,8 +953,6 @@ * an XSS attack. * @param $allowed_tags * An array of allowed tags. - * @param $format - * The format to use. */ function filter_xss($string, $allowed_tags = array('a', 'em', 'strong', 'cite', 'code', 'ul', 'ol', 'li', 'dl', 'dt', 'dd')) { // Only operate on valid UTF-8 strings. This is necessary to prevent cross @@ -1174,7 +1172,7 @@ function filter_xss_bad_protocol($string, $decode = TRUE) { static $allowed_protocols; if (!isset($allowed_protocols)) { - $allowed_protocols = array_flip(variable_get('filter_allowed_protocols', array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'mailto', 'irc', 'ssh', 'sftp', 'webcal'))); + $allowed_protocols = array_flip(variable_get('filter_allowed_protocols', array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'mailto', 'irc', 'ssh', 'sftp', 'webcal', 'rtsp'))); } // Get the plain text representation of the attribute value (i.e. its meaning).
--- a/modules/locale/locale.module Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/locale/locale.module Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ <?php -// $Id: locale.module,v 1.212.2.2 2008/07/09 21:48:28 goba Exp $ +// $Id: locale.module,v 1.212.2.4 2008/09/08 21:51:50 dries Exp $ /** * @file @@ -51,7 +51,7 @@ $output = '<p>'. t("Language negotiation settings determine the site's presentation language. Available options include:") .'</p>'; $output .= '<ul><li>'. t('<strong>None.</strong> The default language is used for site presentation, though users may (optionally) select a preferred language on the <em>My Account</em> page. (User language preferences will be used for site e-mails, if available.)') .'</li>'; $output .= '<li>'. t('<strong>Path prefix only.</strong> The presentation language is determined by examining the path for a language code or other custom string that matches the path prefix (if any) specified for each language. If a suitable prefix is not identified, the default language is used. <em>Example: "example.com/de/contact" sets presentation language to German based on the use of "de" within the path.</em>') .'</li>'; - $output .= '<li>'. t("<strong>Path prefix with language fallback.</strong> The presentation language is determined by examining the path for a language code or other custom string that matches the path prefix (if any) specified for each language. If a suitable prefix is not identified, the display language is determined by the user's language preferences from the <em>My Account</em> page, or by the browser's language settings. If a presentation language cannot be determined, the default language is used.") .'</t>'; + $output .= '<li>'. t("<strong>Path prefix with language fallback.</strong> The presentation language is determined by examining the path for a language code or other custom string that matches the path prefix (if any) specified for each language. If a suitable prefix is not identified, the display language is determined by the user's language preferences from the <em>My Account</em> page, or by the browser's language settings. If a presentation language cannot be determined, the default language is used.") .'</li>'; $output .= '<li>'. t('<strong>Domain name only.</strong> The presentation language is determined by examining the domain used to access the site, and comparing it to the language domain (if any) specified for each language. If a match is not identified, the default language is used. <em>Example: "http://de.example.com/contact" sets presentation language to German based on the use of "http://de.example.com" in the domain.</em>') .'</li></ul>'; $output .= '<p>'. t('The path prefix or domain name for a language may be set by editing the <a href="@languages">available languages</a>. In the absence of an appropriate match, the site is displayed in the <a href="@languages">default language</a>.', array('@languages' => url('admin/settings/language'))) .'</p>'; 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 <am>All languages</em>.'), + '#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 <em>All languages</em>.'), ); 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;
--- 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 @@ <?php -// $Id: node.pages.inc,v 1.28.2.1 2008/02/27 19:44:44 goba Exp $ +// $Id: node.pages.inc,v 1.28.2.2 2008/09/17 07:42:35 goba Exp $ /** * @file @@ -230,6 +230,7 @@ $form['buttons'] = array(); $form['buttons']['submit'] = array( '#type' => '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'),
--- 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 @@ <?php -// $Id: search-result.tpl.php,v 1.1 2007/10/31 18:06:38 dries Exp $ +// $Id: search-result.tpl.php,v 1.1.2.1 2008/08/28 08:21:44 dries Exp $ /** * @file search-result.tpl.php @@ -15,7 +15,7 @@ * - $snippet: A small preview of the result. Does not apply to user searches. * - $info: String of all the meta information ready for print. Does not apply * to user searches. - * - $info_split: Contains same data as $info split into a keyed array. + * - $info_split: Contains same data as $info, split into a keyed array. * - $type: The type of search, e.g., "node" or "user". * * Default keys within $info_split:
--- a/modules/search/search.module Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/search/search.module Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ <?php -// $Id: search.module,v 1.250.2.3 2008/08/13 06:59:49 dries Exp $ +// $Id: search.module,v 1.250.2.4 2008/09/17 06:42:20 goba Exp $ /** * @file @@ -572,11 +572,12 @@ // Insert results into search index foreach ($results[0] as $word => $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); }
--- 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 @@ <?php -// $Id: system.install,v 1.238.2.3 2008/04/25 21:24:20 goba Exp $ +// $Id: system.install,v 1.238.2.5 2008/09/17 05:33:36 goba Exp $ /** * Test and report Drupal installation requirements. @@ -273,7 +273,7 @@ if (!module_exists('update')) { $requirements['update status'] = array( 'value' => $t('Not enabled'), - 'severity' => REQUIREMENT_ERROR, + 'severity' => REQUIREMENT_WARNING, 'description' => $t('Update notifications are not enabled. It is <strong>highly recommended</strong> that you enable the update status module from the <a href="@module">module administration page</a> in order to stay up-to-date on new releases. For more information please read the <a href="@update">Update status handbook page</a>.', 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. */
--- 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 @@ <?php -// $Id: system.module,v 1.585.2.16 2008/08/13 23:59:13 drumm Exp $ +// $Id: system.module,v 1.585.2.20 2008/10/08 20:12:18 goba Exp $ /** * @file @@ -9,7 +9,7 @@ /** * The current system version. */ -define('VERSION', '6.4'); +define('VERSION', '6.5'); /** * Core API compatibility. @@ -39,7 +39,7 @@ /** * Maximum age of temporary files in seconds. */ -define('DRUPAL_MAXIMUM_TEMP_FILE_AGE', 1440); +define('DRUPAL_MAXIMUM_TEMP_FILE_AGE', 21600); /** * Implementation of hook_help(). @@ -1327,7 +1327,7 @@ } $row = array(); - $instances_present = db_fetch_object(db_query("SELECT aid FROM {actions} WHERE parameters != ''")); + $instances_present = db_fetch_object(db_query("SELECT aid FROM {actions} WHERE parameters <> ''")); $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;
--- 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 @@ <?php -// $Id: taxonomy.admin.inc,v 1.22.2.1 2008/02/07 20:46:57 goba Exp $ +// $Id: taxonomy.admin.inc,v 1.22.2.2 2008/10/08 14:23:59 goba Exp $ /** * @file @@ -259,7 +259,7 @@ ); $page = isset($_GET['page']) ? $_GET['page'] : 0; - $page_increment = 10; // Number of terms per page. + $page_increment = variable_get('taxonomy_terms_per_page_admin', 100); // Number of terms per page. $page_entries = 0; // Elements shown on this page. $before_entries = 0; // Elements at the root level before this page. $after_entries = 0; // Elements at the root level after this page.
--- a/modules/taxonomy/taxonomy.module Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/taxonomy/taxonomy.module Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ <?php -// $Id: taxonomy.module,v 1.414.2.4 2008/06/25 08:00:57 goba Exp $ +// $Id: taxonomy.module,v 1.414.2.5 2008/09/17 12:55:37 goba Exp $ /** * @file @@ -973,7 +973,7 @@ * The vocabulary's ID * * @return - * The vocabulary object with all of its metadata, if exists, NULL otherwise. + * The vocabulary object with all of its metadata, if exists, FALSE otherwise. * Results are statically cached. */ function taxonomy_vocabulary_load($vid) { @@ -996,8 +996,8 @@ } } - // Return NULL if this vocabulary does not exist. - return !empty($vocabularies[$vid]) ? $vocabularies[$vid] : NULL; + // Return FALSE if this vocabulary does not exist. + return !empty($vocabularies[$vid]) ? $vocabularies[$vid] : FALSE; } /**
--- a/modules/translation/translation.module Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/translation/translation.module Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ <?php -// $Id: translation.module,v 1.23 2008/01/28 11:38:58 goba Exp $ +// $Id: translation.module,v 1.23.2.1 2008/08/16 21:37:45 dries Exp $ /** * @file @@ -165,13 +165,15 @@ // Do not show link to the same node. unset($translations[$node->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;
--- 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 @@ <?php -// $Id: translation.pages.inc,v 1.2 2008/01/07 13:18:40 goba Exp $ +// $Id: translation.pages.inc,v 1.2.2.1 2008/09/30 10:50:43 goba Exp $ /** * @file @@ -40,7 +40,7 @@ $status = $translation_node->status ? t('Published') : t('Not published'); $status .= $translation_node->translate ? ' - <span class="marker">'. t('outdated') .'</span>' : ''; if ($translation_node->nid == $tnid) { - $language_name = '<strong>'. $language_name .'</strong> (source)'; + $language_name = t('<strong>@language_name</strong> (source)', array('@language_name' => $language_name)); } } else {
--- 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 @@ <?php -// $Id: update.compare.inc,v 1.8.2.1 2008/08/12 05:10:12 dries Exp $ +// $Id: update.compare.inc,v 1.8.2.2 2008/08/28 08:14:56 dries Exp $ /** * @file @@ -349,7 +349,7 @@ } foreach ($available[$project]['releases'] as $version => $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 {
--- 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 @@ <?php -// $Id: update.install,v 1.4 2008/02/03 18:38:14 goba Exp $ +// $Id: update.install,v 1.4.2.1 2008/08/28 08:14:56 dries Exp $ /** * Implementation of hook_install(). @@ -41,7 +41,7 @@ } /** - * Private helper to clear out stale variables from update_status 5.x contrib. + * Private helper to clear out stale variables from update_status 5.x contrib. * * @see update_install() * @see update_update_6000()
--- a/modules/update/update.module Tue Dec 23 14:32:08 2008 +0100 +++ b/modules/update/update.module Tue Dec 23 14:32:19 2008 +0100 @@ -1,5 +1,5 @@ <?php -// $Id: update.module,v 1.17 2008/01/30 10:14:42 goba Exp $ +// $Id: update.module,v 1.17.2.1 2008/09/23 10:19:02 goba Exp $ /** * @file @@ -286,7 +286,9 @@ function update_cron() { $frequency = variable_get('update_check_frequency', 1); $interval = 60 * 60 * 24 * $frequency; - if (time() - variable_get('update_last_check', 0) > $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(); }
--- 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 @@ <?php -// $Id: update.report.inc,v 1.10.2.1 2008/02/05 09:59:21 goba Exp $ +// $Id: update.report.inc,v 1.10.2.2 2008/08/28 08:14:56 dries Exp $ /** * @file @@ -109,13 +109,13 @@ $row .= "<div class=\"versions\">\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'); } }
--- 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 @@ <?php -// $Id: upload.module,v 1.197.2.2 2008/08/13 23:59:14 drumm Exp $ +// $Id: upload.module,v 1.197.2.3 2008/10/08 20:12:18 goba Exp $ /** * @file @@ -178,7 +178,7 @@ ); // Save new file uploads. - if (($user->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;
--- 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 @@ <?php -// $Id: user.module,v 1.892.2.6 2008/08/12 05:11:22 dries Exp $ +// $Id: user.module,v 1.892.2.8 2008/10/08 20:12:18 goba Exp $ /** * @file @@ -1334,9 +1334,18 @@ function user_authenticate($form_values = array()) { global $user; + // Load the account to check if the e-mail is denied by an access rule. + // Doing this check here saves us a user_load() in user_login_name_validate() + // and introduces less code change for a security fix. + $account = user_load(array('name' => $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)),
--- 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 @@ <?php -// $Id: user.pages.inc,v 1.11 2008/01/08 10:35:43 goba Exp $ +// $Id: user.pages.inc,v 1.11.2.1 2008/10/08 20:12:18 goba Exp $ /** * @file @@ -43,6 +43,13 @@ function user_pass_validate($form, &$form_state) { $name = trim($form_state['values']['name']); + + // Blocked accounts cannot request a new password, + // check provided username and email against access rules. + if (drupal_is_denied('user', $name) || drupal_is_denied('mail', $name)) { + form_set_error('name', t('%name is not allowed to request a new password.', array('%name' => $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.'));
--- 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 @@ <?php -// $Id: page.tpl.php,v 1.25 2008/01/24 09:42:53 goba Exp $ +// $Id: page.tpl.php,v 1.25.2.1 2008/09/29 13:32:15 goba Exp $ ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="<?php print $language->language ?>" xml:lang="<?php print $language->language ?>" dir="<?php print $language->dir ?>"> <head> @@ -10,7 +10,7 @@ <?php print $scripts ?> </head> -<body bgcolor="#ffffff"> +<body> <div class="hide"><a href="#content" title="<?php print t('Skip navigation') ?>." accesskey="2"><?php print t('Skip navigation') ?></a>.</div> @@ -112,7 +112,7 @@ <?php if ($footer_message || $footer) : ?> <div id="footer-message"> - <p><?php print $footer_message . $footer;?></p> + <?php print $footer_message . $footer;?> </div> <?php endif; ?> <?php print $closure;?>