# HG changeset patch
# User Franck Deroche
# Date 1230039028 -3600
# Node ID fff6d4c8c04391d02d406b82c21388db73a93442
# Parent 2cfdc3c921424bc439ff1165bd7d89e6467546e1
Drupal 6.3
diff -r 2cfdc3c92142 -r fff6d4c8c043 .htaccess
--- a/.htaccess Tue Dec 23 14:30:08 2008 +0100
+++ b/.htaccess Tue Dec 23 14:30:28 2008 +0100
@@ -13,9 +13,14 @@
# Follow symbolic links in this directory.
Options +FollowSymLinks
-# Customized error messages.
+# Make Drupal handle any 404 errors.
ErrorDocument 404 /index.php
+# Force simple error message for requests for non-existent favicon.ico.
+
+ ErrorDocument 404 "The requested file favicon.ico was not found.
+
+
# Set the default handler.
DirectoryIndex index.php
@@ -94,10 +99,11 @@
# uncomment the following line:
# RewriteBase /
- # Rewrite URLs of the form 'index.php?q=x'.
+ # Rewrite URLs of the form 'x' to the form 'index.php?q=x'.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
-# $Id: .htaccess,v 1.90 2007/10/05 14:43:23 dries Exp $
+# $Id: .htaccess,v 1.90.2.1 2008/07/08 09:33:14 goba Exp $
diff -r 2cfdc3c92142 -r fff6d4c8c043 CHANGELOG.txt
--- a/CHANGELOG.txt Tue Dec 23 14:30:08 2008 +0100
+++ b/CHANGELOG.txt Tue Dec 23 14:30:28 2008 +0100
@@ -1,4 +1,14 @@
-// $Id: CHANGELOG.txt,v 1.253.2.7 2008/04/09 21:11:43 goba Exp $
+// $Id: CHANGELOG.txt,v 1.253.2.9 2008/07/09 21:48:27 goba Exp $
+
+Drupal 6.3, 2008-07-09
+----------------------
+- fixed security issues, (Cross site scripting, cross site request forgery, session fixation and SQL injection), see SA-2008-044
+- slightly modified installation process to prevent file ownership issues on shared hosts
+- improved PostgreSQL compatibility (rewritten queries; custom blocks)
+- upgraded to jQuery 1.2.6
+- performance improvements to search, menu handling and form API caches
+- fixed Views compatibility issues (Views for Drupal 6 requires Drupal 6.3+)
+- fixed a variety of small bugs.
Drupal 6.2, 2008-04-09
----------------------
@@ -110,6 +120,11 @@
- 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.8, 2008-07-09
+----------------------
+- fixed a variety of small bugs.
+- fixed security issues, (Cross site scripting, cross site request forgery, and session fixation), see SA-2008-044
+
Drupal 5.7, 2008-01-28
----------------------
- fixed the input format configuration page.
diff -r 2cfdc3c92142 -r fff6d4c8c043 INSTALL.txt
--- a/INSTALL.txt Tue Dec 23 14:30:08 2008 +0100
+++ b/INSTALL.txt Tue Dec 23 14:30:28 2008 +0100
@@ -1,4 +1,4 @@
-// $Id: INSTALL.txt,v 1.61.2.2 2008/02/07 20:46:56 goba Exp $
+// $Id: INSTALL.txt,v 1.61.2.4 2008/07/09 19:15:59 goba Exp $
CONTENTS OF THIS FILE
---------------------
@@ -28,8 +28,8 @@
a variety of operating systems and web servers, see "Local server setup"
(http://drupal.org/node/157602) in the Drupal handbook.
-OPTIONAL REQUIREMENTS
----------------------
+OPTIONAL TASKS
+--------------
- To use XML-based services such as the Blogger API and RSS syndication,
you will need PHP's XML extension. This extension is enabled by default.
@@ -74,13 +74,27 @@
http://drupal.org/project/translations and download the package. Extract
the contents to the same directory where you extracted Drupal into.
-2. GRANT WRITE PERMISSIONS ON CONFIGURATION FILE
+2. CREATE THE CONFIGURATION FILE AND GRANT WRITE PERMISSIONS
Drupal comes with a default.settings.php file in the sites/default
- directory. The installer will create a copy of this file filled with
- the details you provide through the install process, in the same
- directory. Give the web server write privileges to the sites/default
- directory with the command (from the installation directory):
+ directory. The installer uses this file as a template to create your
+ settings file using the details you provide through the install process.
+ To avoid problems when upgrading, Drupal is not packaged with an actual
+ settings file. You must create a file named settings.php. You may do so
+ by making a copy of default.settings.php (or create an empty file with
+ this name in the same directory). For example, (from the installation
+ directory) make a copy of the default.settings.php file with the command:
+
+ cp sites/default/default.settings.php sites/default/settings.php
+
+ Next, give the web server write privileges to the sites/default/settings.php
+ file with the command (from the installation directory):
+
+ chmod o+w sites/default/settings.php
+
+ So that the files directory can be created automatically, give the web server
+ write privileges to the sites/default directory with the command (from the
+ installation directory):
chmod o+w sites/default
@@ -117,11 +131,17 @@
mkdir sites/default/files
chmod o+w sites/default/files
- The install script will attempt to write-protect the sites/default
- directory after creating the settings.php file. If you make manual
- changes to that file later, be sure to protect it again after making
- your modifications. Failure to remove write permissions to that file
- is a security risk. Although the default location for the settings.php
+ The install script will attempt to write-protect the settings.php file and
+ the sites/default directory after saving your configuration. However, you
+ may need to manually write-protect them using the commands (from the
+ installation directory):
+
+ chmod a-w sites/default/settings.php
+ chmod a-w sites/default
+
+ If you make manual changes to the file later, be sure to protect it again
+ after making your modifications. Failure to remove write permissions to that
+ file is a security risk. Although the default location for the settings.php
file is at sites/default/settings.php, it may be in another location
if you use the multi-site setup, as explained below.
@@ -182,7 +202,7 @@
unexpected problems on an existing site. If you modify the file system path
on an existing site, remember to copy all files from the original location
to the new location.
-
+
Some administrators suggest making the documentation files, especially
CHANGELOG.txt, non-readable so that the exact version of Drupal you are
running is slightly more difficult to determine. If you wish to implement
diff -r 2cfdc3c92142 -r fff6d4c8c043 MAINTAINERS.txt
--- a/MAINTAINERS.txt Tue Dec 23 14:30:08 2008 +0100
+++ b/MAINTAINERS.txt Tue Dec 23 14:30:28 2008 +0100
@@ -1,4 +1,4 @@
-// $Id: MAINTAINERS.txt,v 1.19 2008/02/04 10:26:49 goba Exp $
+// $Id: MAINTAINERS.txt,v 1.19.2.1 2008/05/15 22:13:42 dries Exp $
List of maintainers
--------------------------------------------------------------------------------
@@ -14,7 +14,6 @@
do much other than throw the odd patch in.
"orphan" : no current maintainer, but maybe you could take
the role as you write new code?
-- W: website with status or information
--------------------------------------------------------------------------------
diff -r 2cfdc3c92142 -r fff6d4c8c043 includes/actions.inc
--- a/includes/actions.inc Tue Dec 23 14:30:08 2008 +0100
+++ b/includes/actions.inc Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
variable_get('actions_max_stack', 35)) {
- watchdog('actions', 'Stack overflow: too many calls to actions_do(). Aborting to prevent infinite recursion.', WATCHDOG_ERROR);
+ watchdog('actions', 'Stack overflow: too many calls to actions_do(). Aborting to prevent infinite recursion.', array(), WATCHDOG_ERROR);
return;
}
$actions = array();
diff -r 2cfdc3c92142 -r fff6d4c8c043 includes/bootstrap.inc
--- a/includes/bootstrap.inc Tue Dec 23 14:30:08 2008 +0100
+++ b/includes/bootstrap.inc Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
destination in either the $_REQUEST-array (i.e. by using
+ * destination in either the $_REQUEST-array (i.e. by using
* the query string of an URI) or the $_REQUEST['edit']-array (i.e. by
* using a hidden form field). This is used to direct the user back to
* the proper page after completing a form. For example, after editing
@@ -571,8 +571,8 @@
* - 1 = Log errors to database and to screen.
*/
function drupal_error_handler($errno, $message, $filename, $line, $context) {
- // If the @ error suppression operator was used, error_reporting is
- // temporarily set to 0.
+ // If the @ error suppression operator was used, error_reporting will have
+ // been temporarily set to 0.
if (error_reporting() == 0) {
return;
}
@@ -1225,27 +1225,27 @@
* '' may also be given and will generate the site's base URL.
* @param $options
* An associative array of additional options, with the following keys:
- * 'query'
+ * - 'query'
* A query string to append to the link, or an array of query key/value
* properties.
- * 'fragment'
+ * - 'fragment'
* A fragment identifier (or named anchor) to append to the link.
* Do not include the '#' character.
- * 'absolute' (default FALSE)
+ * - 'absolute' (default FALSE)
* Whether to force the output to be an absolute link (beginning with
* http:). Useful for links that will be displayed outside the site, such
* as in an RSS feed.
- * 'alias' (default FALSE)
+ * - 'alias' (default FALSE)
* Whether the given path is an alias already.
- * 'external'
+ * - 'external'
* Whether the given path is an external URL.
- * 'language'
+ * - 'language'
* An optional language object. Used to build the URL to link to and
* look up the proper alias for the link.
- * 'base_url'
+ * - 'base_url'
* Only used internally, to modify the base URL when a language dependent
* URL requires so.
- * 'prefix'
+ * - 'prefix'
* Only used internally, to modify the path when a language dependent URL
* requires so.
* @return
@@ -1406,23 +1406,23 @@
* used as is.
* @param $options
* An associative array of additional options, with the following keys:
- * 'attributes'
+ * - 'attributes'
* An associative array of HTML attributes to apply to the anchor tag.
- * 'query'
+ * - 'query'
* A query string to append to the link, or an array of query key/value
* properties.
- * 'fragment'
+ * - 'fragment'
* A fragment identifier (named anchor) to append to the link.
* Do not include the '#' character.
- * 'absolute' (default FALSE)
+ * - 'absolute' (default FALSE)
* Whether to force the output to be an absolute link (beginning with
* http:). Useful for links that will be displayed outside the site, such
* as in an RSS feed.
- * 'html' (default FALSE)
+ * - 'html' (default FALSE)
* Whether the title is HTML, or just plain-text. For example for making
* an image a link, this must be set to TRUE, or else you will see the
* escaped HTML.
- * 'alias' (default FALSE)
+ * - 'alias' (default FALSE)
* Whether the given path is an alias already.
* @return
* an HTML string containing a link to the given path.
@@ -1712,21 +1712,26 @@
// If the theme supplies its own style using the name of the module style, skip its inclusion.
// This includes any RTL styles associated with its main LTR counterpart.
if ($type == 'module' && in_array(str_replace('-rtl.css', '.css', basename($file)), $theme_styles)) {
+ // Unset the file to prevent its inclusion when CSS aggregation is enabled.
+ unset($types[$type][$file]);
continue;
}
- if (!$preprocess || !($is_writable && $preprocess_css)) {
- // If a CSS file is not to be preprocessed and it's a module CSS file, it needs to *always* appear at the *top*,
- // regardless of whether preprocessing is on or off.
- if (!$preprocess && $type == 'module') {
- $no_module_preprocess .= ''."\n";
- }
- // If a CSS file is not to be preprocessed and it's a theme CSS file, it needs to *always* appear at the *bottom*,
- // regardless of whether preprocessing is on or off.
- else if (!$preprocess && $type == 'theme') {
- $no_theme_preprocess .= ''."\n";
- }
- else {
- $output .= ''."\n";
+ // Only include the stylesheet if it exists.
+ if (file_exists($file)) {
+ if (!$preprocess || !($is_writable && $preprocess_css)) {
+ // If a CSS file is not to be preprocessed and it's a module CSS file, it needs to *always* appear at the *top*,
+ // regardless of whether preprocessing is on or off.
+ if (!$preprocess && $type == 'module') {
+ $no_module_preprocess .= ''."\n";
+ }
+ // If a CSS file is not to be preprocessed and it's a theme CSS file, it needs to *always* appear at the *bottom*,
+ // regardless of whether preprocessing is on or off.
+ else if (!$preprocess && $type == 'theme') {
+ $no_theme_preprocess .= ''."\n";
+ }
+ else {
+ $output .= ''."\n";
+ }
}
}
}
@@ -2008,10 +2013,10 @@
* are added to the page. Then, all settings are output, followed by 'inline'
* JavaScript code. If running update.php, all preprocessing is disabled.
*
- * @parameter $scope
+ * @param $scope
* (optional) The scope for which the JavaScript rules should be returned.
* Defaults to 'header'.
- * @parameter $javascript
+ * @param $javascript
* (optional) An array with all JavaScript code. Defaults to the default
* JavaScript array for the given scope.
* @return
@@ -2712,7 +2717,7 @@
$elements += array('#title' => NULL, '#description' => NULL);
if (!isset($elements['#children'])) {
$children = element_children($elements);
- /* Render all the children that use a theme function */
+ // Render all the children that use a theme function.
if (isset($elements['#theme']) && empty($elements['#theme_used'])) {
$elements['#theme_used'] = TRUE;
@@ -2736,7 +2741,7 @@
$elements[$key] = isset($previous[$key]) ? $previous[$key] : NULL;
}
}
- /* render each of the children using drupal_render and concatenate them */
+ // Render each of the children using drupal_render and concatenate them.
if (!isset($content) || $content === '') {
foreach ($children as $key) {
$content .= drupal_render($elements[$key]);
@@ -3074,8 +3079,8 @@
* The module for which the tables will be created.
* @return
* An array of arrays with the following key/value pairs:
- * success: a boolean indicating whether the query succeeded
- * query: the SQL query(s) executed, passed through check_plain()
+ * - success: a boolean indicating whether the query succeeded.
+ * - query: the SQL query(s) executed, passed through check_plain().
*/
function drupal_install_schema($module) {
$schema = drupal_get_schema_unprocessed($module);
@@ -3099,8 +3104,8 @@
* The module for which the tables will be removed.
* @return
* An array of arrays with the following key/value pairs:
- * success: a boolean indicating whether the query succeeded
- * query: the SQL query(s) executed, passed through check_plain()
+ * - success: a boolean indicating whether the query succeeded.
+ * - query: the SQL query(s) executed, passed through check_plain().
*/
function drupal_uninstall_schema($module) {
$schema = drupal_get_schema_unprocessed($module);
@@ -3225,6 +3230,11 @@
$update = array($update);
}
+ $schema = drupal_get_schema($table);
+ if (empty($schema)) {
+ return FALSE;
+ }
+
// Convert to an object if needed.
if (is_array($object)) {
$object = (object) $object;
@@ -3234,11 +3244,6 @@
$array = FALSE;
}
- $schema = drupal_get_schema($table);
- if (empty($schema)) {
- return FALSE;
- }
-
$fields = $defs = $values = $serials = $placeholders = array();
// Go through our schema, build SQL, and when inserting, fill in defaults for
@@ -3307,16 +3312,17 @@
$object->$field = db_last_insert_id($table, $field);
}
}
-
- // If we began with an array, convert back so we don't surprise the caller.
- if ($array) {
- $object = (array) $object;
- }
-
- return $return;
}
-
- return FALSE;
+ else {
+ $return = FALSE;
+ }
+
+ // If we began with an array, convert back so we don't surprise the caller.
+ if ($array) {
+ $object = (array) $object;
+ }
+
+ return $return;
}
/**
@@ -3507,7 +3513,7 @@
* Flush all cached data on the site.
*
* Empties cache tables, rebuilds the menu cache and theme registries, and
- * exposes a hook for other modules to clear their own cache data as well.
+ * invokes a hook so that other modules' cache data can be cleared as well.
*/
function drupal_flush_all_caches() {
// Change query-strings on css/js files to enforce reload for all users.
@@ -3515,6 +3521,7 @@
drupal_clear_css_cache();
drupal_clear_js_cache();
+ system_theme_data();
drupal_rebuild_theme_registry();
menu_rebuild();
node_types_rebuild();
diff -r 2cfdc3c92142 -r fff6d4c8c043 includes/database.inc
--- a/includes/database.inc Tue Dec 23 14:30:08 2008 +0100
+++ b/includes/database.inc Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
'. ($element['#title'] ? '' : '') . (isset($element['#description']) && $element['#description'] ? '
'. $element['#description'] .'
' : '') . (!empty($element['#children']) ? $element['#children'] : '') . $element['#value'] ."\n";
+ return '\n";
}
/**
diff -r 2cfdc3c92142 -r fff6d4c8c043 includes/locale.inc
--- a/includes/locale.inc Tue Dec 23 14:30:08 2008 +0100
+++ b/includes/locale.inc Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
'value', '#value' => $source->lid);
+ return confirm_form($form, t('Are you sure you want to delete the string "%source"?', array('%source' => $source->source)), 'admin/build/translate/search', t('Deleting the string will remove all translations of this string in all languages. This action cannot be undone.'), t('Delete'), t('Cancel'));
+}
+
+/**
+ * Process string deletion submissions.
+ */
+function locale_translate_delete_form_submit($form, &$form_state) {
+ db_query('DELETE FROM {locales_source} WHERE lid = %d', $form_state['values']['lid']);
+ db_query('DELETE FROM {locales_target} WHERE lid = %d', $form_state['values']['lid']);
// Force JavaScript translation file recreation for all languages.
_locale_invalidate_js();
cache_clear_all('locale:', 'cache', TRUE);
drupal_set_message(t('The string has been removed.'));
- drupal_goto('admin/build/translate/search');
+ $form_state['redirect'] = 'admin/build/translate/search';
}
/**
* @} End of "locale-translate-delete"
diff -r 2cfdc3c92142 -r fff6d4c8c043 includes/mail.inc
--- a/includes/mail.inc Tue Dec 23 14:30:08 2008 +0100
+++ b/includes/mail.inc Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
!i', '/', $string);
- $string = preg_replace('!?(strong|b)>!i', '*', $string);
+ $string = preg_replace('!?(em|i)((?> +)[^>]*)?>!i', '/', $string);
+ $string = preg_replace('!?(strong|b)((?> +)[^>]*)?>!i', '*', $string);
// Replace inline tags with the text of link and a footnote.
// 'See the Drupal site' becomes
diff -r 2cfdc3c92142 -r fff6d4c8c043 includes/menu.inc
--- a/includes/menu.inc Tue Dec 23 14:30:08 2008 +0100
+++ b/includes/menu.inc Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
data;
}
else {
- db_query('DELETE FROM {menu_router}');
// We need to manually call each module so that we can know which module
// a given item came from.
$callbacks = array();
@@ -1674,7 +1686,6 @@
// Alter the menu as defined in modules, keys are like user/%user.
drupal_alter('menu', $callbacks);
$menu = _menu_router_build($callbacks);
- cache_set('router:', $menu, 'cache_menu');
}
}
return $menu;
@@ -2254,6 +2265,13 @@
}
array_multisort($sort, SORT_NUMERIC, $menu);
+ if (!$menu) {
+ // We must have a serious error - there is no data to save.
+ watchdog('php', 'Menu router rebuild failed - some paths may not work correctly.', array(), WATCHDOG_ERROR);
+ return array();
+ }
+ // Delete the existing router since we have some data to replace it.
+ db_query('DELETE FROM {menu_router}');
// Apply inheritance rules.
foreach ($menu as $path => $v) {
$item = &$menu[$path];
@@ -2356,6 +2374,7 @@
$masks = array_keys($masks);
rsort($masks);
variable_set('menu_masks', $masks);
+ cache_set('router:', $menu, 'cache_menu');
return $menu;
}
diff -r 2cfdc3c92142 -r fff6d4c8c043 includes/theme.inc
--- a/includes/theme.inc Tue Dec 23 14:30:08 2008 +0100
+++ b/includes/theme.inc Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
info['stylesheets'] as $media => $stylesheets) {
foreach ($stylesheets as $stylesheet => $path) {
- if (file_exists($path)) {
- $theme->stylesheets[$media][$stylesheet] = $path;
- }
+ $theme->stylesheets[$media][$stylesheet] = $path;
}
}
foreach ($theme->info['scripts'] as $script => $path) {
@@ -725,6 +731,7 @@
$templates[$new_hook] = array(
'function' => $match,
'arguments' => $info['arguments'],
+ 'original hook' => $hook,
);
}
}
@@ -817,6 +824,7 @@
'template' => $file,
'path' => dirname($files[$match]->filename),
'arguments' => $info['arguments'],
+ 'original hook' => $hook,
);
}
}
@@ -999,7 +1007,7 @@
* defaults for the template in case they are not filled in. If the default
* implementation is a function, by convention it is named theme_HOOK().
*
- * Each module should provide a default implementation for themes that
+ * Each module should provide a default implementation for theme_hooks that
* it registers. This implementation may be either a function or a template;
* if it is a function it must be specified via hook_theme(). By convention,
* default implementations of theme hooks are named theme_HOOK. Default
@@ -1106,7 +1114,7 @@
if (isset($link['href']) && ($link['href'] == $_GET['q'] || ($link['href'] == '' && drupal_is_front_page()))) {
$class .= ' active';
}
- $output .= '
';
return $output;
case 'admin/content/aggregator':
- $output = '
'. t('Thousands of sites (particularly news sites and blogs) publish their latest headlines and posts in feeds, using a number of standardized XML-based formats. Formats supported by the aggregator include RSS, RDF, and Atom.', array('@rss' => 'http://cyber.law.harvard.edu/rss/', '@rdf' => 'hsttp://www.w3.org/RDF/', '@atom' => 'http://www.atomenabled.org')) .'
';
+ $output = '
'. t('Thousands of sites (particularly news sites and blogs) publish their latest headlines and posts in feeds, using a number of standardized XML-based formats. Formats supported by the aggregator include RSS, RDF, and Atom.', array('@rss' => 'http://cyber.law.harvard.edu/rss/', '@rdf' => 'http://www.w3.org/RDF/', '@atom' => 'http://www.atomenabled.org')) .'
';
$output .= '
'. t('Current feeds are listed below, and new feeds may be added. For each feed or feed category, the latest items block may be enabled at the blocks administration page.', array('@addfeed' => url('admin/content/aggregator/add/feed'), '@block' => url('admin/build/block'))) .'
';
return $output;
case 'admin/content/aggregator/add/feed':
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/block/block.admin.inc
--- a/modules/block/block.admin.inc Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/block/block.admin.inc Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
'hidden', '#value' => $box['info'] ? $box['info'] : $box['title']);
+ $form['info'] = array('#type' => 'hidden', '#value' => $box['info']);
$form['bid'] = array('#type' => 'hidden', '#value' => $bid);
return confirm_form($form, t('Are you sure you want to delete the block %name?', array('%name' => $box['info'])), 'admin/build/block', '', t('Delete'), t('Cancel'));
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/block/block.module
--- a/modules/block/block.module Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/block/block.module Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
uid;
+ return user_access('create blog entries', $account) && $account->uid ? TRUE : NULL;
case 'update':
- return user_access('edit any blog entry', $account) || (user_access('edit own blog entries', $account) && ($node->uid == $account->uid));
+ return user_access('edit any blog entry', $account) || (user_access('edit own blog entries', $account) && ($node->uid == $account->uid)) ? TRUE : NULL;
case 'delete':
- return user_access('delete any blog entry', $account) || (user_access('delete own blog entries', $account) && ($node->uid == $account->uid));
+ return user_access('delete any blog entry', $account) || (user_access('delete own blog entries', $account) && ($node->uid == $account->uid)) ? TRUE : NULL;
}
}
@@ -49,7 +49,7 @@
$user->content['summary']['blog'] = array(
'#type' => 'user_profile_item',
'#title' => t('Blog'),
- '#value' => l(t('View recent blog entries'), "blog/$user->uid", array('title' => t("Read @username's latest blog entries.", array('@username' => $user->name)))),
+ '#value' => l(t('View recent blog entries'), "blog/$user->uid", array('attributes' => array('title' => t("Read @username's latest blog entries.", array('@username' => $user->name))))),
'#attributes' => array('class' => 'blog'),
);
}
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/book/book.admin.inc
--- a/modules/book/book.admin.inc Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/book/book.admin.inc Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
title));
$form = array();
$form['#node'] = $node;
- $form['table'] = _book_admin_table($node);
+ _book_admin_table($node, $form);
$form['save'] = array(
'#type' => 'submit',
'#value' => t('Save book pages'),
@@ -81,6 +81,18 @@
}
/**
+ * Check that the book has not been changed while using the form.
+ *
+ * @see book_admin_edit()
+ */
+function book_admin_edit_validate($form, &$form_state) {
+ if ($form_state['values']['tree_hash'] != $form_state['values']['tree_current_hash']) {
+ form_set_error('', t('This book has been modified by another user, the changes could not be saved.'));
+ $form_state['rebuild'] = TRUE;
+ }
+}
+
+/**
* Handle submission of the book administrative page form.
*
* This function takes care to save parent menu items before their children.
@@ -128,8 +140,8 @@
*
* @see book_admin_edit()
*/
-function _book_admin_table($node) {
- $form = array(
+function _book_admin_table($node, &$form) {
+ $form['table'] = array(
'#theme' => 'book_admin_table',
'#tree' => TRUE,
);
@@ -137,9 +149,19 @@
$tree = book_menu_subtree_data($node->book);
$tree = array_shift($tree); // Do not include the book item itself.
if ($tree['below']) {
- _book_admin_table_tree($tree['below'], $form);
+ $hash = sha1(serialize($tree['below']));
+ // Store the hash value as a hidden form element so that we can detect
+ // if another user changed the book hierarchy.
+ $form['tree_hash'] = array(
+ '#type' => 'hidden',
+ '#default_value' => $hash,
+ );
+ $form['tree_current_hash'] = array(
+ '#type' => 'value',
+ '#value' => $hash,
+ );
+ _book_admin_table_tree($tree['below'], $form['table']);
}
- return $form;
}
/**
@@ -226,25 +248,3 @@
return theme('table', $header, $rows, array('id' => 'book-outline'));
}
-/**
- * Recursive helper to sort each layer of a book tree by weight.
- */
-function _book_admin_sort_tree(&$tree) {
- uasort($tree, '_book_admin_compare');
- foreach ($tree as $key => $subtree) {
- if (!empty($tree[$key]['below'])) {
- _book_admin_sort_tree($tree[$key]['below']);
- }
- }
-}
-
-/**
- * Used by uasort() in _book_admin_sort_tree() to compare items in a book tree.
- */
-function _book_admin_compare($a, $b) {
- $weight = $a['link']['weight'] - $b['link']['weight'];
- if ($weight) {
- return $weight;
- }
- return strncmp($a['link']['title'], $b['link']['title']);
-}
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/book/book.module
--- a/modules/book/book.module Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/book/book.module Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
cid] = '';
$comment->name = $comment->uid ? $comment->registered_name : $comment->name;
- $form['subject'][$comment->cid] = array('#value' => l($comment->subject, 'node/'. $comment->nid, array('title' => truncate_utf8($comment->comment, 128), 'fragment' => 'comment-'. $comment->cid)));
+ $form['subject'][$comment->cid] = array('#value' => l($comment->subject, 'node/'. $comment->nid, array('attributes' => array('title' => truncate_utf8($comment->comment, 128)), 'fragment' => 'comment-'. $comment->cid)));
$form['username'][$comment->cid] = array('#value' => theme('username', $comment));
$form['node_title'][$comment->cid] = array('#value' => l($comment->node_title, 'node/'. $comment->nid));
$form['timestamp'][$comment->cid] = array('#value' => format_date($comment->timestamp, 'small'));
@@ -277,7 +277,7 @@
*/
function _comment_delete_thread($comment) {
if (!is_object($comment) || !is_numeric($comment->cid)) {
- watchdog('content', 'Cannot delete non-existent comment.', WATCHDOG_WARNING);
+ watchdog('content', 'Cannot delete non-existent comment.', array(), WATCHDOG_WARNING);
return;
}
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/comment/comment.module
--- a/modules/comment/comment.module Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/comment/comment.module Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
uid == $node->uid));
+ return user_access('edit any forum topic', $account) || (user_access('edit own forum topics', $account) && ($account->uid == $node->uid)) ? TRUE : NULL;
case 'delete':
- return user_access('delete any forum topic', $account) || (user_access('delete own forum topics', $account) && ($account->uid == $node->uid));
+ return user_access('delete any forum topic', $account) || (user_access('delete own forum topics', $account) && ($account->uid == $node->uid)) ? TRUE : NULL;
}
}
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/locale/locale.module
--- a/modules/locale/locale.module Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/locale/locale.module Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
'Delete string',
'page callback' => 'locale_inc_callback',
- 'page arguments' => array('locale_translate_delete', 4), // directly deletes, no confirmation
+ 'page arguments' => array('locale_translate_delete_page', 4),
'access arguments' => array('translate interface'),
'type' => MENU_CALLBACK,
);
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/menu/menu.module
--- a/modules/menu/menu.module Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/menu/menu.module Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
'. t('Enter the name for your new menu. Remember to enable the newly created block in the blocks administration page.', array('@blocks' => url('admin/build/block'))) .'';
case 'admin/build/menu-customize/%':
- return '
'. t('To rearrange menu items, grab a drag-and-drop handle under the Menu item column and drag the items (or group of items) to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save configuration button at the bottom of the page.') .'
';
+ return '
'. t('To rearrange menu items, grab a drag-and-drop handle under the Menu item column and drag the items (or group of items) to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save configuration button at the bottom of the page.') .'
';
case 'admin/build/menu/item/add':
return '
'. t('Enter the title and path for your new menu item.') .'
';
}
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/node/node.install
--- a/modules/node/node.install Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/node/node.install Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
TRUE,
'default' => ''),
'title' => array(
- 'description' => t('The title of this node, always treated a non-markup plain text.'),
+ 'description' => t('The title of this node, always treated as non-markup plain text.'),
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
@@ -63,7 +63,7 @@
'not null' => TRUE,
'default' => 0),
'promote' => array(
- 'description' => t('Boolean indicating whether the node should displayed on the front page.'),
+ 'description' => t('Boolean indicating whether the node should be displayed on the front page.'),
'type' => 'int',
'not null' => TRUE,
'default' => 0),
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/node/node.module
--- a/modules/node/node.module Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/node/node.module Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
title, 'node/'. $node->nid, !empty($node->comment_count) ? array('title' => format_plural($node->comment_count, '1 comment', '@count comments')) : array());
+ $items[] = l($node->title, 'node/'. $node->nid, !empty($node->comment_count) ? array('attributes' => array('title' => format_plural($node->comment_count, '1 comment', '@count comments'))) : array());
$num_rows = TRUE;
}
@@ -907,14 +907,16 @@
// Generate the node table query and the node_revisions table query.
if ($node->is_new) {
+ _node_save_revision($node, $user->uid);
drupal_write_record('node', $node);
- _node_save_revision($node, $user->uid);
+ db_query('UPDATE {node_revisions} SET nid = %d WHERE vid = %d', $node->nid, $node->vid);
$op = 'insert';
}
else {
drupal_write_record('node', $node, 'nid');
if (!empty($node->revision)) {
_node_save_revision($node, $user->uid);
+ db_query('UPDATE {node} SET vid = %d WHERE nid = %d', $node->vid, $node->nid);
}
else {
_node_save_revision($node, $user->uid, 'vid');
@@ -922,9 +924,6 @@
}
$op = 'update';
}
- if ($update_node) {
- db_query('UPDATE {node} SET vid = %d WHERE nid = %d', $node->vid, $node->nid);
- }
// Call the node specific callback (if any).
node_invoke($node, $op);
@@ -1257,12 +1256,22 @@
$join2 .= ' LEFT JOIN {node_counter} nc ON nc.nid = i.sid';
$total += $weight;
}
- $select2 = (count($ranking) ? implode(' + ', $ranking) : 'i.relevance') .' AS score';
+
+ // When all search factors are disabled (ie they have a weight of zero),
+ // the default score is based only on keyword relevance and there is no need to
+ // adjust the score of each item.
+ if ($total == 0) {
+ $select2 = 'i.relevance AS score';
+ $total = 1;
+ }
+ else {
+ $select2 = implode(' + ', $ranking) . ' AS score';
+ }
+
+ // Do search.
+ $find = do_search($keys, 'node', 'INNER JOIN {node} n ON n.nid = i.sid '. $join1, $conditions1 . (empty($where1) ? '' : ' AND '. $where1), $arguments1, $select2, $join2, $arguments2);
- // Do search
- $find = do_search($keys, 'node', 'INNER JOIN {node} n ON n.nid = i.sid '. $join1 .' INNER JOIN {users} u ON n.uid = u.uid', $conditions1 . (empty($where1) ? '' : ' AND '. $where1), $arguments1, $select2, $join2, $arguments2);
-
- // Load results
+ // Load results.
$results = array();
foreach ($find as $item) {
// Build the node body.
@@ -1271,9 +1280,9 @@
$node = node_build_content($node, FALSE, FALSE);
$node->body = drupal_render($node->content);
- // Fetch comments for snippet
+ // Fetch comments for snippet.
$node->body .= module_invoke('comment', 'nodeapi', $node, 'update index');
- // Fetch terms for snippet
+ // Fetch terms for snippet.
$node->body .= module_invoke('taxonomy', 'nodeapi', $node, 'update index');
$extra = node_invoke_nodeapi($node, 'search result');
@@ -1674,7 +1683,7 @@
// Allow modules to add additional item fields and/or modify $item
$extra = node_invoke_nodeapi($item, 'rss item');
- $extra = array_merge($extra, array(array('key' => 'pubDate', 'value' => format_date($item->created, 'custom', 'r')), array('key' => 'dc:creator', 'value' => $item->name), array('key' => 'guid', 'value' => $item->nid .' at '. $base_url, 'attributes' => array('isPermaLink' => 'false'))));
+ $extra = array_merge($extra, array(array('key' => 'pubDate', 'value' => gmdate('r', $item->created)), array('key' => 'dc:creator', 'value' => $item->name), array('key' => 'guid', 'value' => $item->nid .' at '. $base_url, 'attributes' => array('isPermaLink' => 'false'))));
foreach ($extra as $element) {
if (isset($element['namespace'])) {
$namespaces = array_merge($namespaces, $element['namespace']);
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/openid/openid.module
--- a/modules/openid/openid.module Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/openid/openid.module Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
'Delete OpenID',
- 'page callback' => 'openid_user_delete',
- 'page arguments' => array(1),
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('openid_user_delete_form', 1),
'access callback' => 'user_edit_access',
'access arguments' => array(1),
'type' => MENU_CALLBACK,
@@ -472,7 +472,7 @@
$request['openid.realm'] = url('', array('absolute' => TRUE));
}
else {
- $request['openid.trust_root'] = $realm;
+ $request['openid.trust_root'] = url('', array('absolute' => TRUE));
}
// Simple Registration
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/openid/openid.pages.inc
--- a/modules/openid/openid.pages.inc Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/openid/openid.pages.inc Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
uid);
while ($identity = db_fetch_object($result)) {
- $rows[] = array($identity->authname, l(t('Delete'), 'user/'. $account->uid .'/openid/delete/'. $identity->aid));
+ $rows[] = array(check_plain($identity->authname), l(t('Delete'), 'user/'. $account->uid .'/openid/delete/'. $identity->aid));
}
$output = theme('table', $header, $rows);
@@ -80,12 +80,33 @@
}
/**
- * Menu callback; Delete the specified OpenID identity from the system.
+ * Present a confirmation form to delete the specified OpenID identity from the system.
+ *
+ * @ingroup forms
+ * @see openid_user_delete_form_submit()
*/
-function openid_user_delete($account, $aid = 0) {
- db_query("DELETE FROM {authmap} WHERE uid=%d AND aid=%d AND module='openid'", $account->uid, $aid);
+function openid_user_delete_form($form_state, $account, $aid = 0) {
+ $authname = db_result(db_query('SELECT authname FROM {authmap} WHERE uid = %d AND aid = %d', $account->uid, $aid));
+
+ $form = array();
+
+ $form['uid'] = array(
+ '#type' => 'value',
+ '#value' => $account->uid,
+ );
+
+ $form['aid'] = array(
+ '#type' => 'value',
+ '#value' => $aid,
+ );
+
+ return confirm_form($form, t('Are you sure you want to delete the OpenID %authname for %user?', array('%authname' => $authname, '%user' => $account->name)), 'user/'. $account->uid .'/openid');
+}
+
+function openid_user_delete_form_submit($form, &$form_state) {
+ db_query("DELETE FROM {authmap} WHERE uid = %d AND aid = %d AND module = 'openid'", $form_state['values']['uid'], $form_state['values']['aid']);
if (db_affected_rows()) {
drupal_set_message(t('OpenID deleted.'));
}
- drupal_goto('user/'. $account->uid .'/openid');
+ $form_state['redirect'] = 'user/'. $form_state['values']['uid'] .'/openid';
}
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/path/path.module
--- a/modules/path/path.module Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/path/path.module Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
language) ? $node->language : '';
switch ($op) {
case 'validate':
- $node->path = trim($node->path);
- if (db_result(db_query("SELECT COUNT(dst) FROM {url_alias} WHERE dst = '%s' AND src != '%s' AND language = '%s'", $node->path, "node/$node->nid", $language))) {
- form_set_error('path', t('The path is already in use.'));
+ if (isset($node->path)) {
+ $node->path = trim($node->path);
+ if (db_result(db_query("SELECT COUNT(dst) FROM {url_alias} WHERE dst = '%s' AND src != '%s' AND language = '%s'", $node->path, "node/$node->nid", $language))) {
+ form_set_error('path', t('The path is already in use.'));
+ }
}
break;
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/poll/poll.module
--- a/modules/poll/poll.module Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/poll/poll.module Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
uid == $account->uid));
+ return user_access('edit any poll content', $account) || (user_access('edit own poll content', $account) && ($node->uid == $account->uid)) ? TRUE : NULL;
case 'delete':
- return user_access('delete any poll content', $account) || (user_access('delete own poll content', $account) && ($node->uid == $account->uid));
+ return user_access('delete any poll content', $account) || (user_access('delete own poll content', $account) && ($node->uid == $account->uid)) ? TRUE : NULL;
}
}
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/profile/profile.module
--- a/modules/profile/profile.module Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/profile/profile.module Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
'checkboxes',
'#title' => t('Profile fields to display'),
- '#default_value' => variable_get('profile_block_author_fields', NULL),
+ '#default_value' => variable_get('profile_block_author_fields', array()),
'#options' => $fields,
'#description' => t('Select which profile fields you wish to display in the block. Only fields designated as public in the profile field configuration are available.', array('@profile-admin' => url('admin/user/profile'))),
);
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/system/admin.css
--- a/modules/system/admin.css Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/system/admin.css Tue Dec 23 14:30:28 2008 +0100
@@ -1,4 +1,4 @@
-/* $Id: admin.css,v 1.18 2007/12/22 23:24:25 goba Exp $ */
+/* $Id: admin.css,v 1.18.2.1 2008/04/25 21:01:54 goba Exp $ */
/*
** Formatting for administration page
@@ -44,6 +44,9 @@
table.package .description {
width: 100%;
}
+table.package .version {
+ direction: ltr;
+}
div.admin-dependencies, div.admin-required {
font-size: 0.9em;
color: #444;
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/system/system.admin.inc
--- a/modules/system/system.admin.inc Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/system/system.admin.inc Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
';
$output .= '
';
if (system_admin_compact_mode()) {
- $output .= l(t('Show descriptions'), 'admin/compact/off', array('title' => t('Expand layout to include descriptions.')));
+ $output .= l(t('Show descriptions'), 'admin/compact/off', array('attributes' => array('title' => t('Expand layout to include descriptions.'))));
}
else {
- $output .= l(t('Hide descriptions'), 'admin/compact/on', array('title' => t('Compress layout by hiding descriptions.')));
+ $output .= l(t('Hide descriptions'), 'admin/compact/on', array('attributes' => array('title' => t('Compress layout by hiding descriptions.'))));
}
$output .= '
';
@@ -2070,7 +2070,7 @@
$row[] = ''. drupal_render($form['name'][$key]) .'';
}
- $row[] = drupal_render($form['version'][$key]);
+ $row[] = array('data' => drupal_render($form['version'][$key]), 'class' => 'version');
$row[] = array('data' => $description, 'class' => 'description');
$rows[] = $row;
}
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/system/system.install
--- a/modules/system/system.install Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/system/system.install Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
TRUE,
'default' => ''),
'to_arg_functions' => array(
- 'description' => t('A serialized array of function names (like user_current_to_arg) to be called to replace a part of the router path with another string.'),
+ '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,
@@ -1717,7 +1717,7 @@
'secondary-links' => array(
'menu_name' => 'secondary-links',
'title' => 'Secondary links',
- 'description' => 'Secondary links are often used for pages like legal notices, contact details, and other secondary navigation items that play a lesser role than primary links',
+ 'description' => 'Secondary links are often used for pages like legal notices, contact details, and other secondary navigation items that play a lesser role than primary links.',
),
);
// Multi-part update
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/system/system.module
--- a/modules/system/system.module Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/system/system.module Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
build_mode == NODE_BUILD_PREVIEW) {
+ if (isset($node->build_mode) && $node->build_mode == NODE_BUILD_PREVIEW) {
$node->taxonomy = taxonomy_preview_terms($node);
}
if (!empty($node->taxonomy)) {
@@ -908,6 +908,7 @@
else {
$result = db_query(db_rewrite_sql("SELECT t.tid, COUNT(n.nid) AS c FROM {term_node} t INNER JOIN {node} n ON t.vid = n.vid WHERE n.status = 1 AND n.type = '%s' GROUP BY t.tid"), $type);
}
+ $count[$type] = array();
while ($term = db_fetch_object($result)) {
$count[$type][$term->tid] = $term->c;
}
@@ -956,7 +957,7 @@
* An array of matching term objects.
*/
function taxonomy_get_term_by_name($name) {
- $db_result = db_query(db_rewrite_sql("SELECT t.tid, t.* FROM {term_data} t WHERE LOWER(t.name) LIKE LOWER('%s')", 't', 'tid'), trim($name));
+ $db_result = db_query(db_rewrite_sql("SELECT t.tid, t.* FROM {term_data} t WHERE LOWER(t.name) = LOWER('%s')", 't', 'tid'), trim($name));
$result = array();
while ($term = db_fetch_object($db_result)) {
$result[] = $term;
diff -r 2cfdc3c92142 -r fff6d4c8c043 modules/user/user.module
--- a/modules/user/user.module Tue Dec 23 14:30:08 2008 +0100
+++ b/modules/user/user.module Tue Dec 23 14:30:28 2008 +0100
@@ -1,5 +1,5 @@
t('Create a new user account.')));
+ $items[] = l(t('Create new account'), 'user/register', array('attributes' => array('title' => t('Create a new user account.'))));
}
- $items[] = l(t('Request new password'), 'user/password', array('title' => t('Request new password via e-mail.')));
+ $items[] = l(t('Request new password'), 'user/password', array('attributes' => array('title' => t('Request new password via e-mail.'))));
$form['links'] = array('#value' => theme('item_list', $items));
return $form;
}
@@ -1266,9 +1266,9 @@
/**
* Set up a series for validators which check for blocked/denied users,
* then authenticate against local database, then return an error if
- * authentication fails. Distributed authentication modules are welcome
- * to use hook_form_alter() to change this series in order to
- * authenticate against their user database instead of the local users
+ * authentication fails. Distributed authentication modules are welcome
+ * to use hook_form_alter() to change this series in order to
+ * authenticate against their user database instead of the local users
* table.
*
* We use three validators instead of one since external authentication
@@ -1359,8 +1359,10 @@
// This is also used to invalidate one-time login links.
$user->login = time();
db_query("UPDATE {users} SET login = %d WHERE uid = %d", $user->login, $user->uid);
+
+ // Regenerate the session ID to prevent against session fixation attacks.
+ sess_regenerate();
user_module_invoke('login', $edit, $user);
- sess_regenerate();
}
/**
@@ -1636,7 +1638,7 @@
case 'register_admin_created_body':
return t("!username,\n\nA site administrator at !site has created an account for you. You may now log in to !login_uri using the following username and password:\n\nusername: !username\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.\n\n\n-- !site team", $variables, $langcode);
case 'register_pending_approval_subject':
- case 'pending_approval_admin_subject':
+ case 'register_pending_approval_admin_subject':
return t('Account details for !username at !site (pending admin approval)', $variables, $langcode);
case 'register_pending_approval_body':
return t("!username,\n\nThank you for registering at !site. Your application for an account is currently pending approval. Once it has been approved, you will receive another e-mail containing information about how to log in, set your password, and other details.\n\n\n-- !site team", $variables, $langcode);