Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.163
diff -u -p -r1.163 menu.inc
--- includes/menu.inc	24 Apr 2007 08:26:58 -0000	1.163
+++ includes/menu.inc	30 Apr 2007 07:06:42 -0000
@@ -343,6 +343,10 @@ function menu_get_item($path = NULL, $it
  */
 function menu_execute_active_handler() {
   if ($item = menu_get_item()) {
+    //dsm($item);
+     if ($item->includes) {
+      include_once($item->includes);
+    }
     return $item->access ? call_user_func_array($item->page_callback, $item->page_arguments) : MENU_ACCESS_DENIED;
   }
   return MENU_NOT_FOUND;
@@ -777,10 +781,16 @@ function menu_rebuild() {
             $item['page callback'] = $parent['page callback'];
             if (!isset($item['page arguments']) && isset($parent['page arguments'])) {
               $item['page arguments'] = $parent['page arguments'];
+              if (empty($item['includes'])) {
+                $item['includes'] = $parent['includes'];
+              }
             }
           }
         }
       }
+      if (!isset($item['includes'])) {
+        $item['includes'] = '';
+      }
       if (!isset($item['access callback'])) {
         $item['access callback'] = isset($item['access arguments']) ? 'user_access' : 0;
       }
@@ -843,15 +853,16 @@ function menu_rebuild() {
     if (!empty($item['disabled'])) {
       $item['_visible'] = FALSE;
     }
+
     db_query("INSERT INTO {menu} (
       mid, pid, path, load_functions, to_arg_functions,
       access_callback, access_arguments, page_callback, page_arguments, fit,
       number_parts, visible, parents, depth, has_children, tab, title, parent,
       type, mleft, mright, block_callback, description, position,
-      link_path, attributes, query, fragment, absolute, html)
+      link_path, attributes, query, fragment, absolute, html, includes)
       VALUES (%d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d,
       '%s', %d, %d, %d, '%s', '%s', '%s', %d, %d, '%s', '%s', '%s',
-      '%s', '%s', '%s', '%s', %d, %d)",
+      '%s', '%s', '%s', '%s', %d, %d, '%s')",
       $item['_mid'], $item['_pid'], $path, $item['load_functions'],
       $item['to_arg_functions'], $item['access callback'],
       serialize($item['access arguments']), $item['page callback'],
@@ -862,7 +873,7 @@ function menu_rebuild() {
       $item['_mright'], $item['block callback'], $item['description'],
       $item['position'], $link_path,
       $item['attributes'], $item['query'], $item['fragment'],
-      $item['absolute'], $item['html']);
+      $item['absolute'], $item['html'], $item['includes']);
   }
 }
 
Index: modules/block/block.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.module,v
retrieving revision 1.257
diff -u -p -r1.257 block.module
--- modules/block/block.module	17 Apr 2007 07:19:38 -0000	1.257
+++ modules/block/block.module	30 Apr 2007 07:06:42 -0000
@@ -76,6 +76,7 @@ function block_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('block_admin_display'),
     'access arguments' => array('administer blocks'),
+    'includes' => drupal_get_path('module', 'block') . '/block.pages.inc',
   );
   $items['admin/build/block/list'] = array(
     'title' => t('List'),
@@ -96,6 +97,7 @@ function block_menu() {
     'title' => t('Add block'),
     'page arguments' => array('block_add_block_form'),
     'type' => MENU_LOCAL_TASK,
+    'includes' => drupal_get_path('module', 'block') . '/block.pages.inc',
   );
   $default = variable_get('theme_default', 'garland');
   foreach (list_themes() as $key => $theme) {
@@ -146,6 +148,42 @@ function block_block($op = 'list', $delt
   }
 }
 
+
+/**
+ * Implementation of hook_user().
+ *
+ * Allow users to decide which custom blocks to display when they visit
+ * the site.
+ */
+function block_user($type, $edit, &$user, $category = NULL) {
+  global $user;
+  switch ($type) {
+    case 'form':
+      if ($category == 'account') {
+        $result = db_query("SELECT DISTINCT b.* FROM {blocks} b LEFT JOIN {blocks_roles} r ON b.module = r.module AND b.delta = r.delta WHERE b.status = 1 AND b.custom != 0 AND (r.rid IN (%s) OR r.rid IS NULL) ORDER BY b.weight, b.module", implode(',', array_keys($user->roles)));
+        $form['block'] = array('#type' => 'fieldset', '#title' => t('Block configuration'), '#weight' => 3, '#collapsible' => TRUE, '#tree' => TRUE);
+        while ($block = db_fetch_object($result)) {
+          $data = module_invoke($block->module, 'block', 'list');
+          if ($data[$block->delta]['info']) {
+            $return = TRUE;
+            $form['block'][$block->module][$block->delta] = array('#type' => 'checkbox', '#title' => check_plain($data[$block->delta]['info']), '#default_value' => isset($user->block[$block->module][$block->delta]) ? $user->block[$block->module][$block->delta] : ($block->custom == 1));
+          }
+        }
+
+        if (!empty($return)) {
+          return $form;
+        }
+      }
+
+      break;
+    case 'validate':
+      if (empty($edit['block'])) {
+        $edit['block'] = array();
+      }
+      return $edit;
+  }
+}
+
 /**
  * Update the 'blocks' DB table with the blocks currently exported by modules.
  *
@@ -214,450 +252,6 @@ function _block_rehash() {
 }
 
 /**
- * Generate main block administration form.
- */
-function block_admin_display($theme = NULL) {
-  global $theme_key, $custom_theme;
-
-  // Add CSS
-  drupal_add_css(drupal_get_path('module', 'block') .'/block.css', 'module', 'all', FALSE);
-
-  // If non-default theme configuration has been selected, set the custom theme.
-  if ($theme) {
-    $custom_theme = $theme;
-  }
-  else {
-    $custom_theme = variable_get('theme_default', 'garland');
-  }
-  init_theme();
-
-  // Fetch and sort blocks
-  $blocks = _block_rehash();
-  usort($blocks, '_block_compare');
-
-  $throttle = module_exists('throttle');
-  $block_regions = array(BLOCK_REGION_NONE => '<'. t('none') .'>') + system_region_list($theme_key);
-
-  // Build form tree
-  $form['#action'] = arg(3) ? url('admin/build/block/list/'. $theme_key) : url('admin/build/block');
-  $form['#tree'] = TRUE;
-  foreach ($blocks as $i => $block) {
-    $form[$i]['module'] = array('#type' => 'value', '#value' => $block['module']);
-    $form[$i]['delta'] = array('#type' => 'value', '#value' => $block['delta']);
-    $form[$i]['info'] = array('#value' => check_plain($block['info']));
-    $form[$i]['theme'] = array('#type' => 'hidden', '#value' => $theme_key);
-    $form[$i]['weight'] = array('#type' => 'weight', '#default_value' => $block['weight']);
-    $form[$i]['region'] = array('#type' => 'select',
-      '#default_value' => $block['status'] ? (isset($block['region']) ? $block['region'] : system_default_region($theme_key)) : BLOCK_REGION_NONE,
-      '#options' => $block_regions,
-    );
-
-    if ($throttle) {
-      $form[$i]['throttle'] = array('#type' => 'checkbox', '#default_value' => isset($block['throttle']) ? $block['throttle'] : FALSE);
-    }
-    $form[$i]['configure'] = array('#value' => l(t('configure'), 'admin/build/block/configure/'. $block['module'] .'/'. $block['delta']));
-    if ($block['module'] == 'block') {
-      $form[$i]['delete'] = array('#value' => l(t('delete'), 'admin/build/block/delete/'. $block['delta']));
-    }
-  }
-  $form['submit'] = array('#type' => 'submit', '#value' => t('Save blocks'));
-
-  return $form;
-}
-
-/**
- * Helper function for sorting blocks on admin/build/block.
- *
- * Active blocks are sorted by region, then by weight.
- * Disabled blocks are sorted by name.
- */
-function _block_compare($a, $b) {
-  $status = $b['status'] - $a['status'];
-  // Separate enabled from disabled.
-  if ($status) {
-    return $status;
-  }
-  // Enabled blocks
-  if ($a['status']) {
-    $place = strcmp($a['region'], $b['region']);
-    return $place ? $place : ($a['weight'] - $b['weight']);
-  }
-  // Disabled blocks
-  else {
-    return strcmp($a['info'], $b['info']);
-  }
-}
-
-/**
- * Process main block administration form submission.
- */
-function block_admin_display_submit($form_id, $form_values) {
-  foreach ($form_values as $block) {
-    $block['status'] = $block['region'] != BLOCK_REGION_NONE;
-    $block['region'] = $block['status'] ? $block['region'] : '';
-    db_query("UPDATE {blocks} SET status = %d, weight = %d, region = '%s', throttle = %d WHERE module = '%s' AND delta = '%s' AND theme = '%s'", $block['status'], $block['weight'], $block['region'], $block['throttle'], $block['module'], $block['delta'], $block['theme']);
-  }
-  drupal_set_message(t('The block settings have been updated.'));
-  cache_clear_all();
-}
-
-/**
- * Theme main block administration form submission.
- *
- * Note: the blocks are already sorted in the right order,
- * grouped by status, region and weight.
- */
-function theme_block_admin_display($form) {
-  global $theme_key;
-
-  $throttle = module_exists('throttle');
-  $block_regions = system_region_list($theme_key);
-
-  // Highlight regions on page to provide visual reference.
-  foreach ($block_regions as $key => $value) {
-    drupal_set_content($key, '<div class="block-region">'. $value .'</div>');
-  }
-
-  // Build rows
-  $rows = array();
-  $last_region = '';
-  $last_status = 1;
-  foreach (element_children($form) as $i) {
-    $block = &$form[$i];
-    // Only take form elements that are blocks.
-    if (isset($block['info'])) {
-      // Fetch values
-      $region = $block['region']['#default_value'];
-      $status = $region != BLOCK_REGION_NONE;
-
-      // Output region header
-      if ($status && $region != $last_region) {
-        $region_title = t('@region', array('@region' => drupal_ucfirst($block_regions[$region])));
-        $rows[] = array(array('data' => $region_title, 'class' => 'region', 'colspan' => ($throttle ? 7 : 6)));
-        $last_region = $region;
-      }
-      // Output disabled header
-      elseif ($status != $last_status) {
-        $rows[] = array(array('data' => t('Disabled'), 'class' => 'region', 'colspan' => ($throttle ? 7 : 6)));
-        $last_status = $status;
-      }
-
-      // Generate block row
-      $row = array(
-        array('data' => drupal_render($block['info']), 'class' => 'block'),
-        drupal_render($block['region']) . drupal_render($block['theme']),
-        drupal_render($block['weight']),
-      );
-      if ($throttle) {
-        $row[] = drupal_render($block['throttle']);
-      }
-      $row[] = drupal_render($block['configure']);
-      $row[] = !empty($block['delete']) ? drupal_render($block['delete']) : '';
-      $rows[] = $row;
-    }
-  }
-
-  // Finish table
-  $header = array(t('Block'), t('Region'), t('Weight'));
-  if ($throttle) {
-    $header[] = t('Throttle');
-  }
-  $header[] = array('data' => t('Operations'), 'colspan' => 2);
-
-  $output = theme('table', $header, $rows, array('id' => 'blocks'));
-
-  $output .= drupal_render($form);
-
-  return $output;
-}
-
-function block_box_get($bid) {
-  return db_fetch_array(db_query("SELECT bx.*, title FROM {boxes} bx INNER JOIN {blocks} bl ON bx.bid = bl.delta WHERE module = 'block' AND bid = %d", $bid));
-}
-
-/**
- * Menu callback; displays the block configuration form.
- */
-function block_admin_configure($module = NULL, $delta = 0) {
-
-  $form['module'] = array('#type' => 'value', '#value' => $module);
-  $form['delta'] = array('#type' => 'value', '#value' => $delta);
-
-  $edit = db_fetch_array(db_query("SELECT pages, visibility, custom, title FROM {blocks} WHERE module = '%s' AND delta = '%s'", $module, $delta));
-
-  $form['block_settings'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Block specific settings'),
-    '#collapsible' => TRUE,
-  );
-  $form['block_settings']['title'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Block title'),
-    '#maxlength' => 64,
-    '#description' =>  $module == 'block' ? t('The title of the block as shown to the user.') : t('Override the default title for the block. Use <em>&lt;none&gt;</em> to display no title, or leave blank to use the default block title.'),
-    '#default_value' => $edit['title'],
-    '#weight' => -18,
-  );
-
-
-  // Module-specific block configurations.
-  if ($settings = module_invoke($module, 'block', 'configure', $delta)) {
-    foreach ($settings as $k => $v) {
-      $form['block_settings'][$k] = $v;
-    }
-  }
-
-  // Get the block subject for the page title.
-  $info = module_invoke($module, 'block', 'list');
-  if (isset($info[$delta])) {
-    drupal_set_title(t("'%name' block", array('%name' => $info[$delta]['info'])));
-  }
-
-  // Standard block configurations.
-  $form['user_vis_settings'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('User specific visibility settings'),
-    '#collapsible' => TRUE,
-  );
-  $form['user_vis_settings']['custom'] = array(
-    '#type' => 'radios',
-    '#title' => t('Custom visibility settings'),
-    '#options' => array(
-      t('Users cannot control whether or not they see this block.'),
-      t('Show this block by default, but let individual users hide it.'),
-      t('Hide this block by default but let individual users show it.')
-    ),
-    '#description' =>  t('Allow individual users to customize the visibility of this block in their account settings.'),
-    '#default_value' => $edit['custom'],
-  );
-
-  // Role-based visibility settings
-  $default_role_options = array();
-  $result = db_query("SELECT rid FROM {blocks_roles} WHERE module = '%s' AND delta = '%s'", $module, $delta);
-  while ($role = db_fetch_object($result)) {
-    $default_role_options[] = $role->rid;
-  }
-  $result = db_query('SELECT rid, name FROM {role} ORDER BY name');
-  $role_options = array();
-  while ($role = db_fetch_object($result)) {
-    $role_options[$role->rid] = $role->name;
-  }
-  $form['role_vis_settings'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Role specific visibility settings'),
-    '#collapsible' => TRUE,
-  );
-  $form['role_vis_settings']['roles'] = array(
-    '#type' => 'checkboxes',
-    '#title' => t('Show block for specific roles'),
-    '#default_value' => $default_role_options,
-    '#options' => $role_options,
-    '#description' =>  t('Show this block only for the selected role(s). If you select no roles, the block will be visible to all users.'),
-  );
-
-  $form['page_vis_settings'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Page specific visibility settings'),
-    '#collapsible' => TRUE,
-  );
-  $access = user_access('use PHP for block visibility');
-
-  if ($edit['visibility'] == 2 && !$access) {
-    $form['page_vis_settings'] = array();
-    $form['page_vis_settings']['visibility'] = array('#type' => 'value', '#value' => 2);
-    $form['page_vis_settings']['pages'] = array('#type' => 'value', '#value' => $edit['pages']);
-  }
-  else {
-    $options = array(t('Show on every page except the listed pages.'), t('Show on only the listed pages.'));
-    $description = t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page.", array('%blog' => 'blog', '%blog-wildcard' => 'blog/*', '%front' => '<front>'));
-
-    if ($access) {
-      $options[] = t('Show if the following PHP code returns <code>TRUE</code> (PHP-mode, experts only).');
-      $description .= ' '. t('If the PHP-mode is chosen, enter PHP code between %php. Note that executing incorrect PHP-code can break your Drupal site.', array('%php' => '<?php ?>'));
-    }
-    $form['page_vis_settings']['visibility'] = array(
-      '#type' => 'radios',
-      '#title' => t('Show block on specific pages'),
-      '#options' => $options,
-      '#default_value' => $edit['visibility'],
-    );
-    $form['page_vis_settings']['pages'] = array(
-      '#type' => 'textarea',
-      '#title' => t('Pages'),
-      '#default_value' => $edit['pages'],
-      '#description' => $description,
-    );
-  }
-
-  $form['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Save block'),
-  );
-
-  return $form;
-}
-
-function block_admin_configure_validate($form_id, $form_values) {
-  if ($form_values['module'] == 'block') {
-    if (empty($form_values['info']) || db_num_rows(db_query("SELECT bid FROM {boxes} WHERE bid != %d AND info = '%s'", $form_values['delta'], $form_values['info']))) {
-      form_set_error('info', t('Please ensure that each block description is unique.'));
-    }
-  }
-}
-
-function block_admin_configure_submit($form_id, $form_values) {
-  if (!form_get_errors()) {
-    db_query("UPDATE {blocks} SET visibility = %d, pages = '%s', custom = %d, title = '%s' WHERE module = '%s' AND delta = '%s'", $form_values['visibility'], trim($form_values['pages']), $form_values['custom'], $form_values['title'], $form_values['module'], $form_values['delta']);
-    db_query("DELETE FROM {blocks_roles} WHERE module = '%s' AND delta = '%s'", $form_values['module'], $form_values['delta']);
-    foreach (array_filter($form_values['roles']) as $rid) {
-      db_query("INSERT INTO {blocks_roles} (rid, module, delta) VALUES (%d, '%s', '%s')", $rid, $form_values['module'], $form_values['delta']);
-    }
-    module_invoke($form_values['module'], 'block', 'save', $form_values['delta'], $form_values);
-    drupal_set_message(t('The block configuration has been saved.'));
-    cache_clear_all();
-    return 'admin/build/block';
-  }
-}
-
-/**
- * Menu callback: display the custom block addition form.
- */
-function block_add_block_form() {
-  return block_admin_configure('block', NULL);
-}
-
-function block_add_block_form_validate($form_id, $form_values) {
-  if (empty($form_values['info']) || db_num_rows(db_query("SELECT info FROM {boxes} WHERE info = '%s'", $form_values['info']))) {
-    form_set_error('info', t('Please ensure that each block description is unique.'));
-  }
-}
-
-/**
- * Save the new custom block.
- */
-function block_add_block_form_submit($form_id, $form_values) {
-  $delta = db_next_id('{boxes}_bid');
-
-  foreach (list_themes() as $key => $theme) {
-    if ($theme->status) {
-      db_query("INSERT INTO {blocks} (visibility, pages, custom, title, module, theme, status, weight, delta) VALUES(%d, '%s', %d, '%s', '%s', '%s', %d, %d, %d)", $form_values['visibility'], trim($form_values['pages']), $form_values['custom'], $form_values['title'], $form_values['module'], $theme->name, 0, 0, $delta);
-    }
-  }
-
-  foreach (array_filter($form_values['roles']) as $rid) {
-    db_query("INSERT INTO {blocks_roles} (rid, module, delta) VALUES (%d, '%s', '%s')", $rid, $form_values['module'], $delta);
-  }
-
-  db_query("INSERT INTO {boxes} (bid, body, info, format) VALUES  (%d, '%s', '%s', %d)", $delta, $form_values['body'], $form_values['info'], $form_values['format']);
-
-  drupal_set_message(t('The block has been created.'));
-  cache_clear_all();
-
-  return 'admin/build/block';
-}
-
-/**
- * Menu callback; confirm deletion of custom blocks.
- */
-function block_box_delete($bid = 0) {
-  $box = block_box_get($bid);
-  $form['info'] = array('#type' => 'hidden', '#value' => $box['info'] ? $box['info'] : $box['title']);
-  $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'));
-}
-
-/**
- * Deletion of custom blocks.
- */
-function block_box_delete_submit($form_id, $form_values) {
-  db_query('DELETE FROM {boxes} WHERE bid = %d', $form_values['bid']);
-  db_query("DELETE FROM {blocks} WHERE module = 'block' AND delta = %d", $form_values['bid']);
-  drupal_set_message(t('The block %name has been removed.', array('%name' => $form_values['info'])));
-  cache_clear_all();
-  return 'admin/build/block';
-};
-
-/**
- * Define the custom block form.
- */
-function block_box_form($edit = array()) {
-  $edit += array(
-    'info' => '',
-    'body' => '',
-  );
-  $form['info'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Block description'),
-    '#default_value' => $edit['info'],
-    '#maxlength' => 64,
-    '#description' => t('A brief description of your block. Used on the <a href="@overview">block overview page</a>.', array('@overview' => url('admin/build/block'))),
-    '#required' => TRUE,
-    '#weight' => -19,
-  );
-  $form['body_field']['#weight'] = -17;
-  $form['body_field']['body'] = array(
-    '#type' => 'textarea',
-    '#title' => t('Block body'),
-    '#default_value' => $edit['body'],
-    '#rows' => 15,
-    '#description' => t('The content of the block as shown to the user.'),
-    '#weight' => -17,
-  );
-  if (!isset($edit['format'])) {
-    $edit['format'] = FILTER_FORMAT_DEFAULT;
-  }
-  $form['body_field']['format'] = filter_form($edit['format'], -16);
-
-  return $form;
-}
-
-function block_box_save($edit, $delta) {
-  if (!filter_access($edit['format'])) {
-    $edit['format'] = FILTER_FORMAT_DEFAULT;
-  }
-
-  db_query("UPDATE {boxes} SET body = '%s', info = '%s', format = %d WHERE bid = %d", $edit['body'], $edit['info'], $edit['format'], $delta);
-
-  return TRUE;
-}
-
-/**
- * Implementation of hook_user().
- *
- * Allow users to decide which custom blocks to display when they visit
- * the site.
- */
-function block_user($type, $edit, &$user, $category = NULL) {
-  global $user;
-  switch ($type) {
-    case 'form':
-      if ($category == 'account') {
-        $result = db_query("SELECT DISTINCT b.* FROM {blocks} b LEFT JOIN {blocks_roles} r ON b.module = r.module AND b.delta = r.delta WHERE b.status = 1 AND b.custom != 0 AND (r.rid IN (%s) OR r.rid IS NULL) ORDER BY b.weight, b.module", implode(',', array_keys($user->roles)));
-        $form['block'] = array('#type' => 'fieldset', '#title' => t('Block configuration'), '#weight' => 3, '#collapsible' => TRUE, '#tree' => TRUE);
-        while ($block = db_fetch_object($result)) {
-          $data = module_invoke($block->module, 'block', 'list');
-          if ($data[$block->delta]['info']) {
-            $return = TRUE;
-            $form['block'][$block->module][$block->delta] = array('#type' => 'checkbox', '#title' => check_plain($data[$block->delta]['info']), '#default_value' => isset($user->block[$block->module][$block->delta]) ? $user->block[$block->module][$block->delta] : ($block->custom == 1));
-          }
-        }
-
-        if (!empty($return)) {
-          return $form;
-        }
-      }
-
-      break;
-    case 'validate':
-      if (empty($edit['block'])) {
-        $edit['block'] = array();
-      }
-      return $edit;
-  }
-}
-
-/**
  * Return all blocks in the specified region for the current user.
  *
  * @param $region
Index: modules/block/block.pages.inc
===================================================================
RCS file: modules/block/block.pages.inc
diff -N modules/block/block.pages.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/block/block.pages.inc	30 Apr 2007 07:06:42 -0000
@@ -0,0 +1,417 @@
+<?php
+// $Id: block.module,v 1.257 2007/04/17 07:19:38 dries Exp $
+
+/**
+ * @file
+ * Controls the boxes that are displayed around the main content.
+ */
+
+
+/**
+ * Generate main block administration form.
+ */
+function block_admin_display($theme = NULL) {
+  global $theme_key, $custom_theme;
+
+  // Add CSS
+  drupal_add_css(drupal_get_path('module', 'block') .'/block.css', 'module', 'all', FALSE);
+
+  // If non-default theme configuration has been selected, set the custom theme.
+  if ($theme) {
+    $custom_theme = $theme;
+  }
+  else {
+    $custom_theme = variable_get('theme_default', 'garland');
+  }
+  init_theme();
+
+  // Fetch and sort blocks
+  $blocks = _block_rehash();
+  usort($blocks, '_block_compare');
+
+  $throttle = module_exists('throttle');
+  $block_regions = array(BLOCK_REGION_NONE => '<'. t('none') .'>') + system_region_list($theme_key);
+
+  // Build form tree
+  $form['#action'] = arg(3) ? url('admin/build/block/list/'. $theme_key) : url('admin/build/block');
+  $form['#tree'] = TRUE;
+  foreach ($blocks as $i => $block) {
+    $form[$i]['module'] = array('#type' => 'value', '#value' => $block['module']);
+    $form[$i]['delta'] = array('#type' => 'value', '#value' => $block['delta']);
+    $form[$i]['info'] = array('#value' => check_plain($block['info']));
+    $form[$i]['theme'] = array('#type' => 'hidden', '#value' => $theme_key);
+    $form[$i]['weight'] = array('#type' => 'weight', '#default_value' => $block['weight']);
+    $form[$i]['region'] = array('#type' => 'select',
+      '#default_value' => $block['status'] ? (isset($block['region']) ? $block['region'] : system_default_region($theme_key)) : BLOCK_REGION_NONE,
+      '#options' => $block_regions,
+    );
+
+    if ($throttle) {
+      $form[$i]['throttle'] = array('#type' => 'checkbox', '#default_value' => isset($block['throttle']) ? $block['throttle'] : FALSE);
+    }
+    $form[$i]['configure'] = array('#value' => l(t('configure'), 'admin/build/block/configure/'. $block['module'] .'/'. $block['delta']));
+    if ($block['module'] == 'block') {
+      $form[$i]['delete'] = array('#value' => l(t('delete'), 'admin/build/block/delete/'. $block['delta']));
+    }
+  }
+  $form['submit'] = array('#type' => 'submit', '#value' => t('Save blocks'));
+
+  return $form;
+}
+
+/**
+ * Helper function for sorting blocks on admin/build/block.
+ *
+ * Active blocks are sorted by region, then by weight.
+ * Disabled blocks are sorted by name.
+ */
+function _block_compare($a, $b) {
+  $status = $b['status'] - $a['status'];
+  // Separate enabled from disabled.
+  if ($status) {
+    return $status;
+  }
+  // Enabled blocks
+  if ($a['status']) {
+    $place = strcmp($a['region'], $b['region']);
+    return $place ? $place : ($a['weight'] - $b['weight']);
+  }
+  // Disabled blocks
+  else {
+    return strcmp($a['info'], $b['info']);
+  }
+}
+
+/**
+ * Process main block administration form submission.
+ */
+function block_admin_display_submit($form_id, $form_values) {
+  foreach ($form_values as $block) {
+    $block['status'] = $block['region'] != BLOCK_REGION_NONE;
+    $block['region'] = $block['status'] ? $block['region'] : '';
+    db_query("UPDATE {blocks} SET status = %d, weight = %d, region = '%s', throttle = %d WHERE module = '%s' AND delta = '%s' AND theme = '%s'", $block['status'], $block['weight'], $block['region'], $block['throttle'], $block['module'], $block['delta'], $block['theme']);
+  }
+  drupal_set_message(t('The block settings have been updated.'));
+  cache_clear_all();
+}
+
+/**
+ * Theme main block administration form submission.
+ *
+ * Note: the blocks are already sorted in the right order,
+ * grouped by status, region and weight.
+ */
+function theme_block_admin_display($form) {
+  global $theme_key;
+
+  $throttle = module_exists('throttle');
+  $block_regions = system_region_list($theme_key);
+
+  // Highlight regions on page to provide visual reference.
+  foreach ($block_regions as $key => $value) {
+    drupal_set_content($key, '<div class="block-region">'. $value .'</div>');
+  }
+
+  // Build rows
+  $rows = array();
+  $last_region = '';
+  $last_status = 1;
+  foreach (element_children($form) as $i) {
+    $block = &$form[$i];
+    // Only take form elements that are blocks.
+    if (isset($block['info'])) {
+      // Fetch values
+      $region = $block['region']['#default_value'];
+      $status = $region != BLOCK_REGION_NONE;
+
+      // Output region header
+      if ($status && $region != $last_region) {
+        $region_title = t('@region', array('@region' => drupal_ucfirst($block_regions[$region])));
+        $rows[] = array(array('data' => $region_title, 'class' => 'region', 'colspan' => ($throttle ? 7 : 6)));
+        $last_region = $region;
+      }
+      // Output disabled header
+      elseif ($status != $last_status) {
+        $rows[] = array(array('data' => t('Disabled'), 'class' => 'region', 'colspan' => ($throttle ? 7 : 6)));
+        $last_status = $status;
+      }
+
+      // Generate block row
+      $row = array(
+        array('data' => drupal_render($block['info']), 'class' => 'block'),
+        drupal_render($block['region']) . drupal_render($block['theme']),
+        drupal_render($block['weight']),
+      );
+      if ($throttle) {
+        $row[] = drupal_render($block['throttle']);
+      }
+      $row[] = drupal_render($block['configure']);
+      $row[] = !empty($block['delete']) ? drupal_render($block['delete']) : '';
+      $rows[] = $row;
+    }
+  }
+
+  // Finish table
+  $header = array(t('Block'), t('Region'), t('Weight'));
+  if ($throttle) {
+    $header[] = t('Throttle');
+  }
+  $header[] = array('data' => t('Operations'), 'colspan' => 2);
+
+  $output = theme('table', $header, $rows, array('id' => 'blocks'));
+
+  $output .= drupal_render($form);
+
+  return $output;
+}
+
+function block_box_get($bid) {
+  return db_fetch_array(db_query("SELECT bx.*, title FROM {boxes} bx INNER JOIN {blocks} bl ON bx.bid = bl.delta WHERE module = 'block' AND bid = %d", $bid));
+}
+
+/**
+ * Menu callback; displays the block configuration form.
+ */
+function block_admin_configure($module = NULL, $delta = 0) {
+
+  $form['module'] = array('#type' => 'value', '#value' => $module);
+  $form['delta'] = array('#type' => 'value', '#value' => $delta);
+
+  $edit = db_fetch_array(db_query("SELECT pages, visibility, custom, title FROM {blocks} WHERE module = '%s' AND delta = '%s'", $module, $delta));
+
+  $form['block_settings'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Block specific settings'),
+    '#collapsible' => TRUE,
+  );
+  $form['block_settings']['title'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Block title'),
+    '#maxlength' => 64,
+    '#description' =>  $module == 'block' ? t('The title of the block as shown to the user.') : t('Override the default title for the block. Use <em>&lt;none&gt;</em> to display no title, or leave blank to use the default block title.'),
+    '#default_value' => $edit['title'],
+    '#weight' => -18,
+  );
+
+
+  // Module-specific block configurations.
+  if ($settings = module_invoke($module, 'block', 'configure', $delta)) {
+    foreach ($settings as $k => $v) {
+      $form['block_settings'][$k] = $v;
+    }
+  }
+
+  // Get the block subject for the page title.
+  $info = module_invoke($module, 'block', 'list');
+  if (isset($info[$delta])) {
+    drupal_set_title(t("'%name' block", array('%name' => $info[$delta]['info'])));
+  }
+
+  // Standard block configurations.
+  $form['user_vis_settings'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('User specific visibility settings'),
+    '#collapsible' => TRUE,
+  );
+  $form['user_vis_settings']['custom'] = array(
+    '#type' => 'radios',
+    '#title' => t('Custom visibility settings'),
+    '#options' => array(
+      t('Users cannot control whether or not they see this block.'),
+      t('Show this block by default, but let individual users hide it.'),
+      t('Hide this block by default but let individual users show it.')
+    ),
+    '#description' =>  t('Allow individual users to customize the visibility of this block in their account settings.'),
+    '#default_value' => $edit['custom'],
+  );
+
+  // Role-based visibility settings
+  $default_role_options = array();
+  $result = db_query("SELECT rid FROM {blocks_roles} WHERE module = '%s' AND delta = '%s'", $module, $delta);
+  while ($role = db_fetch_object($result)) {
+    $default_role_options[] = $role->rid;
+  }
+  $result = db_query('SELECT rid, name FROM {role} ORDER BY name');
+  $role_options = array();
+  while ($role = db_fetch_object($result)) {
+    $role_options[$role->rid] = $role->name;
+  }
+  $form['role_vis_settings'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Role specific visibility settings'),
+    '#collapsible' => TRUE,
+  );
+  $form['role_vis_settings']['roles'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Show block for specific roles'),
+    '#default_value' => $default_role_options,
+    '#options' => $role_options,
+    '#description' =>  t('Show this block only for the selected role(s). If you select no roles, the block will be visible to all users.'),
+  );
+
+  $form['page_vis_settings'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Page specific visibility settings'),
+    '#collapsible' => TRUE,
+  );
+  $access = user_access('use PHP for block visibility');
+
+  if ($edit['visibility'] == 2 && !$access) {
+    $form['page_vis_settings'] = array();
+    $form['page_vis_settings']['visibility'] = array('#type' => 'value', '#value' => 2);
+    $form['page_vis_settings']['pages'] = array('#type' => 'value', '#value' => $edit['pages']);
+  }
+  else {
+    $options = array(t('Show on every page except the listed pages.'), t('Show on only the listed pages.'));
+    $description = t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page.", array('%blog' => 'blog', '%blog-wildcard' => 'blog/*', '%front' => '<front>'));
+
+    if ($access) {
+      $options[] = t('Show if the following PHP code returns <code>TRUE</code> (PHP-mode, experts only).');
+      $description .= ' '. t('If the PHP-mode is chosen, enter PHP code between %php. Note that executing incorrect PHP-code can break your Drupal site.', array('%php' => '<?php ?>'));
+    }
+    $form['page_vis_settings']['visibility'] = array(
+      '#type' => 'radios',
+      '#title' => t('Show block on specific pages'),
+      '#options' => $options,
+      '#default_value' => $edit['visibility'],
+    );
+    $form['page_vis_settings']['pages'] = array(
+      '#type' => 'textarea',
+      '#title' => t('Pages'),
+      '#default_value' => $edit['pages'],
+      '#description' => $description,
+    );
+  }
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save block'),
+  );
+
+  return $form;
+}
+
+function block_admin_configure_validate($form_id, $form_values) {
+  if ($form_values['module'] == 'block') {
+    if (empty($form_values['info']) || db_num_rows(db_query("SELECT bid FROM {boxes} WHERE bid != %d AND info = '%s'", $form_values['delta'], $form_values['info']))) {
+      form_set_error('info', t('Please ensure that each block description is unique.'));
+    }
+  }
+}
+
+function block_admin_configure_submit($form_id, $form_values) {
+  if (!form_get_errors()) {
+    db_query("UPDATE {blocks} SET visibility = %d, pages = '%s', custom = %d, title = '%s' WHERE module = '%s' AND delta = '%s'", $form_values['visibility'], trim($form_values['pages']), $form_values['custom'], $form_values['title'], $form_values['module'], $form_values['delta']);
+    db_query("DELETE FROM {blocks_roles} WHERE module = '%s' AND delta = '%s'", $form_values['module'], $form_values['delta']);
+    foreach (array_filter($form_values['roles']) as $rid) {
+      db_query("INSERT INTO {blocks_roles} (rid, module, delta) VALUES (%d, '%s', '%s')", $rid, $form_values['module'], $form_values['delta']);
+    }
+    module_invoke($form_values['module'], 'block', 'save', $form_values['delta'], $form_values);
+    drupal_set_message(t('The block configuration has been saved.'));
+    cache_clear_all();
+    return 'admin/build/block';
+  }
+}
+
+/**
+ * Menu callback: display the custom block addition form.
+ */
+function block_add_block_form() {
+  return block_admin_configure('block', NULL);
+}
+
+function block_add_block_form_validate($form_id, $form_values) {
+  if (empty($form_values['info']) || db_num_rows(db_query("SELECT info FROM {boxes} WHERE info = '%s'", $form_values['info']))) {
+    form_set_error('info', t('Please ensure that each block description is unique.'));
+  }
+}
+
+/**
+ * Save the new custom block.
+ */
+function block_add_block_form_submit($form_id, $form_values) {
+  $delta = db_next_id('{boxes}_bid');
+
+  foreach (list_themes() as $key => $theme) {
+    if ($theme->status) {
+      db_query("INSERT INTO {blocks} (visibility, pages, custom, title, module, theme, status, weight, delta) VALUES(%d, '%s', %d, '%s', '%s', '%s', %d, %d, %d)", $form_values['visibility'], trim($form_values['pages']), $form_values['custom'], $form_values['title'], $form_values['module'], $theme->name, 0, 0, $delta);
+    }
+  }
+
+  foreach (array_filter($form_values['roles']) as $rid) {
+    db_query("INSERT INTO {blocks_roles} (rid, module, delta) VALUES (%d, '%s', '%s')", $rid, $form_values['module'], $delta);
+  }
+
+  db_query("INSERT INTO {boxes} (bid, body, info, format) VALUES  (%d, '%s', '%s', %d)", $delta, $form_values['body'], $form_values['info'], $form_values['format']);
+
+  drupal_set_message(t('The block has been created.'));
+  cache_clear_all();
+
+  return 'admin/build/block';
+}
+
+/**
+ * Menu callback; confirm deletion of custom blocks.
+ */
+function block_box_delete($bid = 0) {
+  $box = block_box_get($bid);
+  $form['info'] = array('#type' => 'hidden', '#value' => $box['info'] ? $box['info'] : $box['title']);
+  $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'));
+}
+
+/**
+ * Deletion of custom blocks.
+ */
+function block_box_delete_submit($form_id, $form_values) {
+  db_query('DELETE FROM {boxes} WHERE bid = %d', $form_values['bid']);
+  db_query("DELETE FROM {blocks} WHERE module = 'block' AND delta = %d", $form_values['bid']);
+  drupal_set_message(t('The block %name has been removed.', array('%name' => $form_values['info'])));
+  cache_clear_all();
+  return 'admin/build/block';
+};
+
+/**
+ * Define the custom block form.
+ */
+function block_box_form($edit = array()) {
+  $edit += array(
+    'info' => '',
+    'body' => '',
+  );
+  $form['info'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Block description'),
+    '#default_value' => $edit['info'],
+    '#maxlength' => 64,
+    '#description' => t('A brief description of your block. Used on the <a href="@overview">block overview page</a>.', array('@overview' => url('admin/build/block'))),
+    '#required' => TRUE,
+    '#weight' => -19,
+  );
+  $form['body_field']['#weight'] = -17;
+  $form['body_field']['body'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Block body'),
+    '#default_value' => $edit['body'],
+    '#rows' => 15,
+    '#description' => t('The content of the block as shown to the user.'),
+    '#weight' => -17,
+  );
+  if (!isset($edit['format'])) {
+    $edit['format'] = FILTER_FORMAT_DEFAULT;
+  }
+  $form['body_field']['format'] = filter_form($edit['format'], -16);
+
+  return $form;
+}
+
+function block_box_save($edit, $delta) {
+  if (!filter_access($edit['format'])) {
+    $edit['format'] = FILTER_FORMAT_DEFAULT;
+  }
+
+  db_query("UPDATE {boxes} SET body = '%s', info = '%s', format = %d WHERE bid = %d", $edit['body'], $edit['info'], $edit['format'], $delta);
+
+  return TRUE;
+}
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.540
diff -u -p -r1.540 comment.module
--- modules/comment/comment.module	27 Apr 2007 07:42:54 -0000	1.540
+++ modules/comment/comment.module	30 Apr 2007 07:06:42 -0000
@@ -201,6 +201,7 @@ function comment_menu() {
     'description' => t('List and edit site comments and the comment moderation queue.'),
     'page callback' => 'comment_admin',
     'access arguments' => array('administer comments'),
+    'includes' => drupal_get_path('module', 'comment') . '/comment.pages.inc',
   );
 
   // Tabs:
@@ -220,6 +221,7 @@ function comment_menu() {
     'title' => t('Approval queue'),
     'page arguments' => array('approval'),
     'type' => MENU_LOCAL_TASK,
+    'includes' => drupal_get_path('module', 'comment') . '/comment.pages.inc',
   );
 
   $items['admin/content/comment/settings'] = array(
@@ -228,6 +230,7 @@ function comment_menu() {
     'page arguments' => array('comment_admin_settings'),
     'weight' => 10,
     'type' => MENU_LOCAL_TASK,
+    'includes' => drupal_get_path('module', 'comment') . '/comment.pages.inc',
   );
 
   $items['comment/delete'] = array(
@@ -235,6 +238,7 @@ function comment_menu() {
     'page callback' => 'comment_delete',
     'access arguments' => array('administer comments'),
     'type' => MENU_CALLBACK,
+    'includes' => drupal_get_path('module', 'comment') . '/comment.pages.inc',
   );
 
   $items['comment/edit'] = array(
@@ -242,6 +246,7 @@ function comment_menu() {
     'page callback' => 'comment_edit',
     'access arguments' => array('post comments'),
     'type' => MENU_CALLBACK,
+    'includes' => drupal_get_path('module', 'comment') . '/comment.pages.inc',
   );
   $items['comment/reply/%node'] = array(
     'title' => t('Reply to comment'),
@@ -250,6 +255,7 @@ function comment_menu() {
     'access callback' => 'node_access',
     'access arguments' => array('view', 2),
     'type' => MENU_CALLBACK,
+    'includes' => drupal_get_path('module', 'comment') . '/comment.pages.inc',
   );
   $items['node/%node/%'] = array(
     'title' => t('View'),
@@ -258,6 +264,7 @@ function comment_menu() {
     'access callback' => '_comment_view_access',
     'access arguments' => array(1, 2),
     'type' => MENU_CALLBACK,
+    'includes' => drupal_get_path('module', 'comment') . '/comment.pages.inc',
   );
 
   return $items;
@@ -287,6 +294,7 @@ function comment_block($op = 'list', $de
   }
 }
 
+
 /**
  * Find a number of recent comments. This is done in two steps.
  *   1. Find the n (specified by $number) nodes that have the most recent
@@ -511,1557 +519,108 @@ function comment_user($type, $edit, &$us
 }
 
 /**
- * Menu callback; presents the comment settings page.
- */
-function comment_admin_settings() {
-  $form['viewing_options'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Viewing options'),
-    '#collapsible' => TRUE,
-  );
-
-  $form['viewing_options']['comment_default_mode'] = array(
-    '#type' => 'radios',
-    '#title' => t('Default display mode'),
-    '#default_value' => variable_get('comment_default_mode', COMMENT_MODE_THREADED_EXPANDED),
-    '#options' => _comment_get_modes(),
-    '#description' => t('The default view for comments. Expanded views display the body of the comment. Threaded views keep replies together.'),
-  );
-
-  $form['viewing_options']['comment_default_order'] = array(
-    '#type' => 'radios',
-    '#title' => t('Default display order'),
-    '#default_value' => variable_get('comment_default_order', COMMENT_ORDER_NEWEST_FIRST),
-    '#options' => _comment_get_orders(),
-    '#description' => t('The default sorting for new users and anonymous users while viewing comments. These users may change their view using the comment control panel. For registered users, this change is remembered as a persistent user preference.'),
-  );
-
-  $form['viewing_options']['comment_default_per_page'] = array(
-    '#type' => 'select',
-    '#title' => t('Default comments per page'),
-    '#default_value' => variable_get('comment_default_per_page', 50),
-    '#options' => _comment_per_page(),
-    '#description' => t('Default number of comments for each page: more comments are distributed in several pages.'),
-  );
-
-  $form['viewing_options']['comment_controls'] = array(
-    '#type' => 'radios',
-    '#title' => t('Comment controls'),
-    '#default_value' => variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN),
-    '#options' => array(
-      t('Display above the comments'),
-      t('Display below the comments'),
-      t('Display above and below the comments'),
-      t('Do not display')),
-    '#description' => t('Position of the comment controls box. The comment controls let the user change the default display mode and display order of comments.'),
-  );
-
-  $form['posting_settings'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Posting settings'),
-    '#collapsible' => TRUE,
-  );
-
-  $form['posting_settings']['comment_anonymous'] = array(
-    '#type' => 'radios',
-    '#title' => t('Anonymous commenting'),
-    '#default_value' => variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT),
-    '#options' => array(
-      COMMENT_ANONYMOUS_MAYNOT_CONTACT => t('Anonymous posters may not enter their contact information'),
-      COMMENT_ANONYMOUS_MAY_CONTACT => t('Anonymous posters may leave their contact information'),
-      COMMENT_ANONYMOUS_MUST_CONTACT => t('Anonymous posters must leave their contact information')),
-    '#description' => t('This option is enabled when anonymous users have permission to post comments on the <a href="@url">permissions page</a>.', array('@url' => url('admin/user/access', array('fragment' => 'module-comment')))),
-  );
-  if (!user_access('post comments', user_load(array('uid' => 0)))) {
-    $form['posting_settings']['comment_anonymous']['#disabled'] = TRUE;
-  }
-
-  $form['posting_settings']['comment_subject_field'] = array(
-    '#type' => 'radios',
-    '#title' => t('Comment subject field'),
-    '#default_value' => variable_get('comment_subject_field', 1),
-    '#options' => array(t('Disabled'), t('Enabled')),
-    '#description' => t('Can users provide a unique subject for their comments?'),
-  );
-
-  $form['posting_settings']['comment_preview'] = array(
-    '#type' => 'radios',
-    '#title' => t('Preview comment'),
-    '#default_value' => variable_get('comment_preview', COMMENT_PREVIEW_REQUIRED),
-    '#options' => array(t('Optional'), t('Required')),
-  );
-
-  $form['posting_settings']['comment_form_location'] = array(
-    '#type' => 'radios',
-    '#title' => t('Location of comment submission form'),
-    '#default_value' => variable_get('comment_form_location', COMMENT_FORM_SEPARATE_PAGE),
-    '#options' => array(t('Display on separate page'), t('Display below post or comments')),
-  );
-
-  return system_settings_form($form);
-}
-
-/**
- * This is *not* a hook_access() implementation. This function is called
- * to determine whether the current user has access to a particular comment.
+ * Invoke a hook_comment() operation in all modules.
  *
- * Authenticated users can edit their comments as long they have not been
- * replied to. This prevents people from changing or revising their
- * statements based on the replies to their posts.
+ * @param &$comment
+ *   A comment object.
+ * @param $op
+ *   A string containing the name of the comment operation.
+ * @return
+ *   The returned value of the invoked hooks.
  */
-function comment_access($op, $comment) {
-  global $user;
-
-  if ($op == 'edit') {
-    return ($user->uid && $user->uid == $comment->uid && comment_num_replies($comment->cid) == 0) || user_access('administer comments');
+function comment_invoke_comment(&$comment, $op) {
+  $return = array();
+  foreach (module_implements('comment') as $name) {
+    $function = $name .'_comment';
+    $result = $function($comment, $op);
+    if (isset($result) && is_array($result)) {
+      $return = array_merge($return, $result);
+    }
+    else if (isset($result)) {
+      $return[] = $result;
+    }
   }
+  return $return;
 }
 
-function comment_node_url() {
-  return arg(0) .'/'. arg(1);
-}
-
-function comment_edit($cid) {
-  global $user;
-
-  $comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d', $cid));
-  $comment = drupal_unpack($comment);
-  $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
-  if (comment_access('edit', $comment)) {
-    return comment_form_box((array)$comment);
-  }
-  else {
-    drupal_access_denied();
-  }
-}
 
 /**
- * This function is responsible for generating a comment reply form.
- * There are several cases that have to be handled, including:
- *   - replies to comments
- *   - replies to nodes
- *   - attempts to reply to nodes that can no longer accept comments
- *   - respecting access permissions ('access comments', 'post comments', etc.)
- *
- * The node or comment that is being replied to must appear above the comment
- * form to provide the user context while authoring the comment.
+ * Generate vancode.
  *
- * @param $node
- *   Every comment belongs to a node. This is that node.
- * @param $pid
- *   Some comments are replies to other comments. In those cases, $pid is the parent
- *   comment's cid.
+ * Consists of a leading character indicating length, followed by N digits
+ * with a numerical value in base 36. Vancodes can be sorted as strings
+ * without messing up numerical order.
  *
- * @return $output
- *   The rendered parent node or comment plus the new comment form.
+ * It goes:
+ * 00, 01, 02, ..., 0y, 0z,
+ * 110, 111, ... , 1zy, 1zz,
+ * 2100, 2101, ..., 2zzy, 2zzz,
+ * 31000, 31001, ...
  */
-function comment_reply($node, $pid = NULL) {
-  // Set the breadcrumb trail.
-  menu_set_location(array(array('path' => "node/$node->nid", 'title' => $node->title), array('path' => "comment/reply/$node->nid")));
-
-  $op = isset($_POST['op']) ? $_POST['op'] : '';
-
-  $output = '';
-
-  if (user_access('access comments')) {
-    // The user is previewing a comment prior to submitting it.
-    if ($op == t('Preview comment')) {
-      if (user_access('post comments')) {
-        $output .= comment_form_box(array('pid' => $pid, 'nid' => $node->nid), NULL);
-      }
-      else {
-        drupal_set_message(t('You are not authorized to post comments.'), 'error');
-        drupal_goto("node/$node->nid");
-      }
-    }
-    else {
-      // $pid indicates that this is a reply to a comment.
-      if ($pid) {
-        // load the comment whose cid = $pid
-        if ($comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = %d', $pid, COMMENT_PUBLISHED))) {
-          // If that comment exists, make sure that the current comment and the parent comment both
-          // belong to the same parent node.
-          if ($comment->nid != $node->nid) {
-            // Attempting to reply to a comment not belonging to the current nid.
-            drupal_set_message(t('The comment you are replying to does not exist.'), 'error');
-            drupal_goto("node/$node->nid");
-          }
-          // Display the parent comment
-          $comment = drupal_unpack($comment);
-          $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
-          $output .= theme('comment_view', $comment);
-        }
-        else {
-          drupal_set_message(t('The comment you are replying to does not exist.'), 'error');
-          drupal_goto("node/$node->nid");
-        }
-      }
-      // This is the case where the comment is in response to a node. Display the node.
-      else if (user_access('access content')) {
-        $output .= node_view($node);
-      }
-
-      // Should we show the reply box?
-      if (node_comment_mode($node->nid) != COMMENT_NODE_READ_WRITE) {
-        drupal_set_message(t("This discussion is closed: you can't post new comments."), 'error');
-        drupal_goto("node/$node->nid");
-      }
-      else if (user_access('post comments')) {
-        $output .= comment_form_box(array('pid' => $pid, 'nid' => $node->nid), t('Reply'));
-      }
-      else {
-        drupal_set_message(t('You are not authorized to post comments.'), 'error');
-        drupal_goto("node/$node->nid");
-      }
-    }
-  }
-  else {
-    drupal_set_message(t('You are not authorized to view comments.'), 'error');
-    drupal_goto("node/$node->nid");
-  }
-
-  return $output;
+function int2vancode($i = 0) {
+  $num = base_convert((int)$i, 10, 36);
+  $length = strlen($num);
+  return chr($length + ord('0') - 1) . $num;
 }
 
 /**
- * Accepts a submission of new or changed comment content.
- *
- * @param $edit
- *   A comment array.
- *
- * @return
- *   If the comment is successfully saved the comment ID is returned. If the comment
- *   is not saved, FALSE is returned.
+ * Decode vancode back to an integer.
  */
-function comment_save($edit) {
-  global $user;
-  if (user_access('post comments') && (user_access('administer comments') || node_comment_mode($edit['nid']) == COMMENT_NODE_READ_WRITE)) {
-    if (!form_get_errors()) {
-      if ($edit['cid']) {
-        // Update the comment in the database.
-        db_query("UPDATE {comments} SET status = %d, timestamp = %d, subject = '%s', comment = '%s', format = %d, uid = %d, name = '%s', mail = '%s', homepage = '%s' WHERE cid = %d", $edit['status'], $edit['timestamp'], $edit['subject'], $edit['comment'], $edit['format'], $edit['uid'], $edit['name'], $edit['mail'], $edit['homepage'], $edit['cid']);
-
-        _comment_update_node_statistics($edit['nid']);
-
-        // Allow modules to respond to the updating of a comment.
-        comment_invoke_comment($edit, 'update');
-
-        // Add an entry to the watchdog log.
-        watchdog('content', 'Comment: updated %subject.', array('%subject' => $edit['subject']), WATCHDOG_NOTICE, l(t('view'), 'node/'. $edit['nid'], array('fragment' => 'comment-'. $edit['cid'])));
-      }
-      else {
-        // Check for duplicate comments. Note that we have to use the
-        // validated/filtered data to perform such check.
-        $duplicate = db_result(db_query("SELECT COUNT(cid) FROM {comments} WHERE pid = %d AND nid = %d AND subject = '%s' AND comment = '%s'", $edit['pid'], $edit['nid'], $edit['subject'], $edit['comment']), 0);
-        if ($duplicate != 0) {
-          watchdog('content', 'Comment: duplicate %subject.', array('%subject' => $edit['subject']), WATCHDOG_WARNING);
-        }
-
-        // Add the comment to database.
-        $status = user_access('post comments without approval') ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED;
-        $roles = variable_get('comment_roles', array());
-        $score = 0;
-
-        foreach (array_intersect(array_keys($roles), array_keys($user->roles)) as $rid) {
-          $score = max($roles[$rid], $score);
-        }
-
-        $users = serialize(array(0 => $score));
-
-        // Here we are building the thread field. See the documentation for
-        // comment_render().
-        if ($edit['pid'] == 0) {
-          // This is a comment with no parent comment (depth 0): we start
-          // by retrieving the maximum thread level.
-          $max = db_result(db_query('SELECT MAX(thread) FROM {comments} WHERE nid = %d', $edit['nid']));
-
-          // Strip the "/" from the end of the thread.
-          $max = rtrim($max, '/');
-
-          // Finally, build the thread field for this new comment.
-          $thread = int2vancode(vancode2int($max) + 1) .'/';
-        }
-        else {
-          // This is comment with a parent comment: we increase
-          // the part of the thread value at the proper depth.
-
-          // Get the parent comment:
-          $parent = _comment_load($edit['pid']);
-
-          // Strip the "/" from the end of the parent thread.
-          $parent->thread = (string) rtrim((string) $parent->thread, '/');
-
-          // Get the max value in _this_ thread.
-          $max = db_result(db_query("SELECT MAX(thread) FROM {comments} WHERE thread LIKE '%s.%%' AND nid = %d", $parent->thread, $edit['nid']));
-
-          if ($max == '') {
-            // First child of this parent.
-            $thread = $parent->thread .'.'. int2vancode(0) .'/';
-          }
-          else {
-            // Strip the "/" at the end of the thread.
-            $max = rtrim($max, '/');
-
-            // We need to get the value at the correct depth.
-            $parts = explode('.', $max);
-            $parent_depth = count(explode('.', $parent->thread));
-            $last = $parts[$parent_depth];
-
-            // Finally, build the thread field for this new comment.
-            $thread = $parent->thread .'.'. int2vancode(vancode2int($last) + 1) .'/';
-          }
-        }
-
-        $edit['cid'] = db_next_id('{comments}_cid');
-        $edit['timestamp'] = time();
-
-        if ($edit['uid'] === $user->uid) { // '===' because we want to modify anonymous users too
-          $edit['name'] = $user->name;
-        }
-
-        $edit += array('mail' => '', 'homepage' => '');
-        db_query("INSERT INTO {comments} (cid, nid, pid, uid, subject, comment, format, hostname, timestamp, status, score, users, thread, name, mail, homepage) VALUES (%d, %d, %d, %d, '%s', '%s', %d, '%s', %d, %d, %d, '%s', '%s', '%s', '%s', '%s')", $edit['cid'], $edit['nid'], $edit['pid'], $edit['uid'], $edit['subject'], $edit['comment'], $edit['format'], $_SERVER['REMOTE_ADDR'], $edit['timestamp'], $status, $score, $users, $thread, $edit['name'], $edit['mail'], $edit['homepage']);
-
-        _comment_update_node_statistics($edit['nid']);
-
-        // Tell the other modules a new comment has been submitted.
-        comment_invoke_comment($edit, 'insert');
+function vancode2int($c = '00') {
+  return base_convert(substr($c, 1), 36, 10);
+}
 
-        // Add an entry to the watchdog log.
-        watchdog('content', 'Comment: added %subject.', array('%subject' => $edit['subject']), WATCHDOG_NOTICE, l(t('view'), 'node/'. $edit['nid'], array('fragment' => 'comment-'. $edit['cid'])));
-      }
+/**
+ * Load the entire comment by cid.
+ */
+function _comment_load($cid) {
+  return db_fetch_object(db_query('SELECT * FROM {comments} WHERE cid = %d', $cid));
+}
 
-      // Clear the cache so an anonymous user can see his comment being added.
-      cache_clear_all();
+function comment_num_all($nid) {
+  static $cache;
 
-      // Explain the approval queue if necessary, and then
-      // redirect the user to the node he's commenting on.
-      if ($status == COMMENT_NOT_PUBLISHED) {
-        drupal_set_message(t('Your comment has been queued for moderation by site administrators and will be published after approval.'));
-      }
-      return $edit['cid'];
-    }
-    else {
-      return FALSE;
-    }
-  }
-  else {
-    watchdog('content', 'Comment: unauthorized comment submitted or comment submitted to a closed node %subject.', array('%subject' => $edit['subject']), WATCHDOG_WARNING);
-    drupal_set_message(t('Comment: unauthorized comment submitted or comment submitted to a closed node %subject.', array('%subject' => $edit['subject'])), 'error');
-    return FALSE;
+  if (!isset($cache[$nid])) {
+    $cache[$nid] = db_result(db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = %d', $nid));
   }
+  return $cache[$nid];
 }
 
-function comment_links($comment, $return = 1) {
-  global $user;
-
-  $links = array();
-
-  // If we are viewing just this comment, we link back to the node.
-  if ($return) {
-    $links['comment_parent'] = array(
-      'title' => t('parent'),
-      'href' => comment_node_url(),
-      'fragment' => "comment-$comment->cid"
-    );
-  }
+function comment_num_replies($pid) {
+  static $cache;
 
-  if (node_comment_mode($comment->nid) == COMMENT_NODE_READ_WRITE) {
-    if (user_access('administer comments') && user_access('post comments')) {
-      $links['comment_delete'] = array(
-        'title' => t('delete'),
-        'href' => "comment/delete/$comment->cid"
-      );
-      $links['comment_edit'] = array(
-        'title' => t('edit'),
-        'href' => "comment/edit/$comment->cid"
-      );
-      $links['comment_reply'] = array(
-        'title' => t('reply'),
-        'href' => "comment/reply/$comment->nid/$comment->cid"
-      );
-    }
-    else if (user_access('post comments')) {
-      if (comment_access('edit', $comment)) {
-        $links['comment_edit'] = array(
-          'title' => t('edit'),
-          'href' => "comment/edit/$comment->cid"
-        );
-      }
-      $links['comment_reply'] = array(
-        'title' => t('reply'),
-        'href' => "comment/reply/$comment->nid/$comment->cid"
-      );
-    }
-    else {
-      $links['comment_forbidden']['title'] = theme('comment_post_forbidden', $comment->nid);
-    }
+  if (!isset($cache[$pid])) {
+    $cache[$pid] = db_result(db_query('SELECT COUNT(cid) FROM {comments} WHERE pid = %d AND status = %d', $pid, COMMENT_PUBLISHED));
   }
 
-  return $links;
+  return $cache[$pid];
 }
 
 /**
- * Renders comment(s).
- *
- * @param $node
- *   The node which comment(s) needs rendering.
- * @param $cid
- *   Optional, if given, only one comment is rendered.
- *
- * To display threaded comments in the correct order we keep a 'thread' field
- * and order by that value. This field keeps this data in
- * a way which is easy to update and convenient to use.
- *
- * A "thread" value starts at "1". If we add a child (A) to this comment,
- * we assign it a "thread" = "1.1". A child of (A) will have "1.1.1". Next
- * brother of (A) will get "1.2". Next brother of the parent of (A) will get
- * "2" and so on.
- *
- * First of all note that the thread field stores the depth of the comment:
- * depth 0 will be "X", depth 1 "X.X", depth 2 "X.X.X", etc.
- *
- * Now to get the ordering right, consider this example:
- *
- * 1
- * 1.1
- * 1.1.1
- * 1.2
- * 2
- *
- * If we "ORDER BY thread ASC" we get the above result, and this is the
- * natural order sorted by time. However, if we "ORDER BY thread DESC"
- * we get:
- *
- * 2
- * 1.2
- * 1.1.1
- * 1.1
- * 1
- *
- * Clearly, this is not a natural way to see a thread, and users will get
- * confused. The natural order to show a thread by time desc would be:
- *
- * 2
- * 1
- * 1.2
- * 1.1
- * 1.1.1
- *
- * which is what we already did before the standard pager patch. To achieve
- * this we simply add a "/" at the end of each "thread" value. This way out
- * thread fields will look like depicted below:
- *
- * 1/
- * 1.1/
- * 1.1.1/
- * 1.2/
- * 2/
+ * get number of new comments for current user and specified node
  *
- * we add "/" since this char is, in ASCII, higher than every number, so if
- * now we "ORDER BY thread DESC" we get the correct order. However this would
- * spoil the reverse ordering, "ORDER BY thread ASC" -- here, we do not need
- * to consider the trailing "/" so we use a substring only.
+ * @param $nid node-id to count comments for
+ * @param $timestamp time to count from (defaults to time of last user access
+ *   to node)
  */
-function comment_render($node, $cid = 0) {
+function comment_num_new($nid, $timestamp = 0) {
   global $user;
 
-  $output = '';
-
-  if (user_access('access comments')) {
-    // Pre-process variables.
-    $nid = $node->nid;
-    if (empty($nid)) {
-      $nid = 0;
-    }
-
-    $mode = _comment_get_display_setting('mode');
-    $order = _comment_get_display_setting('sort');
-    $comments_per_page = _comment_get_display_setting('comments_per_page');
-
-    if ($cid) {
-      // Single comment view.
-      $query = 'SELECT c.cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.signature, u.picture, u.data, c.score, c.users, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d';
-      $query_args = array($cid);
-      if (!user_access('administer comments')) {
-        $query .= ' AND c.status = %d';
-        $query_args[] = COMMENT_PUBLISHED;
-      }
-
-      $result = db_query($query, $query_args);
-
-      if ($comment = db_fetch_object($result)) {
-        $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
-        $links = module_invoke_all('link', 'comment', $comment, 1);
-        drupal_alter('link', $links, $node);
-
-        $output .= theme('comment_view', $comment, $links);
-      }
-    }
-    else {
-      // Multiple comment view
-      $query_count = 'SELECT COUNT(*) FROM {comments} WHERE nid = %d';
-      $query = 'SELECT c.cid as cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.signature, u.picture, u.data, c.score, c.users, c.thread, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.nid = %d';
-
-      $query_args = array($nid);
-      if (!user_access('administer comments')) {
-        $query .= ' AND c.status = %d';
-        $query_count .= ' AND status = %d';
-        $query_args[] = COMMENT_PUBLISHED;
-      }
-
-      if ($order == COMMENT_ORDER_NEWEST_FIRST) {
-        if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) {
-          $query .= ' ORDER BY c.timestamp DESC';
-        }
-        else {
-          $query .= ' ORDER BY c.thread DESC';
-        }
-      }
-      else if ($order == COMMENT_ORDER_OLDEST_FIRST) {
-        if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) {
-          $query .= ' ORDER BY c.timestamp';
-        }
-        else {
-
-          /*
-          ** See comment above. Analysis learns that this doesn't cost
-          ** too much. It scales much much better than having the whole
-          ** comment structure.
-          */
-
-          $query .= ' ORDER BY SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))';
-        }
-      }
-
-      // Start a form, for use with comment control.
-      $result = pager_query($query, $comments_per_page, 0, $query_count, $query_args);
-      if (db_num_rows($result) && (variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_ABOVE || variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_ABOVE_BELOW)) {
-        $output .= drupal_get_form('comment_controls', $mode, $order, $comments_per_page);
-      }
-
-      $divs = 0;
-      $last_depth = 0;
-      drupal_add_css(drupal_get_path('module', 'comment') .'/comment.css');
-      while ($comment = db_fetch_object($result)) {
-        $comment = drupal_unpack($comment);
-        $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
-        $comment->depth = count(explode('.', $comment->thread)) - 1;
-
-        if ($mode == COMMENT_MODE_THREADED_COLLAPSED || $mode == COMMENT_MODE_THREADED_EXPANDED) {
-          if ($comment->depth > $last_depth) {
-            $divs++;
-            $output .= '<div class="indented">';
-            $last_depth++;
-          }
-          else {
-            while ($comment->depth < $last_depth) {
-              $divs--;
-              $output .= '</div>';
-              $last_depth--;
-            }
-          }
-        }
-
-        if ($mode == COMMENT_MODE_FLAT_COLLAPSED) {
-          $output .= theme('comment_flat_collapsed', $comment);
-        }
-        else if ($mode == COMMENT_MODE_FLAT_EXPANDED) {
-          $output .= theme('comment_flat_expanded', $comment);
-        }
-        else if ($mode == COMMENT_MODE_THREADED_COLLAPSED) {
-          $output .= theme('comment_thread_collapsed', $comment);
-        }
-        else if ($mode == COMMENT_MODE_THREADED_EXPANDED) {
-          $output .= theme('comment_thread_expanded', $comment);
-        }
-      }
-      for ($i = 0; $i < $divs; $i++) {
-        $output .= '</div>';
-      }
-      $output .= theme('pager', NULL, $comments_per_page, 0);
-
-      if (db_num_rows($result) && (variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_BELOW || variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_ABOVE_BELOW)) {
-        $output .= drupal_get_form('comment_controls', $mode, $order, $comments_per_page);
-      }
-    }
-
-    // If enabled, show new comment form.
-    if (user_access('post comments') && node_comment_mode($nid) == COMMENT_NODE_READ_WRITE && (variable_get('comment_form_location', COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_BELOW)) {
-      $output .= comment_form_box(array('nid' => $nid), t('Post new comment'));
+  if ($user->uid) {
+    // Retrieve the timestamp at which the current user last viewed the
+    // specified node.
+    if (!$timestamp) {
+      $timestamp = node_last_viewed($nid);
     }
+    $timestamp = ($timestamp > NODE_NEW_LIMIT ? $timestamp : NODE_NEW_LIMIT);
 
-    $output = theme('comment_wrapper', $output);
-  }
-
-  return $output;
-}
-
-/**
- * Menu callback; delete a comment.
- */
-function comment_delete($cid = NULL) {
-  $comment = db_fetch_object(db_query('SELECT c.*, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = %d', $cid));
-  $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
-
-  $output = '';
-
-  // We'll only delete if the user has confirmed the
-  // deletion using the form in our else clause below.
-  if (is_object($comment) && is_numeric($comment->cid) && $_POST['confirm']) {
-    drupal_set_message(t('The comment and all its replies have been deleted.'));
-
-    // Delete comment and its replies.
-    _comment_delete_thread($comment);
-
-    _comment_update_node_statistics($comment->nid);
-
-    // Clear the cache so an anonymous user sees that his comment was deleted.
-    cache_clear_all();
+    // Use the timestamp to retrieve the number of new comments.
+    $result = db_result(db_query('SELECT COUNT(c.cid) FROM {node} n INNER JOIN {comments} c ON n.nid = c.nid WHERE n.nid = %d AND timestamp > %d AND c.status = %d', $nid, $timestamp, COMMENT_PUBLISHED));
 
-    drupal_goto("node/$comment->nid");
-  }
-  else if (is_object($comment) && is_numeric($comment->cid)) {
-    $output = drupal_get_form('comment_confirm_delete', $comment->subject, $comment->nid);
+    return $result;
   }
   else {
-    drupal_set_message(t('The comment no longer exists.'));
+    return 0;
   }
 
-  return $output;
-}
-
-function comment_confirm_delete($subject, $nid) {
-  return confirm_form(
-    array(),
-    t('Are you sure you want to delete the comment %title?', array('%title' => $subject)),
-    'node/'. $nid,
-    t('Any replies to this comment will be lost. This action cannot be undone.'),
-    t('Delete'),
-    t('Cancel'));
 }
-
-/**
- * Comment operations. We offer different update operations depending on
- * which comment administration page we're on.
- */
-function comment_operations($action = NULL) {
-  if ($action == 'publish') {
-    $operations = array(
-      'publish' => array(t('Publish the selected comments'), 'UPDATE {comments} SET status = '. COMMENT_PUBLISHED .' WHERE cid = %d'),
-      'delete' => array(t('Delete the selected comments'), '')
-    );
-  }
-  else if ($action == 'unpublish') {
-    $operations = array(
-      'unpublish' => array(t('Unpublish the selected comments'), 'UPDATE {comments} SET status = '. COMMENT_NOT_PUBLISHED .' WHERE cid = %d'),
-      'delete' => array(t('Delete the selected comments'), '')
-    );
-  }
-  else {
-    $operations = array(
-      'publish' => array(t('Publish the selected comments'), 'UPDATE {comments} SET status = '. COMMENT_PUBLISHED .' WHERE cid = %d'),
-      'unpublish' => array(t('Unpublish the selected comments'), 'UPDATE {comments} SET status = '. COMMENT_NOT_PUBLISHED .' WHERE cid = %d'),
-      'delete' => array(t('Delete the selected comments'), '')
-    );
-  }
-  return $operations;
-}
-
-/**
- * Menu callback; present an administrative comment listing.
- */
-function comment_admin($type = 'new') {
-  $edit = $_POST;
-
-  if (isset($edit['operation']) && ($edit['operation'] == 'delete') && $edit['comments']) {
-    return drupal_get_form('comment_multiple_delete_confirm');
-  }
-  else {
-    return drupal_get_form('comment_admin_overview', $type, arg(4));
-  }
-}
-
-function comment_admin_overview($type = 'new', $arg) {
-  // build an 'Update options' form
-  $form['options'] = array(
-    '#type' => 'fieldset', '#title' => t('Update options'),
-    '#prefix' => '<div class="container-inline">', '#suffix' => '</div>'
-  );
-  $options = array();
-  foreach (comment_operations($arg == 'approval' ? 'publish' : 'unpublish') as $key => $value) {
-    $options[$key] = $value[0];
-  }
-  $form['options']['operation'] = array('#type' => 'select', '#options' => $options, '#default_value' => 'publish');
-  $form['options']['submit'] = array('#type' => 'submit', '#value' => t('Update'));
-
-  // load the comments that we want to display
-  $status = ($type == 'approval') ? COMMENT_NOT_PUBLISHED : COMMENT_PUBLISHED;
-  $form['header'] = array('#type' => 'value', '#value' => array(
-    theme('table_select_header_cell'),
-    array('data' => t('Subject'), 'field' => 'subject'),
-    array('data' => t('Author'), 'field' => 'name'),
-    array('data' => t('Time'), 'field' => 'timestamp', 'sort' => 'desc'),
-    array('data' => t('Operations'))
-  ));
-  $result = pager_query('SELECT c.subject, c.nid, c.cid, c.comment, c.timestamp, c.status, c.name, c.homepage, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.status = %d'. tablesort_sql($form['header']['#value']), 50, 0, NULL, $status);
-
-  // build a table listing the appropriate comments
-  $destination = drupal_get_destination();
-  while ($comment = db_fetch_object($result)) {
-    $comments[$comment->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['username'][$comment->cid] = array('#value' => theme('username', $comment));
-    $form['timestamp'][$comment->cid] = array('#value' => format_date($comment->timestamp, 'small'));
-    $form['operations'][$comment->cid] = array('#value' => l(t('edit'), 'comment/edit/'. $comment->cid, array('query' => $destination)));
-  }
-  $form['comments'] = array('#type' => 'checkboxes', '#options' => isset($comments) ? $comments: array());
-  $form['pager'] = array('#value' => theme('pager', NULL, 50, 0));
-  return $form;
-}
-
-/**
- * We can't execute any 'Update options' if no comments were selected.
- */
-function comment_admin_overview_validate($form_id, $form_values) {
-  $form_values['comments'] = array_diff($form_values['comments'], array(0));
-  if (count($form_values['comments']) == 0) {
-    form_set_error('', t('Please select one or more comments to perform the update on.'));
-    drupal_goto('admin/content/comment');
-  }
-}
-
-/**
- * Execute the chosen 'Update option' on the selected comments, such as
- * publishing, unpublishing or deleting.
- */
-function comment_admin_overview_submit($form_id, $form_values) {
-  $operations = comment_operations();
-  if ($operations[$form_values['operation']][1]) {
-    // extract the appropriate database query operation
-    $query = $operations[$form_values['operation']][1];
-    foreach ($form_values['comments'] as $cid => $value) {
-      if ($value) {
-        // perform the update action, then refresh node statistics
-        db_query($query, $cid);
-        $comment = _comment_load($cid);
-        _comment_update_node_statistics($comment->nid);
-        // Allow modules to respond to the updating of a comment.
-        comment_invoke_comment($comment, $form_values['operation']);
-        // Add an entry to the watchdog log.
-        watchdog('content', 'Comment: updated %subject.', array('%subject' => $comment->subject), WATCHDOG_NOTICE, l(t('view'), 'node/'. $comment->nid, array('fragment' => 'comment-'. $comment->cid)));
-      }
-    }
-    cache_clear_all();
-    drupal_set_message(t('The update has been performed.'));
-    drupal_goto('admin/content/comment');
-  }
-}
-
-function theme_comment_admin_overview($form) {
-  $output = drupal_render($form['options']);
-  if (isset($form['subject']) && is_array($form['subject'])) {
-    foreach (element_children($form['subject']) as $key) {
-      $row = array();
-      $row[] = drupal_render($form['comments'][$key]);
-      $row[] = drupal_render($form['subject'][$key]);
-      $row[] = drupal_render($form['username'][$key]);
-      $row[] = drupal_render($form['timestamp'][$key]);
-      $row[] = drupal_render($form['operations'][$key]);
-      $rows[] = $row;
-    }
-  }
-  else {
-    $rows[] = array(array('data' => t('No comments available.'), 'colspan' => '6'));
-  }
-
-  $output .= theme('table', $form['header']['#value'], $rows);
-  if ($form['pager']['#value']) {
-    $output .= drupal_render($form['pager']);
-  }
-
-  $output .= drupal_render($form);
-
-  return $output;
-}
-
-/**
- * List the selected comments and verify that the admin really wants to delete
- * them.
- */
-function comment_multiple_delete_confirm() {
-  $edit = $_POST;
-
-  $form['comments'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
-  // array_filter() returns only elements with actual values
-  $comment_counter = 0;
-  foreach (array_filter($edit['comments']) as $cid => $value) {
-    $comment = _comment_load($cid);
-    if (is_object($comment) && is_numeric($comment->cid)) {
-      $subject = db_result(db_query('SELECT subject FROM {comments} WHERE cid = %d', $cid));
-      $form['comments'][$cid] = array('#type' => 'hidden', '#value' => $cid, '#prefix' => '<li>', '#suffix' => check_plain($subject) .'</li>');
-      $comment_counter++;
-    }
-  }
-  $form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
-
-  if (!$comment_counter) {
-    drupal_set_message(t('There do not appear to be any comments to delete or your selected comment was deleted by another administrator.'));
-    drupal_goto('admin/content/comment');
-  }
-  else {
-    return confirm_form($form,
-                        t('Are you sure you want to delete these comments and all their children?'),
-                        'admin/content/comment', t('This action cannot be undone.'),
-                        t('Delete comments'), t('Cancel'));
-  }
-}
-
-/**
- * Perform the actual comment deletion.
- */
-function comment_multiple_delete_confirm_submit($form_id, $form_values) {
-  if ($form_values['confirm']) {
-    foreach ($form_values['comments'] as $cid => $value) {
-      $comment = _comment_load($cid);
-      _comment_delete_thread($comment);
-      _comment_update_node_statistics($comment->nid);
-    }
-    cache_clear_all();
-    drupal_set_message(t('The comments have been deleted.'));
-  }
-  drupal_goto('admin/content/comment');
-}
-
-/**
-*** misc functions: helpers, privates, history
-**/
-
-/**
- * Load the entire comment by cid.
- */
-function _comment_load($cid) {
-  return db_fetch_object(db_query('SELECT * FROM {comments} WHERE cid = %d', $cid));
-}
-
-function comment_num_all($nid) {
-  static $cache;
-
-  if (!isset($cache[$nid])) {
-    $cache[$nid] = db_result(db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = %d', $nid));
-  }
-  return $cache[$nid];
-}
-
-function comment_num_replies($pid) {
-  static $cache;
-
-  if (!isset($cache[$pid])) {
-    $cache[$pid] = db_result(db_query('SELECT COUNT(cid) FROM {comments} WHERE pid = %d AND status = %d', $pid, COMMENT_PUBLISHED));
-  }
-
-  return $cache[$pid];
-}
-
-/**
- * get number of new comments for current user and specified node
- *
- * @param $nid node-id to count comments for
- * @param $timestamp time to count from (defaults to time of last user access
- *   to node)
- */
-function comment_num_new($nid, $timestamp = 0) {
-  global $user;
-
-  if ($user->uid) {
-    // Retrieve the timestamp at which the current user last viewed the
-    // specified node.
-    if (!$timestamp) {
-      $timestamp = node_last_viewed($nid);
-    }
-    $timestamp = ($timestamp > NODE_NEW_LIMIT ? $timestamp : NODE_NEW_LIMIT);
-
-    // Use the timestamp to retrieve the number of new comments.
-    $result = db_result(db_query('SELECT COUNT(c.cid) FROM {node} n INNER JOIN {comments} c ON n.nid = c.nid WHERE n.nid = %d AND timestamp > %d AND c.status = %d', $nid, $timestamp, COMMENT_PUBLISHED));
-
-    return $result;
-  }
-  else {
-    return 0;
-  }
-
-}
-
-function comment_validate($edit) {
-  global $user;
-
-  // Invoke other validation handlers
-  comment_invoke_comment($edit, 'validate');
-
-  if (isset($edit['date'])) {
-    // As of PHP 5.1.0, strtotime returns FALSE upon failure instead of -1.
-    if (strtotime($edit['date']) <= 0) {
-      form_set_error('date', t('You have to specify a valid date.'));
-    }
-  }
-  if (isset($edit['author']) && !$account = user_load(array('name' => $edit['author']))) {
-    form_set_error('author', t('You have to specify a valid author.'));
-  }
-
-  // Check validity of name, mail and homepage (if given)
-  if (!$user->uid || isset($edit['is_anonymous'])) {
-    if (variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) > COMMENT_ANONYMOUS_MAYNOT_CONTACT) {
-      if ($edit['name']) {
-        $taken = db_result(db_query("SELECT COUNT(uid) FROM {users} WHERE LOWER(name) = '%s'", $edit['name']), 0);
-
-        if ($taken != 0) {
-          form_set_error('name', t('The name you used belongs to a registered user.'));
-        }
-
-      }
-      else if (variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MUST_CONTACT) {
-        form_set_error('name', t('You have to leave your name.'));
-      }
-
-      if ($edit['mail']) {
-        if (!valid_email_address($edit['mail'])) {
-          form_set_error('mail', t('The e-mail address you specified is not valid.'));
-        }
-      }
-      else if (variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MUST_CONTACT) {
-        form_set_error('mail', t('You have to leave an e-mail address.'));
-      }
-
-      if ($edit['homepage']) {
-        if (!valid_url($edit['homepage'], TRUE)) {
-          form_set_error('homepage', t('The URL of your homepage is not valid. Remember that it must be fully qualified, i.e. of the form <code>http://example.com/directory</code>.'));
-        }
-      }
-    }
-  }
-
-  return $edit;
-}
-
-/*
-** Generate the basic commenting form, for appending to a node or display on a separate page.
-** This is rendered by theme_comment_form.
-*/
-
-function comment_form($edit, $title = NULL) {
-  global $user;
-
-  $op = isset($_POST['op']) ? $_POST['op'] : '';
-
-  if ($user->uid) {
-    if (!empty($edit['cid']) && user_access('administer comments')) {
-      if (!empty($edit['author'])) {
-        $author = $edit['author'];
-      }
-      elseif (!empty($edit['name'])) {
-        $author = $edit['name'];
-      }
-      else {
-        $author = $edit['registered_name'];
-      }
-
-      if (!empty($edit['status'])) {
-        $status = $edit['status'];
-      }
-      else {
-        $status = 0;
-      }
-
-      if (!empty($edit['date'])) {
-        $date = $edit['date'];
-      }
-      else {
-        $date = format_date($edit['timestamp'], 'custom', 'Y-m-d H:i O');
-      }
-
-      $form['admin'] = array(
-        '#type' => 'fieldset',
-        '#title' => t('Administration'),
-        '#collapsible' => TRUE,
-        '#collapsed' => TRUE,
-        '#weight' => -2,
-      );
-
-      if ($edit['registered_name'] != '') {
-        // The comment is by a registered user
-        $form['admin']['author'] = array(
-          '#type' => 'textfield',
-          '#title' => t('Authored by'),
-          '#size' => 30,
-          '#maxlength' => 60,
-          '#autocomplete_path' => 'user/autocomplete',
-          '#default_value' => $author,
-          '#weight' => -1,
-        );
-      }
-      else {
-        // The comment is by an anonymous user
-        $form['is_anonymous'] = array(
-          '#type' => 'value',
-          '#value' => TRUE,
-        );
-        $form['admin']['name'] = array(
-          '#type' => 'textfield',
-          '#title' => t('Authored by'),
-          '#size' => 30,
-          '#maxlength' => 60,
-          '#default_value' => $author,
-          '#weight' => -1,
-        );
-        $form['admin']['mail'] = array(
-          '#type' => 'textfield',
-          '#title' => t('E-mail'),
-          '#maxlength' => 64,
-          '#size' => 30,
-          '#default_value' => $edit['mail'],
-          '#description' => t('The content of this field is kept private and will not be shown publicly.'),
-        );
-
-        $form['admin']['homepage'] = array(
-          '#type' => 'textfield',
-          '#title' => t('Homepage'),
-          '#maxlength' => 255,
-          '#size' => 30,
-          '#default_value' => $edit['homepage'],
-        );
-      }
-
-      $form['admin']['date'] = array('#type' => 'textfield', '#parents' => array('date'), '#title' => t('Authored on'), '#size' => 20, '#maxlength' => 25, '#default_value' => $date, '#weight' => -1);
-
-      $form['admin']['status'] = array('#type' => 'radios', '#parents' => array('status'), '#title' => t('Status'), '#default_value' =>  $status, '#options' => array(t('Published'), t('Not published')), '#weight' => -1);
-
-    }
-    else {
-      $form['_author'] = array('#type' => 'item', '#title' => t('Your name'), '#value' => theme('username', $user)
-      );
-      $form['author'] = array('#type' => 'value', '#value' => $user->name);
-    }
-  }
-  else if (variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MAY_CONTACT) {
-    $form['name'] = array('#type' => 'textfield', '#title' => t('Your name'), '#maxlength' => 60, '#size' => 30, '#default_value' => $edit['name'] ? $edit['name'] : variable_get('anonymous', t('Anonymous'))
-    );
-
-    $form['mail'] = array('#type' => 'textfield', '#title' => t('E-mail'), '#maxlength' => 64, '#size' => 30, '#default_value' => $edit['mail'], '#description' => t('The content of this field is kept private and will not be shown publicly.')
-    );
-
-    $form['homepage'] = array('#type' => 'textfield', '#title' => t('Homepage'), '#maxlength' => 255, '#size' => 30, '#default_value' => $edit['homepage']);
-  }
-  else if (variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MUST_CONTACT) {
-    $form['name'] = array('#type' => 'textfield', '#title' => t('Your name'), '#maxlength' => 60, '#size' => 30, '#default_value' => $edit['name'] ? $edit['name'] : variable_get('anonymous', t('Anonymous')), '#required' => TRUE);
-
-    $form['mail'] = array('#type' => 'textfield', '#title' => t('E-mail'), '#maxlength' => 64, '#size' => 30, '#default_value' => $edit['mail'], '#description' => t('The content of this field is kept private and will not be shown publicly.'), '#required' => TRUE);
-
-    $form['homepage'] = array('#type' => 'textfield', '#title' => t('Homepage'), '#maxlength' => 255, '#size' => 30, '#default_value' => $edit['homepage']);
-  }
-
-  if (variable_get('comment_subject_field', 1) == 1) {
-    $form['subject'] = array('#type' => 'textfield', '#title' => t('Subject'), '#maxlength' => 64, '#default_value' => !empty($edit['subject']) ? $edit['subject'] : '');
-  }
-
-  if (!empty($edit['comment'])) {
-    $default = $edit['comment'];
-  }
-  else {
-    $default = '';
-  }
-
-  $form['comment_filter']['comment'] = array(
-    '#type' => 'textarea',
-    '#title' => t('Comment'),
-    '#rows' => 15,
-    '#default_value' => $default,
-    '#required' => TRUE,
-  );
-  if (!isset($edit['format'])) {
-    $edit['format'] = FILTER_FORMAT_DEFAULT;
-  }
-  $form['comment_filter']['format'] = filter_form($edit['format']);
-
-  $form['cid'] = array('#type' => 'value', '#value' => !empty($edit['cid']) ? $edit['cid'] : NULL);
-  $form['pid'] = array('#type' => 'value', '#value' => $edit['pid']);
-  $form['nid'] = array('#type' => 'value', '#value' => $edit['nid']);
-  $form['uid'] = array('#type' => 'value', '#value' => !empty($edit['uid']) ? $edit['uid'] : NULL);
-
-  $form['preview'] = array('#type' => 'button', '#value' => t('Preview comment'), '#weight' => 19);
-  $form['#token'] = 'comment'. $edit['nid'] . $edit['pid'];
-
-  // Only show post button if preview is optional or if we are in preview mode.
-  // We show the post button in preview mode even if there are form errors so that
-  // optional form elements (e.g., captcha) can be updated in preview mode.
-  if (!form_get_errors() && ((variable_get('comment_preview', COMMENT_PREVIEW_REQUIRED) == COMMENT_PREVIEW_OPTIONAL) || ($op == t('Preview comment')) || ($op == t('Post comment')))) {
-    $form['submit'] = array('#type' => 'submit', '#value' => t('Post comment'), '#weight' => 20);
-  }
-
-  if ($op == t('Preview comment')) {
-    $form['#after_build'] = array('comment_form_add_preview');
-  }
-
-  if (!empty($_REQUEST['destination'])) {
-    $form['#attributes']['destination'] = $_REQUEST['destination'];
-  }
-
-  if (empty($edit['cid']) && empty($edit['pid'])) {
-    $form['#action'] = url('comment/reply/'. $edit['nid']);
-  }
-
-  // Graft in extra form additions
-  $form = array_merge($form, comment_invoke_comment($form, 'form'));
-  return $form;
-}
-
-function comment_form_box($edit, $title = NULL) {
-  return theme('box', $title, drupal_get_form('comment_form', $edit, $title));
-}
-
-function comment_form_add_preview($form, $edit) {
-  global $user;
-
-  drupal_set_title(t('Preview comment'));
-
-  $output = '';
-
-  // Invoke full validation for the form, to protect against cross site
-  // request forgeries (CSRF) and setting arbitrary values for fields such as
-  // the input format. Preview the comment only when form validation does not
-  // set any errors.
-  drupal_validate_form($form['form_id']['#value'], $form);
-  if (!form_get_errors()) {
-    $comment = (object)_comment_form_submit($edit);
-
-    // Attach the user and time information.
-    if ($edit['author']) {
-      $account = user_load(array('name' => $edit['author']));
-    }
-    elseif ($user->uid && !isset($edit['is_anonymous'])) {
-      $account = $user;
-    }
-    if ($account) {
-      $comment->uid = $account->uid;
-      $comment->name = check_plain($account->name);
-    }
-    else {
-      $comment->name = variable_get('anonymous', t('Anonymous'));
-    }
-    $comment->timestamp = !empty($edit['timestamp']) ? $edit['timestamp'] : time();
-    $output .= theme('comment_view', $comment);
-  }
-  $form['comment_preview'] = array(
-    '#value' => $output,
-    '#weight' => -100,
-    '#prefix' => '<div class="preview">',
-    '#suffix' => '</div>',
-  );
-
-  $output = '';
-
-  if ($edit['pid']) {
-    $comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = %d', $edit['pid'], COMMENT_PUBLISHED));
-    $comment = drupal_unpack($comment);
-    $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
-    $output .= theme('comment_view', $comment);
-  }
-  else {
-    $form['#suffix'] = node_view(node_load($edit['nid']));
-    $edit['pid'] = 0;
-  }
-
-  $form['comment_preview_below'] = array('#value' => $output, '#weight' => 100);
-
-  return $form;
-}
-
-function comment_form_validate($form_id, $form_values) {
-  comment_validate($form_values);
-}
-
-function _comment_form_submit($form_values) {
-  if (!isset($form_values['date'])) {
-    $form_values['date'] = 'now';
-  }
-  $form_values['timestamp'] = strtotime($form_values['date']);
-  if (isset($form_values['author'])) {
-    $account = user_load(array('name' => $form_values['author']));
-    $form_values['uid'] = $account->uid;
-    $form_values['name'] = $form_values['author'];
-  }
-  // Validate the comment's subject. If not specified, extract
-  // one from the comment's body.
-  if (trim($form_values['subject']) == '') {
-    // The body may be in any format, so we:
-    // 1) Filter it into HTML
-    // 2) Strip out all HTML tags
-    // 3) Convert entities back to plain-text.
-    // Note: format is checked by check_markup().
-    $form_values['subject'] = trim(truncate_utf8(decode_entities(strip_tags(check_markup($form_values['comment'], $form_values['format']))), 29, TRUE));
-    // Edge cases where the comment body is populated only by HTML tags will
-    // require a default subject.
-    if ($form_values['subject'] == '') {
-      $form_values['subject'] = t('(No subject)');
-    }
-  }
-
-  return $form_values;
-}
-
-function comment_form_submit($form_id, $form_values) {
-  $form_values = _comment_form_submit($form_values);
-  if ($cid = comment_save($form_values)) {
-    return array('node/'. $form_values['nid'], NULL, "comment-$cid");
-  }
-}
-
-/*
-** Renderer or visualization functions this can be optionally
-** overridden by themes.
-*/
-
-function theme_comment_preview($comment, $links = array(), $visible = 1) {
-  $output = '<div class="preview">';
-  $output .= theme('comment_view', $comment, $links, $visible);
-  $output .= '</div>';
-  return $output;
-};
-
-function theme_comment_view($comment, $links = array(), $visible = 1) {
-  static $first_new = TRUE;
-
-  $output = '';
-  $comment->new = node_mark($comment->nid, $comment->timestamp);
-  if ($first_new && $comment->new != MARK_READ) {
-    // Assign the anchor only for the first new comment. This avoids duplicate
-    // id attributes on a page.
-    $first_new = FALSE;
-    $output .= "<a id=\"new\"></a>\n";
-  }
-
-  $output .= "<a id=\"comment-$comment->cid\"></a>\n";
-
-  // Switch to folded/unfolded view of the comment
-  if ($visible) {
-    $comment->comment = check_markup($comment->comment, $comment->format, FALSE);
-
-    // Comment API hook
-    comment_invoke_comment($comment, 'view');
-
-    $output .= theme('comment', $comment, $links);
-  }
-  else {
-    $output .= theme('comment_folded', $comment);
-  }
-
-  return $output;
-}
-
-function comment_controls($mode = COMMENT_MODE_THREADED_EXPANDED, $order = COMMENT_ORDER_NEWEST_FIRST, $comments_per_page = 50) {
-  $form['mode'] = array('#type' => 'select',
-    '#default_value' => $mode,
-    '#options' => _comment_get_modes(),
-    '#weight' => 1,
-  );
-  $form['order'] = array(
-    '#type' => 'select',
-    '#default_value' => $order,
-    '#options' => _comment_get_orders(),
-    '#weight' => 2,
-  );
-  foreach (_comment_per_page() as $i) {
-    $options[$i] = t('!a comments per page', array('!a' => $i));
-  }
-  $form['comments_per_page'] = array('#type' => 'select',
-    '#default_value' => $comments_per_page,
-    '#options' => $options,
-    '#weight' => 3,
-  );
-
-  $form['submit'] = array('#type' => 'submit',
-    '#value' => t('Save settings'),
-    '#weight' => 20,
-  );
-
-  return $form;
-}
-
-function theme_comment_controls($form) {
-  $output .= '<div class="container-inline">';
-  $output .=  drupal_render($form);
-  $output .= '</div>';
-  $output .= '<div class="description">'. t('Select your preferred way to display the comments and click "Save settings" to activate your changes.') .'</div>';
-  return theme('box', t('Comment viewing options'), $output);
-}
-
-function comment_controls_submit($form_id, $form_values) {
-  global $user;
-
-  $mode = $form_values['mode'];
-  $order = $form_values['order'];
-  $comments_per_page = $form_values['comments_per_page'];
-
-  if ($user->uid) {
-    $user = user_save($user, array('mode' => $mode, 'sort' => $order, 'comments_per_page' => $comments_per_page));
-  }
-  else {
-    $_SESSION['comment_mode'] = $mode;
-    $_SESSION['comment_sort'] = $order;
-    $_SESSION['comment_comments_per_page'] = $comments_per_page;
-  }
-}
-
-/**
- * Prepare values for comment.tpl.php
- */
-function template_preprocess_comment(&$variables) {
-  $comment = $variables['comment'];
-  $variables['author']    = theme('username', $comment);
-  $variables['comment']   = $comment;
-  $variables['content']   = $comment->comment;
-  $variables['date']      = format_date($comment->timestamp);
-  $variables['links']     = isset($variables['links']) ? theme('links', $variables['links']) : '';
-  $variables['new']       = $comment->new ? t('new') : '';
-  $variables['picture']   = theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', $comment) : '';
-  $variables['signature'] = $comment->signature;
-  $variables['submitted'] = t('Submitted by !a on @b.',
-                      array('!a' => theme('username', $comment),
-                            '@b' => format_date($comment->timestamp)));
-  $variables['title']     = l($comment->subject, $_GET['q'], array('fragment' => "comment-$comment->cid"));
-}
-
-function theme_comment_folded($comment) {
-  $output  = "<div class=\"comment-folded\">\n";
-  $output .= ' <span class="subject">'. l($comment->subject, comment_node_url() .'/'. $comment->cid, array('fragment' => "comment-$comment->cid")) .' '. theme('mark', $comment->new) .'</span> ';
-  $output .= '<span class="credit">'. t('by') .' '. theme('username', $comment) ."</span>\n";
-  $output .= "</div>\n";
-  return $output;
-}
-
-function theme_comment_flat_collapsed($comment) {
-  return theme('comment_view', $comment, '', 0);
-}
-
-function theme_comment_flat_expanded($comment) {
-  return theme('comment_view', $comment, module_invoke_all('link', 'comment', $comment, 0));
-}
-
-function theme_comment_thread_collapsed($comment) {
-  $output .= theme('comment_view', $comment, '', 0);
-  return $output;
-}
-
-function theme_comment_thread_expanded($comment) {
-  $output = '';
-  $output .= theme('comment_view', $comment, module_invoke_all('link', 'comment', $comment, 0));
-  return $output;
-}
-
-function theme_comment_post_forbidden($nid) {
-  global $user;
-  if ($user->uid) {
-    return t("you can't post comments");
-  }
-  else {
-    // we cannot use drupal_get_destination() because these links sometimes appear on /node and taxo listing pages
-    if (variable_get('comment_form_location', COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_SEPARATE_PAGE) {
-      $destination = "destination=". drupal_urlencode("comment/reply/$nid#comment-form");
-    }
-    else {
-      $destination = "destination=". drupal_urlencode("node/$nid#comment-form");
-    }
-
-    if (variable_get('user_register', 1)) {
-      return t('<a href="@login">Login</a> or <a href="@register">register</a> to post comments', array('@login' => url('user/login', array('query' => $destination)), '@register' => url('user/register', array('query' => $destination))));
-    }
-    else {
-      return t('<a href="@login">Login</a> to post comments', array('@login' => url('user/login', array('query' => $destination))));
-    }
-  }
-}
-
-/**
- * Allow themable wrapping of all comments.
- */
-function theme_comment_wrapper($content) {
-  return '<div id="comments">'. $content .'</div>';
-}
-
-function _comment_delete_thread($comment) {
-  if (!is_object($comment) || !is_numeric($comment->cid)) {
-    watchdog('content', 'Can not delete non-existent comment.', WATCHDOG_WARNING);
-    return;
-  }
-
-  // Delete the comment:
-  db_query('DELETE FROM {comments} WHERE cid = %d', $comment->cid);
-  watchdog('content', 'Comment: deleted %subject.', array('%subject' => $comment->subject));
-
-  comment_invoke_comment($comment, 'delete');
-
-  // Delete the comment's replies
-  $result = db_query('SELECT c.*, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE pid = %d', $comment->cid);
-  while ($comment = db_fetch_object($result)) {
-    $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
-    _comment_delete_thread($comment);
-  }
-}
-
-/**
- * Return an array of viewing modes for comment listings.
- *
- * We can't use a global variable array because the locale system
- * is not initialized yet when the comment module is loaded.
- */
-function _comment_get_modes() {
-  return array(
-    COMMENT_MODE_FLAT_COLLAPSED => t('Flat list - collapsed'),
-    COMMENT_MODE_FLAT_EXPANDED => t('Flat list - expanded'),
-    COMMENT_MODE_THREADED_COLLAPSED => t('Threaded list - collapsed'),
-    COMMENT_MODE_THREADED_EXPANDED => t('Threaded list - expanded')
-  );
-}
-
-/**
- * Return an array of viewing orders for comment listings.
- *
- * We can't use a global variable array because the locale system
- * is not initialized yet when the comment module is loaded.
- */
-function _comment_get_orders() {
-  return array(
-    COMMENT_ORDER_NEWEST_FIRST => t('Date - newest first'),
-    COMMENT_ORDER_OLDEST_FIRST => t('Date - oldest first')
-  );
-}
-
-/**
- * Return an array of "comments per page" settings from which the user
- * can choose.
- */
-function _comment_per_page() {
-  return drupal_map_assoc(array(10, 30, 50, 70, 90, 150, 200, 250, 300));
-}
-
-/**
- * Return a current comment display setting
- *
- * $setting can be one of these: 'mode', 'sort', 'comments_per_page'
- */
-function _comment_get_display_setting($setting) {
-  global $user;
-
-  if (isset($_GET[$setting])) {
-    $value = $_GET[$setting];
-  }
-  else {
-    // get the setting's site default
-    switch ($setting) {
-      case 'mode':
-        $default = variable_get('comment_default_mode', COMMENT_MODE_THREADED_EXPANDED);
-        break;
-      case 'sort':
-        $default = variable_get('comment_default_order', COMMENT_ORDER_NEWEST_FIRST);
-        break;
-      case 'comments_per_page':
-        $default = variable_get('comment_default_per_page', '50');
-    }
-    if (variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_HIDDEN) {
-      // if comment controls are disabled use site default
-      $value = $default;
-    }
-    else {
-      // otherwise use the user's setting if set
-      if ($user->$setting) {
-        $value = $user->$setting;
-      }
-      else if ($_SESSION['comment_'. $setting]) {
-        $value = $_SESSION['comment_'. $setting];
-      }
-      else {
-        $value = $default;
-      }
-    }
-  }
-  return $value;
-}
-
-/**
- * Updates the comment statistics for a given node. This should be called any
- * time a comment is added, deleted, or updated.
- *
- * The following fields are contained in the node_comment_statistics table.
- * - last_comment_timestamp: the timestamp of the last comment for this node or the node create stamp if no comments exist for the node.
- * - last_comment_name: the name of the anonymous poster for the last comment
- * - last_comment_uid: the uid of the poster for the last comment for this node or the node authors uid if no comments exists for the node.
- * - comment_count: the total number of approved/published comments on this node.
- */
-function _comment_update_node_statistics($nid) {
-  $count = db_result(db_query('SELECT COUNT(cid) FROM {comments} WHERE nid = %d AND status = %d', $nid, COMMENT_PUBLISHED));
-
-  // comments exist
-  if ($count > 0) {
-    $last_reply = db_fetch_object(db_query_range('SELECT cid, name, timestamp, uid FROM {comments} WHERE nid = %d AND status = %d ORDER BY cid DESC', $nid, COMMENT_PUBLISHED, 0, 1));
-    db_query("UPDATE {node_comment_statistics} SET comment_count = %d, last_comment_timestamp = %d, last_comment_name = '%s', last_comment_uid = %d WHERE nid = %d", $count, $last_reply->timestamp, $last_reply->uid ? '' : $last_reply->name, $last_reply->uid, $nid);
-  }
-
-  // no comments
-  else {
-    $node = db_fetch_object(db_query("SELECT uid, created FROM {node} WHERE nid = %d", $nid));
-    db_query("UPDATE {node_comment_statistics} SET comment_count = 0, last_comment_timestamp = %d, last_comment_name = '', last_comment_uid = %d WHERE nid = %d", $node->created, $node->uid, $nid);
-  }
-}
-
-/**
- * Invoke a hook_comment() operation in all modules.
- *
- * @param &$comment
- *   A comment object.
- * @param $op
- *   A string containing the name of the comment operation.
- * @return
- *   The returned value of the invoked hooks.
- */
-function comment_invoke_comment(&$comment, $op) {
-  $return = array();
-  foreach (module_implements('comment') as $name) {
-    $function = $name .'_comment';
-    $result = $function($comment, $op);
-    if (isset($result) && is_array($result)) {
-      $return = array_merge($return, $result);
-    }
-    else if (isset($result)) {
-      $return[] = $result;
-    }
-  }
-  return $return;
-}
-
-
-/**
- * Generate vancode.
- *
- * Consists of a leading character indicating length, followed by N digits
- * with a numerical value in base 36. Vancodes can be sorted as strings
- * without messing up numerical order.
- *
- * It goes:
- * 00, 01, 02, ..., 0y, 0z,
- * 110, 111, ... , 1zy, 1zz,
- * 2100, 2101, ..., 2zzy, 2zzz,
- * 31000, 31001, ...
- */
-function int2vancode($i = 0) {
-  $num = base_convert((int)$i, 10, 36);
-  $length = strlen($num);
-  return chr($length + ord('0') - 1) . $num;
-}
-
-/**
- * Decode vancode back to an integer.
- */
-function vancode2int($c = '00') {
-  return base_convert(substr($c, 1), 36, 10);
-}
-
Index: modules/comment/comment.pages.inc
===================================================================
RCS file: modules/comment/comment.pages.inc
diff -N modules/comment/comment.pages.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/comment/comment.pages.inc	30 Apr 2007 07:06:42 -0000
@@ -0,0 +1,1461 @@
+<?php
+// $Id: $
+
+/**
+ * @file
+ * Enables users to comment on published content.
+ *
+ * When enabled, the Drupal comment module creates a discussion
+ * board for each Drupal node. Users can post comments to discuss
+ * a forum topic, weblog post, story, collaborative book page, etc.
+ */
+
+
+/**
+ * Menu callback; presents the comment settings page.
+ */
+function comment_admin_settings() {
+  $form['viewing_options'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Viewing options'),
+    '#collapsible' => TRUE,
+  );
+
+  $form['viewing_options']['comment_default_mode'] = array(
+    '#type' => 'radios',
+    '#title' => t('Default display mode'),
+    '#default_value' => variable_get('comment_default_mode', COMMENT_MODE_THREADED_EXPANDED),
+    '#options' => _comment_get_modes(),
+    '#description' => t('The default view for comments. Expanded views display the body of the comment. Threaded views keep replies together.'),
+  );
+
+  $form['viewing_options']['comment_default_order'] = array(
+    '#type' => 'radios',
+    '#title' => t('Default display order'),
+    '#default_value' => variable_get('comment_default_order', COMMENT_ORDER_NEWEST_FIRST),
+    '#options' => _comment_get_orders(),
+    '#description' => t('The default sorting for new users and anonymous users while viewing comments. These users may change their view using the comment control panel. For registered users, this change is remembered as a persistent user preference.'),
+  );
+
+  $form['viewing_options']['comment_default_per_page'] = array(
+    '#type' => 'select',
+    '#title' => t('Default comments per page'),
+    '#default_value' => variable_get('comment_default_per_page', 50),
+    '#options' => _comment_per_page(),
+    '#description' => t('Default number of comments for each page: more comments are distributed in several pages.'),
+  );
+
+  $form['viewing_options']['comment_controls'] = array(
+    '#type' => 'radios',
+    '#title' => t('Comment controls'),
+    '#default_value' => variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN),
+    '#options' => array(
+      t('Display above the comments'),
+      t('Display below the comments'),
+      t('Display above and below the comments'),
+      t('Do not display')),
+    '#description' => t('Position of the comment controls box. The comment controls let the user change the default display mode and display order of comments.'),
+  );
+
+  $form['posting_settings'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Posting settings'),
+    '#collapsible' => TRUE,
+  );
+
+  $form['posting_settings']['comment_anonymous'] = array(
+    '#type' => 'radios',
+    '#title' => t('Anonymous commenting'),
+    '#default_value' => variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT),
+    '#options' => array(
+      COMMENT_ANONYMOUS_MAYNOT_CONTACT => t('Anonymous posters may not enter their contact information'),
+      COMMENT_ANONYMOUS_MAY_CONTACT => t('Anonymous posters may leave their contact information'),
+      COMMENT_ANONYMOUS_MUST_CONTACT => t('Anonymous posters must leave their contact information')),
+    '#description' => t('This option is enabled when anonymous users have permission to post comments on the <a href="@url">permissions page</a>.', array('@url' => url('admin/user/access', array('fragment' => 'module-comment')))),
+  );
+  if (!user_access('post comments', user_load(array('uid' => 0)))) {
+    $form['posting_settings']['comment_anonymous']['#disabled'] = TRUE;
+  }
+
+  $form['posting_settings']['comment_subject_field'] = array(
+    '#type' => 'radios',
+    '#title' => t('Comment subject field'),
+    '#default_value' => variable_get('comment_subject_field', 1),
+    '#options' => array(t('Disabled'), t('Enabled')),
+    '#description' => t('Can users provide a unique subject for their comments?'),
+  );
+
+  $form['posting_settings']['comment_preview'] = array(
+    '#type' => 'radios',
+    '#title' => t('Preview comment'),
+    '#default_value' => variable_get('comment_preview', COMMENT_PREVIEW_REQUIRED),
+    '#options' => array(t('Optional'), t('Required')),
+  );
+
+  $form['posting_settings']['comment_form_location'] = array(
+    '#type' => 'radios',
+    '#title' => t('Location of comment submission form'),
+    '#default_value' => variable_get('comment_form_location', COMMENT_FORM_SEPARATE_PAGE),
+    '#options' => array(t('Display on separate page'), t('Display below post or comments')),
+  );
+
+  return system_settings_form($form);
+}
+
+/**
+ * This is *not* a hook_access() implementation. This function is called
+ * to determine whether the current user has access to a particular comment.
+ *
+ * Authenticated users can edit their comments as long they have not been
+ * replied to. This prevents people from changing or revising their
+ * statements based on the replies to their posts.
+ */
+function comment_access($op, $comment) {
+  global $user;
+
+  if ($op == 'edit') {
+    return ($user->uid && $user->uid == $comment->uid && comment_num_replies($comment->cid) == 0) || user_access('administer comments');
+  }
+}
+
+function comment_node_url() {
+  return arg(0) .'/'. arg(1);
+}
+
+function comment_edit($cid) {
+  global $user;
+
+  $comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d', $cid));
+  $comment = drupal_unpack($comment);
+  $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
+  if (comment_access('edit', $comment)) {
+    return comment_form_box((array)$comment);
+  }
+  else {
+    drupal_access_denied();
+  }
+}
+
+/**
+ * This function is responsible for generating a comment reply form.
+ * There are several cases that have to be handled, including:
+ *   - replies to comments
+ *   - replies to nodes
+ *   - attempts to reply to nodes that can no longer accept comments
+ *   - respecting access permissions ('access comments', 'post comments', etc.)
+ *
+ * The node or comment that is being replied to must appear above the comment
+ * form to provide the user context while authoring the comment.
+ *
+ * @param $node
+ *   Every comment belongs to a node. This is that node.
+ * @param $pid
+ *   Some comments are replies to other comments. In those cases, $pid is the parent
+ *   comment's cid.
+ *
+ * @return $output
+ *   The rendered parent node or comment plus the new comment form.
+ */
+function comment_reply($node, $pid = NULL) {
+  // Set the breadcrumb trail.
+  menu_set_location(array(array('path' => "node/$node->nid", 'title' => $node->title), array('path' => "comment/reply/$node->nid")));
+
+  $op = isset($_POST['op']) ? $_POST['op'] : '';
+
+  $output = '';
+
+  if (user_access('access comments')) {
+    // The user is previewing a comment prior to submitting it.
+    if ($op == t('Preview comment')) {
+      if (user_access('post comments')) {
+        $output .= comment_form_box(array('pid' => $pid, 'nid' => $node->nid), NULL);
+      }
+      else {
+        drupal_set_message(t('You are not authorized to post comments.'), 'error');
+        drupal_goto("node/$node->nid");
+      }
+    }
+    else {
+      // $pid indicates that this is a reply to a comment.
+      if ($pid) {
+        // load the comment whose cid = $pid
+        if ($comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = %d', $pid, COMMENT_PUBLISHED))) {
+          // If that comment exists, make sure that the current comment and the parent comment both
+          // belong to the same parent node.
+          if ($comment->nid != $node->nid) {
+            // Attempting to reply to a comment not belonging to the current nid.
+            drupal_set_message(t('The comment you are replying to does not exist.'), 'error');
+            drupal_goto("node/$node->nid");
+          }
+          // Display the parent comment
+          $comment = drupal_unpack($comment);
+          $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
+          $output .= theme('comment_view', $comment);
+        }
+        else {
+          drupal_set_message(t('The comment you are replying to does not exist.'), 'error');
+          drupal_goto("node/$node->nid");
+        }
+      }
+      // This is the case where the comment is in response to a node. Display the node.
+      else if (user_access('access content')) {
+        $output .= node_view($node);
+      }
+
+      // Should we show the reply box?
+      if (node_comment_mode($node->nid) != COMMENT_NODE_READ_WRITE) {
+        drupal_set_message(t("This discussion is closed: you can't post new comments."), 'error');
+        drupal_goto("node/$node->nid");
+      }
+      else if (user_access('post comments')) {
+        $output .= comment_form_box(array('pid' => $pid, 'nid' => $node->nid), t('Reply'));
+      }
+      else {
+        drupal_set_message(t('You are not authorized to post comments.'), 'error');
+        drupal_goto("node/$node->nid");
+      }
+    }
+  }
+  else {
+    drupal_set_message(t('You are not authorized to view comments.'), 'error');
+    drupal_goto("node/$node->nid");
+  }
+
+  return $output;
+}
+
+/**
+ * Accepts a submission of new or changed comment content.
+ *
+ * @param $edit
+ *   A comment array.
+ *
+ * @return
+ *   If the comment is successfully saved the comment ID is returned. If the comment
+ *   is not saved, FALSE is returned.
+ */
+function comment_save($edit) {
+  global $user;
+  if (user_access('post comments') && (user_access('administer comments') || node_comment_mode($edit['nid']) == COMMENT_NODE_READ_WRITE)) {
+    if (!form_get_errors()) {
+      if ($edit['cid']) {
+        // Update the comment in the database.
+        db_query("UPDATE {comments} SET status = %d, timestamp = %d, subject = '%s', comment = '%s', format = %d, uid = %d, name = '%s', mail = '%s', homepage = '%s' WHERE cid = %d", $edit['status'], $edit['timestamp'], $edit['subject'], $edit['comment'], $edit['format'], $edit['uid'], $edit['name'], $edit['mail'], $edit['homepage'], $edit['cid']);
+
+        _comment_update_node_statistics($edit['nid']);
+
+        // Allow modules to respond to the updating of a comment.
+        comment_invoke_comment($edit, 'update');
+
+        // Add an entry to the watchdog log.
+        watchdog('content', 'Comment: updated %subject.', array('%subject' => $edit['subject']), WATCHDOG_NOTICE, l(t('view'), 'node/'. $edit['nid'], array('fragment' => 'comment-'. $edit['cid'])));
+      }
+      else {
+        // Check for duplicate comments. Note that we have to use the
+        // validated/filtered data to perform such check.
+        $duplicate = db_result(db_query("SELECT COUNT(cid) FROM {comments} WHERE pid = %d AND nid = %d AND subject = '%s' AND comment = '%s'", $edit['pid'], $edit['nid'], $edit['subject'], $edit['comment']), 0);
+        if ($duplicate != 0) {
+          watchdog('content', 'Comment: duplicate %subject.', array('%subject' => $edit['subject']), WATCHDOG_WARNING);
+        }
+
+        // Add the comment to database.
+        $status = user_access('post comments without approval') ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED;
+        $roles = variable_get('comment_roles', array());
+        $score = 0;
+
+        foreach (array_intersect(array_keys($roles), array_keys($user->roles)) as $rid) {
+          $score = max($roles[$rid], $score);
+        }
+
+        $users = serialize(array(0 => $score));
+
+        // Here we are building the thread field. See the documentation for
+        // comment_render().
+        if ($edit['pid'] == 0) {
+          // This is a comment with no parent comment (depth 0): we start
+          // by retrieving the maximum thread level.
+          $max = db_result(db_query('SELECT MAX(thread) FROM {comments} WHERE nid = %d', $edit['nid']));
+
+          // Strip the "/" from the end of the thread.
+          $max = rtrim($max, '/');
+
+          // Finally, build the thread field for this new comment.
+          $thread = int2vancode(vancode2int($max) + 1) .'/';
+        }
+        else {
+          // This is comment with a parent comment: we increase
+          // the part of the thread value at the proper depth.
+
+          // Get the parent comment:
+          $parent = _comment_load($edit['pid']);
+
+          // Strip the "/" from the end of the parent thread.
+          $parent->thread = (string) rtrim((string) $parent->thread, '/');
+
+          // Get the max value in _this_ thread.
+          $max = db_result(db_query("SELECT MAX(thread) FROM {comments} WHERE thread LIKE '%s.%%' AND nid = %d", $parent->thread, $edit['nid']));
+
+          if ($max == '') {
+            // First child of this parent.
+            $thread = $parent->thread .'.'. int2vancode(0) .'/';
+          }
+          else {
+            // Strip the "/" at the end of the thread.
+            $max = rtrim($max, '/');
+
+            // We need to get the value at the correct depth.
+            $parts = explode('.', $max);
+            $parent_depth = count(explode('.', $parent->thread));
+            $last = $parts[$parent_depth];
+
+            // Finally, build the thread field for this new comment.
+            $thread = $parent->thread .'.'. int2vancode(vancode2int($last) + 1) .'/';
+          }
+        }
+
+        $edit['cid'] = db_next_id('{comments}_cid');
+        $edit['timestamp'] = time();
+
+        if ($edit['uid'] === $user->uid) { // '===' because we want to modify anonymous users too
+          $edit['name'] = $user->name;
+        }
+
+        $edit += array('mail' => '', 'homepage' => '');
+        db_query("INSERT INTO {comments} (cid, nid, pid, uid, subject, comment, format, hostname, timestamp, status, score, users, thread, name, mail, homepage) VALUES (%d, %d, %d, %d, '%s', '%s', %d, '%s', %d, %d, %d, '%s', '%s', '%s', '%s', '%s')", $edit['cid'], $edit['nid'], $edit['pid'], $edit['uid'], $edit['subject'], $edit['comment'], $edit['format'], $_SERVER['REMOTE_ADDR'], $edit['timestamp'], $status, $score, $users, $thread, $edit['name'], $edit['mail'], $edit['homepage']);
+
+        _comment_update_node_statistics($edit['nid']);
+
+        // Tell the other modules a new comment has been submitted.
+        comment_invoke_comment($edit, 'insert');
+
+        // Add an entry to the watchdog log.
+        watchdog('content', 'Comment: added %subject.', array('%subject' => $edit['subject']), WATCHDOG_NOTICE, l(t('view'), 'node/'. $edit['nid'], array('fragment' => 'comment-'. $edit['cid'])));
+      }
+
+      // Clear the cache so an anonymous user can see his comment being added.
+      cache_clear_all();
+
+      // Explain the approval queue if necessary, and then
+      // redirect the user to the node he's commenting on.
+      if ($status == COMMENT_NOT_PUBLISHED) {
+        drupal_set_message(t('Your comment has been queued for moderation by site administrators and will be published after approval.'));
+      }
+      return $edit['cid'];
+    }
+    else {
+      return FALSE;
+    }
+  }
+  else {
+    watchdog('content', 'Comment: unauthorized comment submitted or comment submitted to a closed node %subject.', array('%subject' => $edit['subject']), WATCHDOG_WARNING);
+    drupal_set_message(t('Comment: unauthorized comment submitted or comment submitted to a closed node %subject.', array('%subject' => $edit['subject'])), 'error');
+    return FALSE;
+  }
+}
+
+function comment_links($comment, $return = 1) {
+  global $user;
+
+  $links = array();
+
+  // If we are viewing just this comment, we link back to the node.
+  if ($return) {
+    $links['comment_parent'] = array(
+      'title' => t('parent'),
+      'href' => comment_node_url(),
+      'fragment' => "comment-$comment->cid"
+    );
+  }
+
+  if (node_comment_mode($comment->nid) == COMMENT_NODE_READ_WRITE) {
+    if (user_access('administer comments') && user_access('post comments')) {
+      $links['comment_delete'] = array(
+        'title' => t('delete'),
+        'href' => "comment/delete/$comment->cid"
+      );
+      $links['comment_edit'] = array(
+        'title' => t('edit'),
+        'href' => "comment/edit/$comment->cid"
+      );
+      $links['comment_reply'] = array(
+        'title' => t('reply'),
+        'href' => "comment/reply/$comment->nid/$comment->cid"
+      );
+    }
+    else if (user_access('post comments')) {
+      if (comment_access('edit', $comment)) {
+        $links['comment_edit'] = array(
+          'title' => t('edit'),
+          'href' => "comment/edit/$comment->cid"
+        );
+      }
+      $links['comment_reply'] = array(
+        'title' => t('reply'),
+        'href' => "comment/reply/$comment->nid/$comment->cid"
+      );
+    }
+    else {
+      $links['comment_forbidden']['title'] = theme('comment_post_forbidden', $comment->nid);
+    }
+  }
+
+  return $links;
+}
+
+/**
+ * Renders comment(s).
+ *
+ * @param $node
+ *   The node which comment(s) needs rendering.
+ * @param $cid
+ *   Optional, if given, only one comment is rendered.
+ *
+ * To display threaded comments in the correct order we keep a 'thread' field
+ * and order by that value. This field keeps this data in
+ * a way which is easy to update and convenient to use.
+ *
+ * A "thread" value starts at "1". If we add a child (A) to this comment,
+ * we assign it a "thread" = "1.1". A child of (A) will have "1.1.1". Next
+ * brother of (A) will get "1.2". Next brother of the parent of (A) will get
+ * "2" and so on.
+ *
+ * First of all note that the thread field stores the depth of the comment:
+ * depth 0 will be "X", depth 1 "X.X", depth 2 "X.X.X", etc.
+ *
+ * Now to get the ordering right, consider this example:
+ *
+ * 1
+ * 1.1
+ * 1.1.1
+ * 1.2
+ * 2
+ *
+ * If we "ORDER BY thread ASC" we get the above result, and this is the
+ * natural order sorted by time. However, if we "ORDER BY thread DESC"
+ * we get:
+ *
+ * 2
+ * 1.2
+ * 1.1.1
+ * 1.1
+ * 1
+ *
+ * Clearly, this is not a natural way to see a thread, and users will get
+ * confused. The natural order to show a thread by time desc would be:
+ *
+ * 2
+ * 1
+ * 1.2
+ * 1.1
+ * 1.1.1
+ *
+ * which is what we already did before the standard pager patch. To achieve
+ * this we simply add a "/" at the end of each "thread" value. This way out
+ * thread fields will look like depicted below:
+ *
+ * 1/
+ * 1.1/
+ * 1.1.1/
+ * 1.2/
+ * 2/
+ *
+ * we add "/" since this char is, in ASCII, higher than every number, so if
+ * now we "ORDER BY thread DESC" we get the correct order. However this would
+ * spoil the reverse ordering, "ORDER BY thread ASC" -- here, we do not need
+ * to consider the trailing "/" so we use a substring only.
+ */
+function comment_render($node, $cid = 0) {
+  global $user;
+
+  $output = '';
+
+  if (user_access('access comments')) {
+    // Pre-process variables.
+    $nid = $node->nid;
+    if (empty($nid)) {
+      $nid = 0;
+    }
+
+    $mode = _comment_get_display_setting('mode');
+    $order = _comment_get_display_setting('sort');
+    $comments_per_page = _comment_get_display_setting('comments_per_page');
+
+    if ($cid) {
+      // Single comment view.
+      $query = 'SELECT c.cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.signature, u.picture, u.data, c.score, c.users, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d';
+      $query_args = array($cid);
+      if (!user_access('administer comments')) {
+        $query .= ' AND c.status = %d';
+        $query_args[] = COMMENT_PUBLISHED;
+      }
+
+      $result = db_query($query, $query_args);
+
+      if ($comment = db_fetch_object($result)) {
+        $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
+        $links = module_invoke_all('link', 'comment', $comment, 1);
+        drupal_alter('link', $links, $node);
+
+        $output .= theme('comment_view', $comment, $links);
+      }
+    }
+    else {
+      // Multiple comment view
+      $query_count = 'SELECT COUNT(*) FROM {comments} WHERE nid = %d';
+      $query = 'SELECT c.cid as cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.signature, u.picture, u.data, c.score, c.users, c.thread, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.nid = %d';
+
+      $query_args = array($nid);
+      if (!user_access('administer comments')) {
+        $query .= ' AND c.status = %d';
+        $query_count .= ' AND status = %d';
+        $query_args[] = COMMENT_PUBLISHED;
+      }
+
+      if ($order == COMMENT_ORDER_NEWEST_FIRST) {
+        if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) {
+          $query .= ' ORDER BY c.timestamp DESC';
+        }
+        else {
+          $query .= ' ORDER BY c.thread DESC';
+        }
+      }
+      else if ($order == COMMENT_ORDER_OLDEST_FIRST) {
+        if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) {
+          $query .= ' ORDER BY c.timestamp';
+        }
+        else {
+
+          /*
+          ** See comment above. Analysis learns that this doesn't cost
+          ** too much. It scales much much better than having the whole
+          ** comment structure.
+          */
+
+          $query .= ' ORDER BY SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))';
+        }
+      }
+
+      // Start a form, for use with comment control.
+      $result = pager_query($query, $comments_per_page, 0, $query_count, $query_args);
+      if (db_num_rows($result) && (variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_ABOVE || variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_ABOVE_BELOW)) {
+        $output .= drupal_get_form('comment_controls', $mode, $order, $comments_per_page);
+      }
+
+      $divs = 0;
+      $last_depth = 0;
+      drupal_add_css(drupal_get_path('module', 'comment') .'/comment.css');
+      while ($comment = db_fetch_object($result)) {
+        $comment = drupal_unpack($comment);
+        $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
+        $comment->depth = count(explode('.', $comment->thread)) - 1;
+
+        if ($mode == COMMENT_MODE_THREADED_COLLAPSED || $mode == COMMENT_MODE_THREADED_EXPANDED) {
+          if ($comment->depth > $last_depth) {
+            $divs++;
+            $output .= '<div class="indented">';
+            $last_depth++;
+          }
+          else {
+            while ($comment->depth < $last_depth) {
+              $divs--;
+              $output .= '</div>';
+              $last_depth--;
+            }
+          }
+        }
+
+        if ($mode == COMMENT_MODE_FLAT_COLLAPSED) {
+          $output .= theme('comment_flat_collapsed', $comment);
+        }
+        else if ($mode == COMMENT_MODE_FLAT_EXPANDED) {
+          $output .= theme('comment_flat_expanded', $comment);
+        }
+        else if ($mode == COMMENT_MODE_THREADED_COLLAPSED) {
+          $output .= theme('comment_thread_collapsed', $comment);
+        }
+        else if ($mode == COMMENT_MODE_THREADED_EXPANDED) {
+          $output .= theme('comment_thread_expanded', $comment);
+        }
+      }
+      for ($i = 0; $i < $divs; $i++) {
+        $output .= '</div>';
+      }
+      $output .= theme('pager', NULL, $comments_per_page, 0);
+
+      if (db_num_rows($result) && (variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_BELOW || variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_ABOVE_BELOW)) {
+        $output .= drupal_get_form('comment_controls', $mode, $order, $comments_per_page);
+      }
+    }
+
+    // If enabled, show new comment form.
+    if (user_access('post comments') && node_comment_mode($nid) == COMMENT_NODE_READ_WRITE && (variable_get('comment_form_location', COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_BELOW)) {
+      $output .= comment_form_box(array('nid' => $nid), t('Post new comment'));
+    }
+
+    $output = theme('comment_wrapper', $output);
+  }
+
+  return $output;
+}
+
+/**
+ * Menu callback; delete a comment.
+ */
+function comment_delete($cid = NULL) {
+  $comment = db_fetch_object(db_query('SELECT c.*, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = %d', $cid));
+  $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
+
+  $output = '';
+
+  // We'll only delete if the user has confirmed the
+  // deletion using the form in our else clause below.
+  if (is_object($comment) && is_numeric($comment->cid) && $_POST['confirm']) {
+    drupal_set_message(t('The comment and all its replies have been deleted.'));
+
+    // Delete comment and its replies.
+    _comment_delete_thread($comment);
+
+    _comment_update_node_statistics($comment->nid);
+
+    // Clear the cache so an anonymous user sees that his comment was deleted.
+    cache_clear_all();
+
+    drupal_goto("node/$comment->nid");
+  }
+  else if (is_object($comment) && is_numeric($comment->cid)) {
+    $output = drupal_get_form('comment_confirm_delete', $comment->subject, $comment->nid);
+  }
+  else {
+    drupal_set_message(t('The comment no longer exists.'));
+  }
+
+  return $output;
+}
+
+function comment_confirm_delete($subject, $nid) {
+  return confirm_form(
+    array(),
+    t('Are you sure you want to delete the comment %title?', array('%title' => $subject)),
+    'node/'. $nid,
+    t('Any replies to this comment will be lost. This action cannot be undone.'),
+    t('Delete'),
+    t('Cancel'));
+}
+
+/**
+ * Comment operations. We offer different update operations depending on
+ * which comment administration page we're on.
+ */
+function comment_operations($action = NULL) {
+  if ($action == 'publish') {
+    $operations = array(
+      'publish' => array(t('Publish the selected comments'), 'UPDATE {comments} SET status = '. COMMENT_PUBLISHED .' WHERE cid = %d'),
+      'delete' => array(t('Delete the selected comments'), '')
+    );
+  }
+  else if ($action == 'unpublish') {
+    $operations = array(
+      'unpublish' => array(t('Unpublish the selected comments'), 'UPDATE {comments} SET status = '. COMMENT_NOT_PUBLISHED .' WHERE cid = %d'),
+      'delete' => array(t('Delete the selected comments'), '')
+    );
+  }
+  else {
+    $operations = array(
+      'publish' => array(t('Publish the selected comments'), 'UPDATE {comments} SET status = '. COMMENT_PUBLISHED .' WHERE cid = %d'),
+      'unpublish' => array(t('Unpublish the selected comments'), 'UPDATE {comments} SET status = '. COMMENT_NOT_PUBLISHED .' WHERE cid = %d'),
+      'delete' => array(t('Delete the selected comments'), '')
+    );
+  }
+  return $operations;
+}
+
+/**
+ * Menu callback; present an administrative comment listing.
+ */
+function comment_admin($type = 'new') {
+  $edit = $_POST;
+
+  if (isset($edit['operation']) && ($edit['operation'] == 'delete') && $edit['comments']) {
+    return drupal_get_form('comment_multiple_delete_confirm');
+  }
+  else {
+    return drupal_get_form('comment_admin_overview', $type, arg(4));
+  }
+}
+
+function comment_admin_overview($type = 'new', $arg) {
+  // build an 'Update options' form
+  $form['options'] = array(
+    '#type' => 'fieldset', '#title' => t('Update options'),
+    '#prefix' => '<div class="container-inline">', '#suffix' => '</div>'
+  );
+  $options = array();
+  foreach (comment_operations($arg == 'approval' ? 'publish' : 'unpublish') as $key => $value) {
+    $options[$key] = $value[0];
+  }
+  $form['options']['operation'] = array('#type' => 'select', '#options' => $options, '#default_value' => 'publish');
+  $form['options']['submit'] = array('#type' => 'submit', '#value' => t('Update'));
+
+  // load the comments that we want to display
+  $status = ($type == 'approval') ? COMMENT_NOT_PUBLISHED : COMMENT_PUBLISHED;
+  $form['header'] = array('#type' => 'value', '#value' => array(
+    theme('table_select_header_cell'),
+    array('data' => t('Subject'), 'field' => 'subject'),
+    array('data' => t('Author'), 'field' => 'name'),
+    array('data' => t('Time'), 'field' => 'timestamp', 'sort' => 'desc'),
+    array('data' => t('Operations'))
+  ));
+  $result = pager_query('SELECT c.subject, c.nid, c.cid, c.comment, c.timestamp, c.status, c.name, c.homepage, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.status = %d'. tablesort_sql($form['header']['#value']), 50, 0, NULL, $status);
+
+  // build a table listing the appropriate comments
+  $destination = drupal_get_destination();
+  while ($comment = db_fetch_object($result)) {
+    $comments[$comment->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['username'][$comment->cid] = array('#value' => theme('username', $comment));
+    $form['timestamp'][$comment->cid] = array('#value' => format_date($comment->timestamp, 'small'));
+    $form['operations'][$comment->cid] = array('#value' => l(t('edit'), 'comment/edit/'. $comment->cid, array('query' => $destination)));
+  }
+  $form['comments'] = array('#type' => 'checkboxes', '#options' => isset($comments) ? $comments: array());
+  $form['pager'] = array('#value' => theme('pager', NULL, 50, 0));
+  return $form;
+}
+
+/**
+ * We can't execute any 'Update options' if no comments were selected.
+ */
+function comment_admin_overview_validate($form_id, $form_values) {
+  $form_values['comments'] = array_diff($form_values['comments'], array(0));
+  if (count($form_values['comments']) == 0) {
+    form_set_error('', t('Please select one or more comments to perform the update on.'));
+    drupal_goto('admin/content/comment');
+  }
+}
+
+/**
+ * Execute the chosen 'Update option' on the selected comments, such as
+ * publishing, unpublishing or deleting.
+ */
+function comment_admin_overview_submit($form_id, $form_values) {
+  $operations = comment_operations();
+  if ($operations[$form_values['operation']][1]) {
+    // extract the appropriate database query operation
+    $query = $operations[$form_values['operation']][1];
+    foreach ($form_values['comments'] as $cid => $value) {
+      if ($value) {
+        // perform the update action, then refresh node statistics
+        db_query($query, $cid);
+        $comment = _comment_load($cid);
+        _comment_update_node_statistics($comment->nid);
+        // Allow modules to respond to the updating of a comment.
+        comment_invoke_comment($comment, $form_values['operation']);
+        // Add an entry to the watchdog log.
+        watchdog('content', 'Comment: updated %subject.', array('%subject' => $comment->subject), WATCHDOG_NOTICE, l(t('view'), 'node/'. $comment->nid, array('fragment' => 'comment-'. $comment->cid)));
+      }
+    }
+    cache_clear_all();
+    drupal_set_message(t('The update has been performed.'));
+    drupal_goto('admin/content/comment');
+  }
+}
+
+function theme_comment_admin_overview($form) {
+  $output = drupal_render($form['options']);
+  if (isset($form['subject']) && is_array($form['subject'])) {
+    foreach (element_children($form['subject']) as $key) {
+      $row = array();
+      $row[] = drupal_render($form['comments'][$key]);
+      $row[] = drupal_render($form['subject'][$key]);
+      $row[] = drupal_render($form['username'][$key]);
+      $row[] = drupal_render($form['timestamp'][$key]);
+      $row[] = drupal_render($form['operations'][$key]);
+      $rows[] = $row;
+    }
+  }
+  else {
+    $rows[] = array(array('data' => t('No comments available.'), 'colspan' => '6'));
+  }
+
+  $output .= theme('table', $form['header']['#value'], $rows);
+  if ($form['pager']['#value']) {
+    $output .= drupal_render($form['pager']);
+  }
+
+  $output .= drupal_render($form);
+
+  return $output;
+}
+
+/**
+ * List the selected comments and verify that the admin really wants to delete
+ * them.
+ */
+function comment_multiple_delete_confirm() {
+  $edit = $_POST;
+
+  $form['comments'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
+  // array_filter() returns only elements with actual values
+  $comment_counter = 0;
+  foreach (array_filter($edit['comments']) as $cid => $value) {
+    $comment = _comment_load($cid);
+    if (is_object($comment) && is_numeric($comment->cid)) {
+      $subject = db_result(db_query('SELECT subject FROM {comments} WHERE cid = %d', $cid));
+      $form['comments'][$cid] = array('#type' => 'hidden', '#value' => $cid, '#prefix' => '<li>', '#suffix' => check_plain($subject) .'</li>');
+      $comment_counter++;
+    }
+  }
+  $form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
+
+  if (!$comment_counter) {
+    drupal_set_message(t('There do not appear to be any comments to delete or your selected comment was deleted by another administrator.'));
+    drupal_goto('admin/content/comment');
+  }
+  else {
+    return confirm_form($form,
+                        t('Are you sure you want to delete these comments and all their children?'),
+                        'admin/content/comment', t('This action cannot be undone.'),
+                        t('Delete comments'), t('Cancel'));
+  }
+}
+
+/**
+ * Perform the actual comment deletion.
+ */
+function comment_multiple_delete_confirm_submit($form_id, $form_values) {
+  if ($form_values['confirm']) {
+    foreach ($form_values['comments'] as $cid => $value) {
+      $comment = _comment_load($cid);
+      _comment_delete_thread($comment);
+      _comment_update_node_statistics($comment->nid);
+    }
+    cache_clear_all();
+    drupal_set_message(t('The comments have been deleted.'));
+  }
+  drupal_goto('admin/content/comment');
+}
+
+/**
+*** misc functions: helpers, privates, history
+**/
+
+function comment_validate($edit) {
+  global $user;
+
+  // Invoke other validation handlers
+  comment_invoke_comment($edit, 'validate');
+
+  if (isset($edit['date'])) {
+    // As of PHP 5.1.0, strtotime returns FALSE upon failure instead of -1.
+    if (strtotime($edit['date']) <= 0) {
+      form_set_error('date', t('You have to specify a valid date.'));
+    }
+  }
+  if (isset($edit['author']) && !$account = user_load(array('name' => $edit['author']))) {
+    form_set_error('author', t('You have to specify a valid author.'));
+  }
+
+  // Check validity of name, mail and homepage (if given)
+  if (!$user->uid || isset($edit['is_anonymous'])) {
+    if (variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) > COMMENT_ANONYMOUS_MAYNOT_CONTACT) {
+      if ($edit['name']) {
+        $taken = db_result(db_query("SELECT COUNT(uid) FROM {users} WHERE LOWER(name) = '%s'", $edit['name']), 0);
+
+        if ($taken != 0) {
+          form_set_error('name', t('The name you used belongs to a registered user.'));
+        }
+
+      }
+      else if (variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MUST_CONTACT) {
+        form_set_error('name', t('You have to leave your name.'));
+      }
+
+      if ($edit['mail']) {
+        if (!valid_email_address($edit['mail'])) {
+          form_set_error('mail', t('The e-mail address you specified is not valid.'));
+        }
+      }
+      else if (variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MUST_CONTACT) {
+        form_set_error('mail', t('You have to leave an e-mail address.'));
+      }
+
+      if ($edit['homepage']) {
+        if (!valid_url($edit['homepage'], TRUE)) {
+          form_set_error('homepage', t('The URL of your homepage is not valid. Remember that it must be fully qualified, i.e. of the form <code>http://example.com/directory</code>.'));
+        }
+      }
+    }
+  }
+
+  return $edit;
+}
+
+/*
+** Generate the basic commenting form, for appending to a node or display on a separate page.
+** This is rendered by theme_comment_form.
+*/
+
+function comment_form($edit, $title = NULL) {
+  global $user;
+
+  $op = isset($_POST['op']) ? $_POST['op'] : '';
+
+  if ($user->uid) {
+    if (!empty($edit['cid']) && user_access('administer comments')) {
+      if (!empty($edit['author'])) {
+        $author = $edit['author'];
+      }
+      elseif (!empty($edit['name'])) {
+        $author = $edit['name'];
+      }
+      else {
+        $author = $edit['registered_name'];
+      }
+
+      if (!empty($edit['status'])) {
+        $status = $edit['status'];
+      }
+      else {
+        $status = 0;
+      }
+
+      if (!empty($edit['date'])) {
+        $date = $edit['date'];
+      }
+      else {
+        $date = format_date($edit['timestamp'], 'custom', 'Y-m-d H:i O');
+      }
+
+      $form['admin'] = array(
+        '#type' => 'fieldset',
+        '#title' => t('Administration'),
+        '#collapsible' => TRUE,
+        '#collapsed' => TRUE,
+        '#weight' => -2,
+      );
+
+      if ($edit['registered_name'] != '') {
+        // The comment is by a registered user
+        $form['admin']['author'] = array(
+          '#type' => 'textfield',
+          '#title' => t('Authored by'),
+          '#size' => 30,
+          '#maxlength' => 60,
+          '#autocomplete_path' => 'user/autocomplete',
+          '#default_value' => $author,
+          '#weight' => -1,
+        );
+      }
+      else {
+        // The comment is by an anonymous user
+        $form['is_anonymous'] = array(
+          '#type' => 'value',
+          '#value' => TRUE,
+        );
+        $form['admin']['name'] = array(
+          '#type' => 'textfield',
+          '#title' => t('Authored by'),
+          '#size' => 30,
+          '#maxlength' => 60,
+          '#default_value' => $author,
+          '#weight' => -1,
+        );
+        $form['admin']['mail'] = array(
+          '#type' => 'textfield',
+          '#title' => t('E-mail'),
+          '#maxlength' => 64,
+          '#size' => 30,
+          '#default_value' => $edit['mail'],
+          '#description' => t('The content of this field is kept private and will not be shown publicly.'),
+        );
+
+        $form['admin']['homepage'] = array(
+          '#type' => 'textfield',
+          '#title' => t('Homepage'),
+          '#maxlength' => 255,
+          '#size' => 30,
+          '#default_value' => $edit['homepage'],
+        );
+      }
+
+      $form['admin']['date'] = array('#type' => 'textfield', '#parents' => array('date'), '#title' => t('Authored on'), '#size' => 20, '#maxlength' => 25, '#default_value' => $date, '#weight' => -1);
+
+      $form['admin']['status'] = array('#type' => 'radios', '#parents' => array('status'), '#title' => t('Status'), '#default_value' =>  $status, '#options' => array(t('Published'), t('Not published')), '#weight' => -1);
+
+    }
+    else {
+      $form['_author'] = array('#type' => 'item', '#title' => t('Your name'), '#value' => theme('username', $user)
+      );
+      $form['author'] = array('#type' => 'value', '#value' => $user->name);
+    }
+  }
+  else if (variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MAY_CONTACT) {
+    $form['name'] = array('#type' => 'textfield', '#title' => t('Your name'), '#maxlength' => 60, '#size' => 30, '#default_value' => $edit['name'] ? $edit['name'] : variable_get('anonymous', t('Anonymous'))
+    );
+
+    $form['mail'] = array('#type' => 'textfield', '#title' => t('E-mail'), '#maxlength' => 64, '#size' => 30, '#default_value' => $edit['mail'], '#description' => t('The content of this field is kept private and will not be shown publicly.')
+    );
+
+    $form['homepage'] = array('#type' => 'textfield', '#title' => t('Homepage'), '#maxlength' => 255, '#size' => 30, '#default_value' => $edit['homepage']);
+  }
+  else if (variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MUST_CONTACT) {
+    $form['name'] = array('#type' => 'textfield', '#title' => t('Your name'), '#maxlength' => 60, '#size' => 30, '#default_value' => $edit['name'] ? $edit['name'] : variable_get('anonymous', t('Anonymous')), '#required' => TRUE);
+
+    $form['mail'] = array('#type' => 'textfield', '#title' => t('E-mail'), '#maxlength' => 64, '#size' => 30, '#default_value' => $edit['mail'], '#description' => t('The content of this field is kept private and will not be shown publicly.'), '#required' => TRUE);
+
+    $form['homepage'] = array('#type' => 'textfield', '#title' => t('Homepage'), '#maxlength' => 255, '#size' => 30, '#default_value' => $edit['homepage']);
+  }
+
+  if (variable_get('comment_subject_field', 1) == 1) {
+    $form['subject'] = array('#type' => 'textfield', '#title' => t('Subject'), '#maxlength' => 64, '#default_value' => !empty($edit['subject']) ? $edit['subject'] : '');
+  }
+
+  if (!empty($edit['comment'])) {
+    $default = $edit['comment'];
+  }
+  else {
+    $default = '';
+  }
+
+  $form['comment_filter']['comment'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Comment'),
+    '#rows' => 15,
+    '#default_value' => $default,
+    '#required' => TRUE,
+  );
+  if (!isset($edit['format'])) {
+    $edit['format'] = FILTER_FORMAT_DEFAULT;
+  }
+  $form['comment_filter']['format'] = filter_form($edit['format']);
+
+  $form['cid'] = array('#type' => 'value', '#value' => !empty($edit['cid']) ? $edit['cid'] : NULL);
+  $form['pid'] = array('#type' => 'value', '#value' => $edit['pid']);
+  $form['nid'] = array('#type' => 'value', '#value' => $edit['nid']);
+  $form['uid'] = array('#type' => 'value', '#value' => !empty($edit['uid']) ? $edit['uid'] : NULL);
+
+  $form['preview'] = array('#type' => 'button', '#value' => t('Preview comment'), '#weight' => 19);
+  $form['#token'] = 'comment'. $edit['nid'] . $edit['pid'];
+
+  // Only show post button if preview is optional or if we are in preview mode.
+  // We show the post button in preview mode even if there are form errors so that
+  // optional form elements (e.g., captcha) can be updated in preview mode.
+  if (!form_get_errors() && ((variable_get('comment_preview', COMMENT_PREVIEW_REQUIRED) == COMMENT_PREVIEW_OPTIONAL) || ($op == t('Preview comment')) || ($op == t('Post comment')))) {
+    $form['submit'] = array('#type' => 'submit', '#value' => t('Post comment'), '#weight' => 20);
+  }
+
+  if ($op == t('Preview comment')) {
+    $form['#after_build'] = array('comment_form_add_preview');
+  }
+
+  if (!empty($_REQUEST['destination'])) {
+    $form['#attributes']['destination'] = $_REQUEST['destination'];
+  }
+
+  if (empty($edit['cid']) && empty($edit['pid'])) {
+    $form['#action'] = url('comment/reply/'. $edit['nid']);
+  }
+
+  // Graft in extra form additions
+  $form = array_merge($form, comment_invoke_comment($form, 'form'));
+  return $form;
+}
+
+function comment_form_box($edit, $title = NULL) {
+  return theme('box', $title, drupal_get_form('comment_form', $edit, $title));
+}
+
+function comment_form_add_preview($form, $edit) {
+  global $user;
+
+  drupal_set_title(t('Preview comment'));
+
+  $output = '';
+
+  // Invoke full validation for the form, to protect against cross site
+  // request forgeries (CSRF) and setting arbitrary values for fields such as
+  // the input format. Preview the comment only when form validation does not
+  // set any errors.
+  drupal_validate_form($form['form_id']['#value'], $form);
+  if (!form_get_errors()) {
+    $comment = (object)_comment_form_submit($edit);
+
+    // Attach the user and time information.
+    if ($edit['author']) {
+      $account = user_load(array('name' => $edit['author']));
+    }
+    elseif ($user->uid && !isset($edit['is_anonymous'])) {
+      $account = $user;
+    }
+    if ($account) {
+      $comment->uid = $account->uid;
+      $comment->name = check_plain($account->name);
+    }
+    else {
+      $comment->name = variable_get('anonymous', t('Anonymous'));
+    }
+    $comment->timestamp = !empty($edit['timestamp']) ? $edit['timestamp'] : time();
+    $output .= theme('comment_view', $comment);
+  }
+  $form['comment_preview'] = array(
+    '#value' => $output,
+    '#weight' => -100,
+    '#prefix' => '<div class="preview">',
+    '#suffix' => '</div>',
+  );
+
+  $output = '';
+
+  if ($edit['pid']) {
+    $comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = %d', $edit['pid'], COMMENT_PUBLISHED));
+    $comment = drupal_unpack($comment);
+    $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
+    $output .= theme('comment_view', $comment);
+  }
+  else {
+    $form['#suffix'] = node_view(node_load($edit['nid']));
+    $edit['pid'] = 0;
+  }
+
+  $form['comment_preview_below'] = array('#value' => $output, '#weight' => 100);
+
+  return $form;
+}
+
+function comment_form_validate($form_id, $form_values) {
+  comment_validate($form_values);
+}
+
+function _comment_form_submit($form_values) {
+  if (!isset($form_values['date'])) {
+    $form_values['date'] = 'now';
+  }
+  $form_values['timestamp'] = strtotime($form_values['date']);
+  if (isset($form_values['author'])) {
+    $account = user_load(array('name' => $form_values['author']));
+    $form_values['uid'] = $account->uid;
+    $form_values['name'] = $form_values['author'];
+  }
+  // Validate the comment's subject. If not specified, extract
+  // one from the comment's body.
+  if (trim($form_values['subject']) == '') {
+    // The body may be in any format, so we:
+    // 1) Filter it into HTML
+    // 2) Strip out all HTML tags
+    // 3) Convert entities back to plain-text.
+    // Note: format is checked by check_markup().
+    $form_values['subject'] = trim(truncate_utf8(decode_entities(strip_tags(check_markup($form_values['comment'], $form_values['format']))), 29, TRUE));
+    // Edge cases where the comment body is populated only by HTML tags will
+    // require a default subject.
+    if ($form_values['subject'] == '') {
+      $form_values['subject'] = t('(No subject)');
+    }
+  }
+
+  return $form_values;
+}
+
+function comment_form_submit($form_id, $form_values) {
+  $form_values = _comment_form_submit($form_values);
+  if ($cid = comment_save($form_values)) {
+    return array('node/'. $form_values['nid'], NULL, "comment-$cid");
+  }
+}
+
+/*
+** Renderer or visualization functions this can be optionally
+** overridden by themes.
+*/
+
+function theme_comment_preview($comment, $links = array(), $visible = 1) {
+  $output = '<div class="preview">';
+  $output .= theme('comment_view', $comment, $links, $visible);
+  $output .= '</div>';
+  return $output;
+};
+
+function theme_comment_view($comment, $links = array(), $visible = 1) {
+  static $first_new = TRUE;
+
+  $output = '';
+  $comment->new = node_mark($comment->nid, $comment->timestamp);
+  if ($first_new && $comment->new != MARK_READ) {
+    // Assign the anchor only for the first new comment. This avoids duplicate
+    // id attributes on a page.
+    $first_new = FALSE;
+    $output .= "<a id=\"new\"></a>\n";
+  }
+
+  $output .= "<a id=\"comment-$comment->cid\"></a>\n";
+
+  // Switch to folded/unfolded view of the comment
+  if ($visible) {
+    $comment->comment = check_markup($comment->comment, $comment->format, FALSE);
+
+    // Comment API hook
+    comment_invoke_comment($comment, 'view');
+
+    $output .= theme('comment', $comment, $links);
+  }
+  else {
+    $output .= theme('comment_folded', $comment);
+  }
+
+  return $output;
+}
+
+function comment_controls($mode = COMMENT_MODE_THREADED_EXPANDED, $order = COMMENT_ORDER_NEWEST_FIRST, $comments_per_page = 50) {
+  $form['mode'] = array('#type' => 'select',
+    '#default_value' => $mode,
+    '#options' => _comment_get_modes(),
+    '#weight' => 1,
+  );
+  $form['order'] = array(
+    '#type' => 'select',
+    '#default_value' => $order,
+    '#options' => _comment_get_orders(),
+    '#weight' => 2,
+  );
+  foreach (_comment_per_page() as $i) {
+    $options[$i] = t('!a comments per page', array('!a' => $i));
+  }
+  $form['comments_per_page'] = array('#type' => 'select',
+    '#default_value' => $comments_per_page,
+    '#options' => $options,
+    '#weight' => 3,
+  );
+
+  $form['submit'] = array('#type' => 'submit',
+    '#value' => t('Save settings'),
+    '#weight' => 20,
+  );
+
+  return $form;
+}
+
+function theme_comment_controls($form) {
+  $output .= '<div class="container-inline">';
+  $output .=  drupal_render($form);
+  $output .= '</div>';
+  $output .= '<div class="description">'. t('Select your preferred way to display the comments and click "Save settings" to activate your changes.') .'</div>';
+  return theme('box', t('Comment viewing options'), $output);
+}
+
+function comment_controls_submit($form_id, $form_values) {
+  global $user;
+
+  $mode = $form_values['mode'];
+  $order = $form_values['order'];
+  $comments_per_page = $form_values['comments_per_page'];
+
+  if ($user->uid) {
+    $user = user_save($user, array('mode' => $mode, 'sort' => $order, 'comments_per_page' => $comments_per_page));
+  }
+  else {
+    $_SESSION['comment_mode'] = $mode;
+    $_SESSION['comment_sort'] = $order;
+    $_SESSION['comment_comments_per_page'] = $comments_per_page;
+  }
+}
+
+/**
+ * Prepare values for comment.tpl.php
+ */
+function template_preprocess_comment(&$variables) {
+  $comment = $variables['comment'];
+  $variables['author']    = theme('username', $comment);
+  $variables['comment']   = $comment;
+  $variables['content']   = $comment->comment;
+  $variables['date']      = format_date($comment->timestamp);
+  $variables['links']     = isset($variables['links']) ? theme('links', $variables['links']) : '';
+  $variables['new']       = $comment->new ? t('new') : '';
+  $variables['picture']   = theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', $comment) : '';
+  $variables['signature'] = $comment->signature;
+  $variables['submitted'] = t('Submitted by !a on @b.',
+                      array('!a' => theme('username', $comment),
+                            '@b' => format_date($comment->timestamp)));
+  $variables['title']     = l($comment->subject, $_GET['q'], array('fragment' => "comment-$comment->cid"));
+}
+
+function theme_comment_folded($comment) {
+  $output  = "<div class=\"comment-folded\">\n";
+  $output .= ' <span class="subject">'. l($comment->subject, comment_node_url() .'/'. $comment->cid, array('fragment' => "comment-$comment->cid")) .' '. theme('mark', $comment->new) .'</span> ';
+  $output .= '<span class="credit">'. t('by') .' '. theme('username', $comment) ."</span>\n";
+  $output .= "</div>\n";
+  return $output;
+}
+
+function theme_comment_flat_collapsed($comment) {
+  return theme('comment_view', $comment, '', 0);
+}
+
+function theme_comment_flat_expanded($comment) {
+  return theme('comment_view', $comment, module_invoke_all('link', 'comment', $comment, 0));
+}
+
+function theme_comment_thread_collapsed($comment) {
+  $output .= theme('comment_view', $comment, '', 0);
+  return $output;
+}
+
+function theme_comment_thread_expanded($comment) {
+  $output = '';
+  $output .= theme('comment_view', $comment, module_invoke_all('link', 'comment', $comment, 0));
+  return $output;
+}
+
+function theme_comment_post_forbidden($nid) {
+  global $user;
+  if ($user->uid) {
+    return t("you can't post comments");
+  }
+  else {
+    // we cannot use drupal_get_destination() because these links sometimes appear on /node and taxo listing pages
+    if (variable_get('comment_form_location', COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_SEPARATE_PAGE) {
+      $destination = "destination=". drupal_urlencode("comment/reply/$nid#comment-form");
+    }
+    else {
+      $destination = "destination=". drupal_urlencode("node/$nid#comment-form");
+    }
+
+    if (variable_get('user_register', 1)) {
+      return t('<a href="@login">Login</a> or <a href="@register">register</a> to post comments', array('@login' => url('user/login', array('query' => $destination)), '@register' => url('user/register', array('query' => $destination))));
+    }
+    else {
+      return t('<a href="@login">Login</a> to post comments', array('@login' => url('user/login', array('query' => $destination))));
+    }
+  }
+}
+
+/**
+ * Allow themable wrapping of all comments.
+ */
+function theme_comment_wrapper($content) {
+  return '<div id="comments">'. $content .'</div>';
+}
+
+function _comment_delete_thread($comment) {
+  if (!is_object($comment) || !is_numeric($comment->cid)) {
+    watchdog('content', 'Can not delete non-existent comment.', WATCHDOG_WARNING);
+    return;
+  }
+
+  // Delete the comment:
+  db_query('DELETE FROM {comments} WHERE cid = %d', $comment->cid);
+  watchdog('content', 'Comment: deleted %subject.', array('%subject' => $comment->subject));
+
+  comment_invoke_comment($comment, 'delete');
+
+  // Delete the comment's replies
+  $result = db_query('SELECT c.*, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE pid = %d', $comment->cid);
+  while ($comment = db_fetch_object($result)) {
+    $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
+    _comment_delete_thread($comment);
+  }
+}
+
+/**
+ * Return an array of viewing modes for comment listings.
+ *
+ * We can't use a global variable array because the locale system
+ * is not initialized yet when the comment module is loaded.
+ */
+function _comment_get_modes() {
+  return array(
+    COMMENT_MODE_FLAT_COLLAPSED => t('Flat list - collapsed'),
+    COMMENT_MODE_FLAT_EXPANDED => t('Flat list - expanded'),
+    COMMENT_MODE_THREADED_COLLAPSED => t('Threaded list - collapsed'),
+    COMMENT_MODE_THREADED_EXPANDED => t('Threaded list - expanded')
+  );
+}
+
+/**
+ * Return an array of viewing orders for comment listings.
+ *
+ * We can't use a global variable array because the locale system
+ * is not initialized yet when the comment module is loaded.
+ */
+function _comment_get_orders() {
+  return array(
+    COMMENT_ORDER_NEWEST_FIRST => t('Date - newest first'),
+    COMMENT_ORDER_OLDEST_FIRST => t('Date - oldest first')
+  );
+}
+
+/**
+ * Return an array of "comments per page" settings from which the user
+ * can choose.
+ */
+function _comment_per_page() {
+  return drupal_map_assoc(array(10, 30, 50, 70, 90, 150, 200, 250, 300));
+}
+
+/**
+ * Return a current comment display setting
+ *
+ * $setting can be one of these: 'mode', 'sort', 'comments_per_page'
+ */
+function _comment_get_display_setting($setting) {
+  global $user;
+
+  if (isset($_GET[$setting])) {
+    $value = $_GET[$setting];
+  }
+  else {
+    // get the setting's site default
+    switch ($setting) {
+      case 'mode':
+        $default = variable_get('comment_default_mode', COMMENT_MODE_THREADED_EXPANDED);
+        break;
+      case 'sort':
+        $default = variable_get('comment_default_order', COMMENT_ORDER_NEWEST_FIRST);
+        break;
+      case 'comments_per_page':
+        $default = variable_get('comment_default_per_page', '50');
+    }
+    if (variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_HIDDEN) {
+      // if comment controls are disabled use site default
+      $value = $default;
+    }
+    else {
+      // otherwise use the user's setting if set
+      if ($user->$setting) {
+        $value = $user->$setting;
+      }
+      else if ($_SESSION['comment_'. $setting]) {
+        $value = $_SESSION['comment_'. $setting];
+      }
+      else {
+        $value = $default;
+      }
+    }
+  }
+  return $value;
+}
+
+/**
+ * Updates the comment statistics for a given node. This should be called any
+ * time a comment is added, deleted, or updated.
+ *
+ * The following fields are contained in the node_comment_statistics table.
+ * - last_comment_timestamp: the timestamp of the last comment for this node or the node create stamp if no comments exist for the node.
+ * - last_comment_name: the name of the anonymous poster for the last comment
+ * - last_comment_uid: the uid of the poster for the last comment for this node or the node authors uid if no comments exists for the node.
+ * - comment_count: the total number of approved/published comments on this node.
+ */
+function _comment_update_node_statistics($nid) {
+  $count = db_result(db_query('SELECT COUNT(cid) FROM {comments} WHERE nid = %d AND status = %d', $nid, COMMENT_PUBLISHED));
+
+  // comments exist
+  if ($count > 0) {
+    $last_reply = db_fetch_object(db_query_range('SELECT cid, name, timestamp, uid FROM {comments} WHERE nid = %d AND status = %d ORDER BY cid DESC', $nid, COMMENT_PUBLISHED, 0, 1));
+    db_query("UPDATE {node_comment_statistics} SET comment_count = %d, last_comment_timestamp = %d, last_comment_name = '%s', last_comment_uid = %d WHERE nid = %d", $count, $last_reply->timestamp, $last_reply->uid ? '' : $last_reply->name, $last_reply->uid, $nid);
+  }
+
+  // no comments
+  else {
+    $node = db_fetch_object(db_query("SELECT uid, created FROM {node} WHERE nid = %d", $nid));
+    db_query("UPDATE {node_comment_statistics} SET comment_count = 0, last_comment_timestamp = %d, last_comment_name = '', last_comment_uid = %d WHERE nid = %d", $node->created, $node->uid, $nid);
+  }
+}
+
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.805
diff -u -p -r1.805 node.module
--- modules/node/node.module	25 Apr 2007 21:28:00 -0000	1.805
+++ modules/node/node.module	30 Apr 2007 07:06:43 -0000
@@ -1128,6 +1128,7 @@ function node_menu() {
     'weight' => -10,
     'page callback' => 'system_admin_menu_block_page',
     'access arguments' => array('administer site configuration'),
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
 
   $items['admin/content/node'] = array(
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.99
diff -u -p -r1.99 system.install
--- modules/system/system.install	25 Apr 2007 21:34:32 -0000	1.99
+++ modules/system/system.install	30 Apr 2007 07:06:44 -0000
@@ -359,6 +359,7 @@ function system_install() {
         fragment varchar(255) NOT NULL default '',
         absolute INT NOT NULL default 0,
         html INT NOT NULL default 0,
+        includes mediumtext NOT NULL default '',
         PRIMARY KEY  (path),
         KEY fit (fit),
         KEY visible (visible),
@@ -835,6 +836,7 @@ function system_install() {
         fragment varchar(255) NOT NULL default '',
         absolute INT NOT NULL default 0,
         html INT NOT NULL default 0,
+        includes text NOT NULL default '',
         PRIMARY KEY (path)
       )");
 
@@ -3847,6 +3849,28 @@ function system_update_6012() {
 }
 
 /**
+ * Add optional includes to menu paths
+ */
+function system_update_6013() {
+  $ret = array();
+
+  switch ($GLOBALS['db_type']) {
+    case 'pgsql':
+      db_add_column($ret, 'menu', 'includes', 'text', array('default' => "''", 'not null' => TRUE));
+      break;
+    case 'mysql':
+    case 'mysqli':
+      $ret[] = update_sql("ALTER TABLE {menu} ADD includes mediumtext NOT NULL default ''");
+      break;
+
+  }
+
+  return $ret;
+}
+
+
+
+/**
  * @} End of "defgroup updates-5.x-to-6.x"
  * The next series of updates should start at 7000.
  */
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.471
diff -u -p -r1.471 system.module
--- modules/system/system.module	24 Apr 2007 19:49:01 -0000	1.471
+++ modules/system/system.module	30 Apr 2007 07:06:44 -0000
@@ -134,22 +134,26 @@ function system_menu() {
     'access arguments' => array('access administration pages'),
     'page callback' => 'system_main_admin_page',
     'weight' => 9,
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/compact'] = array(
     'title' => t('Compact mode'),
     'page callback' => 'system_admin_compact_page',
     'type' => MENU_CALLBACK,
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/by-task'] = array(
     'title' => t('By task'),
     'page callback' => 'system_main_admin_page',
     'type' => MENU_DEFAULT_LOCAL_TASK,
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/by-module'] = array(
     'title' => t('By module'),
     'page callback' => 'system_admin_by_module',
     'type' => MENU_LOCAL_TASK,
     'weight' => 2,
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   // menu items that are basically just menu blocks
   $items['admin/settings'] = array(
@@ -159,6 +163,7 @@ function system_menu() {
     'weight' => -5,
     'page callback' => 'system_settings_overview',
     'access arguments' => array('administer site configuration'),
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/build'] = array(
     'title' => t('Site building'),
@@ -167,6 +172,7 @@ function system_menu() {
     'weight' => -10,
     'page callback' => 'system_admin_menu_block_page',
     'access arguments' => array('administer site configuration'),
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/settings/admin'] = array(
     'title' => t('Administration theme'),
@@ -175,6 +181,7 @@ function system_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_admin_theme_settings'),
     'block callback' => 'system_admin_theme_settings',
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   // Themes:
   $items['admin/build/themes'] = array(
@@ -182,12 +189,14 @@ function system_menu() {
     'description' => t('Change which theme your site uses or allows users to set.'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_themes_form'),
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/build/themes/select'] = array(
     'title' => t('List'),
     'description' => t('Select the default theme.'),
     'type' => MENU_DEFAULT_LOCAL_TASK,
     'weight' => -1,
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/build/themes/settings'] = array(
     'title' => t('Configure'),
@@ -217,6 +226,7 @@ function system_menu() {
     'description' => t('Enable or disable add-on modules for your site.'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_modules'),
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/build/modules/list'] = array(
     'title' => t('List'),
@@ -242,59 +252,69 @@ function system_menu() {
     'description' => t('Change basic site information, such as the site name, slogan, e-mail address, mission, front page and more.'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_site_information_settings'),
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/settings/error-reporting'] = array(
     'title' => t('Error reporting'),
     'description' => t('Control how Drupal deals with errors including 403/404 errors as well as PHP error reporting.'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_error_reporting_settings'),
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/settings/logging'] = array(
     'title' => t('Logging and alerts'),
     'description' => t('Settings for logging and alerts modules. Various modules can route Drupal\'s system events to different destination, such as syslog, database, email, ...etc.'),
     'page callback' => 'system_logging_overview',
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/settings/performance'] = array(
     'title' => t('Performance'),
     'description' => t('Enable or disable page caching for anonymous users, and enable or disable CSS preprocessor.'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_performance_settings'),
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/settings/file-system'] = array(
     'title' => t('File system'),
     'description' => t('Tell Drupal where to store uploaded files and how they are accessed.'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_file_system_settings'),
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/settings/image-toolkit'] = array(
     'title' => t('Image toolkit'),
     'description' => t('Choose which image toolkit to use if you have installed optional toolkits.'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_image_toolkit_settings'),
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/content/rss-publishing'] = array(
     'title' => t('RSS publishing'),
     'description' => t('Configure the number of items per feed and whether feeds should be titles/teasers/full-text.'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_rss_feeds_settings'),
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/settings/date-time'] = array(
     'title' => t('Date and time'),
     'description' => t("Settings for how Drupal displays date and time, as well as the system's default timezone."),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_date_time_settings'),
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/settings/site-maintenance'] = array(
     'title' => t('Site maintenance'),
     'description' => t('Take the site off-line for maintenance or bring it back online.'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_site_maintenance_settings'),
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/settings/clean-urls'] = array(
     'title' => t('Clean URLs'),
     'description' => t('Enable or disable clean URLs for your site.'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_clean_url_settings'),
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
 
   // Logs:
@@ -304,6 +324,7 @@ function system_menu() {
     'page callback' => 'system_admin_menu_block_page',
     'weight' => 5,
     'position' => 'left',
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/logs/status'] = array(
     'title' => t('Status report'),
@@ -311,6 +332,7 @@ function system_menu() {
     'page callback' => 'system_status',
     'weight' => 10,
     'access arguments' => array('administer site configuration'),
+    'includes' => drupal_get_path('module', 'system') . '/system.pages.inc',
   );
   $items['admin/logs/status/run-cron'] = array(
     'title' => t('Run cron'),
@@ -374,55 +396,99 @@ function system_user($type, $edit, &$use
 }
 
 /**
- * Provide the administration overview page.
+ * Implementation of hook_node_type().
+ *
+ * Updates theme settings after a node type change.
  */
-function system_main_admin_page($arg = NULL) {
-  // If we received an argument, they probably meant some other page.
-  // Let's 404 them since the menu system cannot be told we do not
-  // accept arguments.
-  if (isset($arg) && substr($arg, 0, 3) != 'by-') {
-    return drupal_not_found();
+function system_node_type($op, $info) {
+  if ($op == 'update' && !empty($info->old_type) && $info->type != $info->old_type) {
+    $old = 'toggle_node_info_'. $info->old_type;
+    $new = 'toggle_node_info_'. $info->type;
+
+    $theme_settings = variable_get('theme_settings', array());
+    if (isset($theme_settings[$old])) {
+      $theme_settings[$new] = $theme_settings[$old];
+      unset($theme_settings[$old]);
+      variable_set('theme_settings', $theme_settings);
+    }
   }
+}
+
+/**
+ * Get a list of available regions from a specified theme.
+ *
+ * @param $theme_key
+ *   The name of a theme.
+ * @return
+ *   An array of regions in the form $region['name'] = 'description'.
+ */
+function system_region_list($theme_key) {
+  static $list = array();
 
-  // Check for status report errors.
-  if (system_status(TRUE)) {
-    drupal_set_message(t('One or more problems were detected with your Drupal installation. Check the <a href="@status">status report</a> for more information.', array('@status' => url('admin/logs/status'))), 'error');
+  if (!array_key_exists($theme_key, $list)) {
+    $info = unserialize(db_result(db_query("SELECT info FROM {system} WHERE type = 'theme' AND name = '%s'", $theme_key)));
+    $list[$theme_key] = array_map('t', $info['regions']);
   }
 
-  $map = arg(NULL);
-  $result = db_query("SELECT * FROM {menu} WHERE path LIKE 'admin/%%' AND depth = 2 AND visible = 1 AND path != 'admin/help' ORDER BY mleft");
-  while ($item = db_fetch_object($result)) {
-    _menu_translate($item, $map, MENU_RENDER_LINK);
-    if (!$item->access) {
-      continue;
-    }
-    $block = (array)$item;
-    $block['content'] = '';
-    if ($item->block_callback && function_exists($item->block_callback)) {
-      $function = $item->block_callback;
-      $block['content'] .= $function();
+  return $list[$theme_key];
+}
+
+/**
+ * Get the name of the default region for a given theme.
+ *
+ * @param $theme
+ *   The name of a theme.
+ * @return
+ *   A string that is the region name.
+ */
+function system_default_region($theme) {
+  $regions = array_keys(system_region_list($theme));
+  return isset($regions[0]) ? $regions[0] : '';
+}
+
+/**
+ * Assign an initial, default set of blocks for a theme.
+ *
+ * This function is called the first time a new theme is enabled. The new theme
+ * gets a copy of the default theme's blocks, with the difference that if a
+ * particular region isn't available in the new theme, the block is assigned
+ * to the new theme's default region.
+ *
+ * @param $theme
+ *   The name of a theme.
+ */
+function system_initialize_theme_blocks($theme) {
+  // Initialize theme's blocks if none already registered.
+  if (!(db_num_rows(db_query("SELECT module FROM {blocks} WHERE theme = '%s'", $theme)))) {
+    $default_theme = variable_get('theme_default', 'garland');
+    $regions = system_region_list($theme);
+    $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s'", $default_theme);
+    while ($block = db_fetch_array($result)) {
+      // If the region isn't supported by the theme, assign the block to the theme's default region.
+      if (!array_key_exists($block['region'], $regions)) {
+        $block['region'] = system_default_region($theme);
+      }
+      db_query("INSERT INTO {blocks} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d)",
+          $block['module'], $block['delta'], $theme, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle']);
     }
-    $block['content'] .= theme('admin_block_content', system_admin_menu_block($item));
-    $blocks[] = $block;
   }
-  return theme('admin_page', $blocks);
 }
 
+
 /**
- * Provide a single block on the administration overview page.
+ * Add default buttons to a form and set its prefix
  */
-function system_admin_menu_block($item) {
-  $map = arg(NULL);
-  $content = array();
-  $result = db_query('SELECT * FROM {menu} WHERE depth = %d AND %d < mleft AND mright < %d AND visible = 1 ORDER BY mleft', $item->depth + 1, $item->mleft, $item->mright);
-  while ($item = db_fetch_object($result)) {
-    _menu_translate($item, $map, MENU_RENDER_LINK);
-    if (!$item->access) {
-      continue;
-    }
-    $content[] = (array)$item;
+function system_settings_form($form) {
+  $form['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration') );
+  $form['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset to defaults') );
+
+  if (!empty($_POST) && form_get_errors()) {
+    drupal_set_message(t('The settings have not been saved because of the errors.'), 'error');
   }
-  return $content;
+  $form['#submit']['system_settings_form_submit'] = array();
+  $form['#validate']['system_settings_form_validate'] = array();
+  $form['#theme'] = 'system_settings_form';
+  return $form;
 }
 
 /**
@@ -440,48 +506,116 @@ function system_admin_menu_block_page() 
   return $output;
 }
 
-function system_admin_compact_page($mode = 'off') {
-  global $user;
-  user_save($user, array('admin_compact_mode' => ($mode == 'on')));
-  drupal_goto('admin');
+/**
+ * Provide a single block on the administration overview page.
+ */
+function system_admin_menu_block($item) {
+  $map = arg(NULL);
+  $content = array();
+  $result = db_query('SELECT * FROM {menu} WHERE depth = %d AND %d < mleft AND mright < %d AND visible = 1 ORDER BY mleft', $item->depth + 1, $item->mleft, $item->mright);
+  while ($item = db_fetch_object($result)) {
+    _menu_translate($item, $map, MENU_RENDER_LINK);
+    if (!$item->access) {
+      continue;
+    }
+    $content[] = (array)$item;
+  }
+  return $content;
 }
 
+
 /**
- * This function allows selection of the theme to show in administration sections.
+ * This function formats the content of an administrative block.
+ *
+ * @param $block
+ *   An array containing information about the block. It should
+ *   include a 'title', a 'description' and a formatted 'content'.
+ * @themeable
  */
-function system_admin_theme_settings() {
-  $themes = system_theme_data();
-  ksort($themes);
-  $options[0] = t('System default');
-  foreach ($themes as $theme) {
-    $options[$theme->name] = $theme->info['name'];
+function theme_admin_block_content($content) {
+  if (!$content) {
+    return '';
   }
 
-  $form['admin_theme'] = array(
-    '#type' => 'select',
-    '#options' => $options,
-    '#title' => t('Administration theme'),
-    '#description' => t('Choose which theme the administration pages should display in. If you choose "System default" the administration pages will use the same theme as the rest of the site.'),
-    '#default_value' => variable_get('admin_theme', '0'),
-  );
-
-  // In order to give it our own submit, we have to give it the default submit
-  // too because the presence of a #submit will prevent the default #submit
-  // from being used. Also we want ours first.
-  $form['#submit']['system_admin_theme_submit'] = array();
-  $form['#submit']['system_settings_form_submit'] = array();
-  return system_settings_form($form);
+  if (system_admin_compact_mode()) {
+    $output = '<ul class="menu">';
+    foreach ($content as $item) {
+      if (empty($item['attributes'])) {
+        $item['attributes'] = array();
+      }
+      $item['attributes'] += array('title' => $item['description']);
+      $output .= '<li class="leaf">'. l($item['title'], $item['path'], $item) .'</li>';
+    }
+    $output .= '</ul>';
+  }
+  else {
+    $output = '<dl class="admin-list">';
+    foreach ($content as $item) {
+      $output .= '<dt>'. l($item['title'], $item['path'], $item) .'</dt>';
+      $output .= '<dd>'. $item['description'] .'</dd>';
+    }
+    $output .= '</dl>';
+  }
+  return $output;
 }
 
+/**
+ * Output a confirmation form
+ *
+ * This function returns a complete form for confirming an action. A link is
+ * offered to go back to the item that is being changed in case the user changes
+ * his/her mind.
+ *
+ * You can check for the existence of $_POST[$name] (where $name
+ * is usually 'confirm') to check if the confirmation was successful or
+ * use the regular submit model.
+ *
+ * @param $form
+ *   Additional elements to inject into the form, for example hidden elements.
+ * @param $question
+ *   The question to ask the user (e.g. "Are you sure you want to delete the
+ *   block <em>foo</em>?").
+ * @param $path
+ *   The page to go to if the user denies the action.
+ *   Can be either a drupal path, or an array with the keys 'path', 'query', 'fragment'.
+ * @param $description
+ *   Additional text to display (defaults to "This action cannot be undone.").
+ * @param $yes
+ *   A caption for the button which confirms the action (e.g. "Delete",
+ *   "Replace", ...).
+ * @param $no
+ *   A caption for the link which denies the action (e.g. "Cancel").
+ * @param $name
+ *   The internal name used to refer to the confirmation item.
+ * @return
+ *   The form.
+ */
+function confirm_form($form, $question, $path, $description = NULL, $yes = NULL, $no = NULL, $name = 'confirm') {
+  $description = isset($description) ? $description : t('This action cannot be undone.');
 
-function system_admin_theme_submit($form_id, $form_values) {
-  // If we're changing themes, make sure the theme has its blocks initialized.
-  if ($form_values['admin_theme'] != variable_get('admin_theme', '0')) {
-    $result = db_query("SELECT status FROM {blocks} WHERE theme = '%s'", $form_values['admin_theme']);
-    if (!db_num_rows($result)) {
-      system_initialize_theme_blocks($form_values['admin_theme']);
-    }
+  // Prepare cancel link
+  $query = $fragment = NULL;
+  if (is_array($path)) {
+    $query = isset($path['query']) ? $path['query'] : NULL;
+    $fragment = isset($path['fragment']) ? $path['fragment'] : NULL;
+    $path = isset($path['path']) ? $path['path'] : NULL;
   }
+  $cancel = l($no ? $no : t('Cancel'), $path, array('query' => $query, 'fragment' => $fragment));
+
+  drupal_set_title($question);
+
+  // Confirm form fails duplication check, as the form values rarely change -- so skip it.
+  $form['#skip_duplicate_check'] = TRUE;
+
+  $form['#attributes'] = array('class' => 'confirmation');
+  $form['description'] = array('#value' => $description);
+  $form[$name] = array('#type' => 'hidden', '#value' => 1);
+
+  $form['actions'] = array('#prefix' => '<div class="container-inline">', '#suffix' => '</div>');
+  $form['actions']['submit'] = array('#type' => 'submit', '#value' => $yes ? $yes : t('Confirm'));
+  $form['actions']['cancel'] = array('#value' => $cancel);
+  $form['#theme'] = 'confirm_form';
+  return $form;
 }
 
 /*
@@ -562,1902 +696,10 @@ function _system_zonelist() {
   return $zones;
 }
 
-function system_site_information_settings() {
-  $form['site_name'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Name'),
-    '#default_value' => variable_get('site_name', 'Drupal'),
-    '#description' => t('The name of this website.'),
-    '#required' => TRUE
-  );
-  $form['site_mail'] = array(
-    '#type' => 'textfield',
-    '#title' => t('E-mail address'),
-    '#default_value' => variable_get('site_mail', ini_get('sendmail_from')),
-    '#description' => t('A valid e-mail address to be used as the "From" address by the auto-mailer during registration, new password requests, notifications, etc.  To lessen the likelihood of e-mail being marked as spam, this e-mail address should use the same domain as the website.'),
-    '#required' => TRUE,
-  );
-  $form['site_slogan'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Slogan'),
-    '#default_value' => variable_get('site_slogan', ''),
-    '#description' => t('The slogan of this website. Some themes display a slogan when available.')
-  );
-
-  $form['site_mission'] = array(
-    '#type' => 'textarea',
-    '#title' => t('Mission'),
-    '#default_value' => variable_get('site_mission', ''),
-    '#description' => t('Your site\'s mission statement or focus.')
-  );
-  $form['site_footer'] = array(
-    '#type' => 'textarea',
-    '#title' => t('Footer message'),
-    '#default_value' => variable_get('site_footer', ''),
-    '#description' => t('This text will be displayed at the bottom of each page. Useful for adding a copyright notice to your pages.')
-  );
-  $form['anonymous'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Anonymous user'),
-    '#default_value' => variable_get('anonymous', t('Anonymous')),
-    '#description' => t('The name used to indicate anonymous users.')
-  );
-  $form['site_frontpage'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Default front page'),
-    '#default_value' => variable_get('site_frontpage', 'node'),
-    '#size' => 40,
-    '#description' => t('The home page displays content from this relative URL. If unsure, specify "node".'),
-    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
-  );
-
-  return system_settings_form($form);
-}
-
-function system_clean_url_settings() {
-  $form['clean_url'] = array(
-    '#type' => 'radios',
-    '#title' => t('Clean URLs'),
-    '#default_value' => variable_get('clean_url', 0),
-    '#options' => array(t('Disabled'), t('Enabled')),
-    '#description' => t('This option makes Drupal emit "clean" URLs (i.e. without <code>?q=</code> in the URL).'),
-  );
-
-  if (!variable_get('clean_url', 0)) {
-    if (strpos(request_uri(), '?q=') !== FALSE) {
-      drupal_add_js(array('cleanURL' => array('success' => t('Your server has been successfully tested to support this feature.'), 'failure' => t('Your system configuration does not currently support this feature. The <a href="http://drupal.org/node/15365">handbook page on Clean URLs</a> has additional troubleshooting information.'), 'testing' => t('Testing clean URLs...'))), 'setting');
-      drupal_add_js(drupal_get_path('module', 'system') .'/system.js', 'module');
-      drupal_add_js('
-// Global Killswitch
-if (Drupal.jsEnabled) {
-  $(document).ready(function() {
-    Drupal.cleanURLsSettingsCheck();
-  });
-}', 'inline');
-
-      $form['clean_url']['#description'] .= ' <span>'. t('Before enabling clean URLs, you must perform a test to determine if your server is properly configured. If you are able to see this page again after clicking the "Run the clean URL test" link, the test has succeeded and the radio buttons above will be available. If instead you are directed to a "Page not found" error, you will need to change the configuration of your server. The <a href="@handbook">handbook page on Clean URLs</a> has additional troubleshooting information.', array('@handbook' => 'http://drupal.org/node/15365')) .'</span>';
-
-      $form['clean_url']['#disabled'] = TRUE;
-      $form['clean_url']['#prefix'] = '<div id="clean-url">';
-      $form['clean_url']['#suffix'] = '<p>'. t('<a href="@clean_url">Run the clean url test</a>.', array('@clean_url' => base_path() .'admin/settings/clean-urls')) .'</p></div>';
-    }
-    else {
-      $form['clean_url']['#description'] .= ' '. t('Your server has been successfully tested to support this feature.');
-    }
-  }
-
-  return system_settings_form($form);
-}
-
-function system_error_reporting_settings() {
-
-  $form['site_403'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Default 403 (access denied) page'),
-    '#default_value' => variable_get('site_403', ''),
-    '#size' => 40,
-    '#description' => t('This page is displayed when the requested document is denied to the current user. If unsure, specify nothing.'),
-    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
-  );
-
-  $form['site_404'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Default 404 (not found) page'),
-    '#default_value' =>  variable_get('site_404', ''),
-    '#size' => 40,
-    '#description' => t('This page is displayed when no other content matches the requested document. If unsure, specify nothing.'),
-    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
-  );
-
-  $form['error_level'] = array(
-    '#type' => 'select', '#title' => t('Error reporting'), '#default_value' => variable_get('error_level', 1),
-    '#options' => array(t('Write errors to the log'), t('Write errors to the log and to the screen')),
-    '#description' =>  t('Where Drupal, PHP and SQL errors are logged. On a production server it is recommended that errors are only written to the error log. On a test server it can be helpful to write logs to the screen.')
-  );
-
-  return system_settings_form($form);
-}
-
-function system_performance_settings() {
-
-  $description = '<p>'. t("The normal cache mode is suitable for most sites and does not cause any side effects. The aggressive cache mode causes Drupal to skip the loading (init) and unloading (exit) of enabled modules when serving a cached page. This results in an additional performance boost but can cause unwanted side effects.") .'</p>';
-
-  $problem_modules = array_unique(array_merge(module_implements('init'), module_implements('exit')));
-  sort($problem_modules);
-
-  if (count($problem_modules) > 0) {
-    $description .= '<p>'. t('<strong class="error">The following enabled modules are incompatible with aggressive mode caching and will not function properly: %modules</strong>', array('%modules' => implode(', ', $problem_modules))) .'.</p>';
-  }
-  else {
-    $description .= '<p>'. t('<strong class="ok">Currently, all enabled modules are compatible with the aggressive caching policy.</strong> Please note, if you use aggressive caching and enable new modules, you will need to check this page again to ensure compatibility.') .'</p>';
-  }
-  $form['page_cache'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Page cache'),
-    '#description' => t('Enabling the cache will offer a significant performance boost. Drupal can store and send compressed cached pages requested by <em>anonymous</em> users. By caching a web page, Drupal does not have to construct the page each time someone wants to view it.'),
-  );
-
-  $form['page_cache']['cache'] = array(
-    '#type' => 'radios',
-    '#title' => t('Caching mode'),
-    '#default_value' => variable_get('cache', CACHE_DISABLED),
-    '#options' => array(CACHE_DISABLED => t('Disabled'), CACHE_NORMAL => t('Normal (recommended, no side effects)'), CACHE_AGGRESSIVE => t('Aggressive (experts only, possible side effects)')),
-    '#description' => $description
-  );
-
-  $period = drupal_map_assoc(array(0, 60, 180, 300, 600, 900, 1800, 2700, 3600, 10800, 21600, 32400, 43200, 86400), 'format_interval');
-  $period[0] = t('none');
-  $form['page_cache']['cache_lifetime'] = array(
-    '#type' => 'select',
-    '#title' => t('Minimum cache lifetime'),
-    '#default_value' => variable_get('cache_lifetime', 0),
-    '#options' => $period,
-    '#description' => t('On high-traffic sites it can become necessary to enforce a minimum cache lifetime. The minimum cache lifetime is the minimum amount of time that will go by before the cache is emptied and recreated. A larger minimum cache lifetime offers better performance, but users will not see new content for a longer period of time.')
-  );
-
-  $form['bandwidth_optimizations'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Bandwidth optimizations'),
-    '#description' => t('These options can help reduce both the size and number of requests made to your website. This can reduce the server load, the bandwidth used, and the average page loading time for your visitors.')
-  );
-
-  $directory = file_directory_path();
-  $is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC);
-  $form['bandwidth_optimizations']['preprocess_css'] = array(
-    '#type' => 'radios',
-    '#title' => t('Aggregate and compress CSS files'),
-    '#default_value' => variable_get('preprocess_css', FALSE) && $is_writable,
-    '#disabled' => !$is_writable,
-    '#options' => array(t('Disabled'), t('Enabled')),
-    '#description' => t("Some Drupal modules include their own CSS files. When these modules are enabled, each module's CSS file adds an additional HTTP request to the page, which can increase the load time of each page. These HTTP requests can also slightly increase server load. It is recommended to only turn this option on when your site is in production, as it can interfere with theme development. This option is disabled if you have not set up your files directory, or if your download method is set to private."),
-  );
-
-  $form['#submit']['system_settings_form_submit'] = array();
-  $form['#submit']['drupal_clear_css_cache'] = array();
-
-  return system_settings_form($form);
-}
-
-function system_file_system_settings() {
-
-  $form['file_directory_path'] = array(
-    '#type' => 'textfield',
-    '#title' => t('File system path'),
-    '#default_value' => file_directory_path(),
-    '#maxlength' => 255,
-    '#description' => t('A file system path where the files will be stored. This directory has to exist and be writable by Drupal. If the download method is set to public this directory has to be relative to the Drupal installation directory, and be accessible over the web. When download method is set to private this directory should not be accessible over the web. Changing this location after the site has been in use will cause problems so only change this setting on an existing site if you know what you are doing.'),
-    '#after_build' => array('system_check_directory'),
-  );
-
-  $form['file_directory_temp'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Temporary directory'),
-    '#default_value' => file_directory_temp(),
-    '#maxlength' => 255,
-    '#description' => t('Location where uploaded files will be kept during previews. Relative paths will be resolved relative to the Drupal installation directory.'),
-    '#after_build' => array('system_check_directory'),
-  );
-
-  $form['file_downloads'] = array(
-    '#type' => 'radios',
-    '#title' => t('Download method'),
-    '#default_value' => variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC),
-    '#options' => array(FILE_DOWNLOADS_PUBLIC => t('Public - files are available using HTTP directly.'), FILE_DOWNLOADS_PRIVATE => t('Private - files are transferred by Drupal.')),
-    '#description' => t('If you want any sort of access control on the downloading of files, this needs to be set to <em>private</em>. You can change this at any time, however all download URLs will change and there may be unexpected problems so it is not recommended.')
-  );
-
-  return system_settings_form($form);
-}
-
-function system_image_toolkit_settings() {
-  $toolkits_available = image_get_available_toolkits();
-  if (count($toolkits_available) > 1) {
-    $form['image_toolkit'] = array(
-      '#type' => 'radios',
-      '#title' => t('Select an image processing toolkit'),
-      '#default_value' => variable_get('image_toolkit', image_get_toolkit()),
-      '#options' => $toolkits_available
-    );
-  }
-  else {
-    $form['image_toolkit'] = array('#value' => '<p>'. t("No image toolkits found. Drupal will use PHP's built-in GD library for image handling.") .'</p>');
-  }
-  $form['image_toolkit_settings'] = image_toolkit_invoke('settings');
-  return system_settings_form($form);
-}
-
-function system_rss_feeds_settings() {
-
-  $form['feed_default_items'] = array(
-    '#type' => 'select',
-    '#title' => t('Number of items per feed'),
-    '#default_value' => variable_get('feed_default_items', 10),
-    '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30)),
-    '#description' => t('The default number of items to include in a feed.')
-  );
-  $form['feed_item_length'] = array(
-    '#type' => 'select',
-    '#title' => t('Display of XML feed items'),
-    '#default_value' => variable_get('feed_item_length', 'teaser'),
-    '#options' => array('title' => t('Titles only'), 'teaser' => t('Titles plus teaser'), 'fulltext' => t('Full text')),
-    '#description' => t('Global setting for the length of XML feed items that are output by default.')
-  );
-
-  return system_settings_form($form);
+/**
+ * Determine if a user is in compact mode.
+ */
+function system_admin_compact_mode() {
+  global $user;
+  return (isset($user->admin_compact_mode)) ? $user->admin_compact_mode : variable_get('admin_compact_mode', FALSE);
 }
-
-function system_date_time_settings() {
-  // Date settings:
-  $zones = _system_zonelist();
-
-  // Date settings: possible date formats
-  $dateshort = array('Y-m-d H:i', 'm/d/Y - H:i', 'd/m/Y - H:i', 'Y/m/d - H:i',
-           'd.m.Y - H:i', 'm/d/Y - g:ia', 'd/m/Y - g:ia', 'Y/m/d - g:ia',
-           'M j Y - H:i', 'j M Y - H:i', 'Y M j - H:i',
-           'M j Y - g:ia', 'j M Y - g:ia', 'Y M j - g:ia');
-  $datemedium = array('D, Y-m-d H:i', 'D, m/d/Y - H:i', 'D, d/m/Y - H:i',
-          'D, Y/m/d - H:i', 'F j, Y - H:i', 'j F, Y - H:i', 'Y, F j - H:i',
-          'D, m/d/Y - g:ia', 'D, d/m/Y - g:ia', 'D, Y/m/d - g:ia',
-          'F j, Y - g:ia', 'j F Y - g:ia', 'Y, F j - g:ia', 'j. F Y - G:i');
-  $datelong = array('l, F j, Y - H:i', 'l, j F, Y - H:i', 'l, Y,  F j - H:i',
-        'l, F j, Y - g:ia', 'l, j F Y - g:ia', 'l, Y,  F j - g:ia', 'l, j. F Y - G:i');
-
-  // Date settings: construct choices for user
-  foreach ($dateshort as $f) {
-    $dateshortchoices[$f] = format_date(time(), 'custom', $f);
-  }
-  foreach ($datemedium as $f) {
-    $datemediumchoices[$f] = format_date(time(), 'custom', $f);
-  }
-  foreach ($datelong as $f) {
-    $datelongchoices[$f] = format_date(time(), 'custom', $f);
-  }
-
-  $form['date_default_timezone'] = array(
-    '#type' => 'select',
-    '#title' => t('Default time zone'),
-    '#default_value' => variable_get('date_default_timezone', 0),
-    '#options' => $zones,
-    '#description' => t('Select the default site time zone.')
-  );
-
-  $form['configurable_timezones'] = array(
-    '#type' => 'radios',
-    '#title' => t('Configurable time zones'),
-    '#default_value' => variable_get('configurable_timezones', 1),
-    '#options' => array(t('Disabled'), t('Enabled')),
-    '#description' => t('Enable or disable user-configurable time zones. When enabled, users can set their own time zone and dates will be updated accordingly.')
-  );
-
-  $form['date_format_short'] = array(
-    '#type' => 'select',
-    '#title' => t('Short date format'),
-    '#default_value' => variable_get('date_format_short', $dateshort[1]),
-    '#options' => $dateshortchoices,
-    '#description' => t('The short format of date display.')
-  );
-
-  $form['date_format_medium'] = array(
-    '#type' => 'select',
-    '#title' => t('Medium date format'),
-    '#default_value' => variable_get('date_format_medium', $datemedium[1]),
-    '#options' => $datemediumchoices,
-    '#description' => t('The medium sized date display.')
-  );
-
-  $form['date_format_long'] = array(
-    '#type' => 'select',
-    '#title' => t('Long date format'),
-    '#default_value' => variable_get('date_format_long', $datelong[0]),
-    '#options' => $datelongchoices,
-    '#description' => t('Longer date format used for detailed display.')
-  );
-
-  $form['date_first_day'] = array(
-    '#type' => 'select',
-    '#title' => t('First day of week'),
-    '#default_value' => variable_get('date_first_day', 0),
-    '#options' => array(0 => t('Sunday'), 1 => t('Monday'), 2 => t('Tuesday'), 3 => t('Wednesday'), 4 => t('Thursday'), 5 => t('Friday'), 6 => t('Saturday')),
-    '#description' => t('The first day of the week for calendar views.')
-  );
-
-  return system_settings_form($form);
-}
-
-function system_site_maintenance_settings() {
-
-  $form['site_offline'] = array(
-    '#type' => 'radios',
-    '#title' => t('Site status'),
-    '#default_value' => variable_get('site_offline', 0),
-    '#options' => array(t('Online'), t('Off-line')),
-    '#description' => t('When set to "Online", all visitors will be able to browse your site normally. When set to "Off-line", only users with the "administer site configuration" permission will be able to access your site to perform maintenance; all other visitors will see the site off-line message configured below. Authorized users can log in during "Off-line" mode directly via the <a href="@user-login">user login</a> page.', array('@user-login' => url('user'))),
-  );
-
-  $form['site_offline_message'] = array(
-    '#type' => 'textarea',
-    '#title' => t('Site off-line message'),
-    '#default_value' => variable_get('site_offline_message', t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => variable_get('site_name', 'Drupal')))),
-    '#description' => t('Message to show visitors when the site is in off-line mode.')
-  );
-
-  return system_settings_form($form);
-}
-
-/**
- * Checks the existence of the directory specified in $form_element. This
- * function is called from the system_settings form to check both the
- * file_directory_path and file_directory_temp directories. If validation
- * fails, the form element is flagged with an error from within the
- * file_check_directory function.
- *
- * @param $form_element
- *   The form element containing the name of the directory to check.
- */
-function system_check_directory($form_element) {
-  file_check_directory($form_element['#value'], FILE_CREATE_DIRECTORY, $form_element['#parents'][0]);
-  return $form_element;
-}
-
-/**
- * Retrieves the current status of an array of files in the system table.
- */
-function system_get_files_database(&$files, $type) {
-  // Extract current files from database.
-  $result = db_query("SELECT filename, name, type, status, throttle, schema_version FROM {system} WHERE type = '%s'", $type);
-  while ($file = db_fetch_object($result)) {
-    if (isset($files[$file->name]) && is_object($files[$file->name])) {
-      $file->old_filename = $file->filename;
-      foreach ($file as $key => $value) {
-        if (!isset($files[$file->name]) || !isset($files[$file->name]->$key)) {
-          $files[$file->name]->$key = $value;
-        }
-      }
-    }
-  }
-}
-
-function system_theme_default() {
-  // Prepare defaults for themes.
-  return array(
-    'regions' => array(
-      'left' => 'Left sidebar',
-      'right' => 'Right sidebar',
-      'content' => 'Content',
-      'header' => 'Header',
-      'footer' => 'Footer',
-    ),
-    'description' => '',
-    'features' => array(
-      'comment_user_picture',
-      'favicon',
-      'mission',
-      'logo',
-      'name',
-      'node_user_picture',
-      'search',
-      'slogan'
-    ),
-  );
-}
-
-/**
- * Collect data about all currently available themes
- */
-function system_theme_data() {
-  include_once './includes/install.inc';
-
-  // Find themes
-  $themes = drupal_system_listing('\.theme$', 'themes');
-
-  // Find theme engines
-  $engines = drupal_system_listing('\.engine$', 'themes/engines');
-
-  // can't iterate over array itself as it uses a copy of the array items
-  foreach (array_keys($themes) as $key) {
-    drupal_get_filename('theme', $themes[$key]->name, $themes[$key]->filename);
-    drupal_load('theme', $themes[$key]->name);
-    $themes[$key]->owner = $themes[$key]->filename;
-    $themes[$key]->prefix = $key;
-  }
-
-  // Remove all theme engines from the system table
-  db_query("DELETE FROM {system} WHERE type = 'theme_engine'");
-
-  foreach ($engines as $engine) {
-    // Insert theme engine into system table
-    drupal_get_filename('theme_engine', $engine->name, $engine->filename);
-    drupal_load('theme_engine', $engine->name);
-    db_query("INSERT INTO {system} (name, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', %d, %d, %d)", $engine->name, 'theme_engine', $engine->filename, 1, 0, 0);
-
-    // Add templates to the site listing
-    foreach (call_user_func($engine->name .'_templates') as $template) {
-      // Do not double-insert templates with theme files in their directory,
-      // but do register their engine data.
-      if (array_key_exists($template->name, $themes)) {
-        $themes[$template->name]->template = TRUE;
-        $themes[$template->name]->owner = $engine->filename;
-        $themes[$template->name]->prefix = $engine->name;
-      }
-      else {
-        $template->template = TRUE;
-        $template->name = basename(dirname($template->filename));
-        $template->owner = $engine->filename;
-        $template->prefix = $engine->name;
-
-        $themes[$template->name] = $template;
-      }
-    }
-  }
-
-  // Find styles in each theme's directory.
-  foreach ($themes as $theme) {
-    foreach (file_scan_directory(dirname($theme->filename), 'style.css$') as $style) {
-      $style->style = TRUE;
-      $style->template = isset($theme->template) ? $theme->template : FALSE;
-      $style->name = basename(dirname($style->filename));
-      $style->owner = $theme->filename;
-      $style->prefix = !empty($theme->template) ? $theme->prefix : $theme->name;
-      // do not double-insert styles with theme files in their directory
-      if (array_key_exists($style->name, $themes)) {
-        continue;
-      }
-      $themes[$style->name] = $style;
-    }
-  }
-
-  // Extract current files from database.
-  system_get_files_database($themes, 'theme');
-
-  $defaults = system_theme_default();
-  // Read info files for the owner
-  foreach (array_keys($themes) as $key) {
-    $themes[$key]->info = drupal_parse_info_file(dirname($themes[$key]->filename) .'/'. $themes[$key]->name .'.info') + $defaults;
-  }
-
-  db_query("DELETE FROM {system} WHERE type = 'theme'");
-
-  foreach ($themes as $theme) {
-    db_query("INSERT INTO {system} (name, owner, info, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', '%s', %d, %d, %d)", $theme->name, $theme->owner, serialize($theme->info), 'theme', $theme->filename, isset($theme->status) ? $theme->status : 0, 0, 0);
-  }
-
-  return $themes;
-}
-
-/**
- * Get a list of available regions from a specified theme.
- *
- * @param $theme_key
- *   The name of a theme.
- * @return
- *   An array of regions in the form $region['name'] = 'description'.
- */
-function system_region_list($theme_key) {
-  static $list = array();
-
-  if (!array_key_exists($theme_key, $list)) {
-    $info = unserialize(db_result(db_query("SELECT info FROM {system} WHERE type = 'theme' AND name = '%s'", $theme_key)));
-    $list[$theme_key] = array_map('t', $info['regions']);
-  }
-
-  return $list[$theme_key];
-}
-
-/**
- * Get the name of the default region for a given theme.
- *
- * @param $theme
- *   The name of a theme.
- * @return
- *   A string that is the region name.
- */
-function system_default_region($theme) {
-  $regions = array_keys(system_region_list($theme));
-  return isset($regions[0]) ? $regions[0] : '';
-}
-
-/**
- * Assign an initial, default set of blocks for a theme.
- *
- * This function is called the first time a new theme is enabled. The new theme
- * gets a copy of the default theme's blocks, with the difference that if a
- * particular region isn't available in the new theme, the block is assigned
- * to the new theme's default region.
- *
- * @param $theme
- *   The name of a theme.
- */
-function system_initialize_theme_blocks($theme) {
-  // Initialize theme's blocks if none already registered.
-  if (!(db_num_rows(db_query("SELECT module FROM {blocks} WHERE theme = '%s'", $theme)))) {
-    $default_theme = variable_get('theme_default', 'garland');
-    $regions = system_region_list($theme);
-    $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s'", $default_theme);
-    while ($block = db_fetch_array($result)) {
-      // If the region isn't supported by the theme, assign the block to the theme's default region.
-      if (!array_key_exists($block['region'], $regions)) {
-        $block['region'] = system_default_region($theme);
-      }
-      db_query("INSERT INTO {blocks} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d)",
-          $block['module'], $block['delta'], $theme, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle']);
-    }
-  }
-}
-
-/**
- * Add default buttons to a form and set its prefix
- */
-function system_settings_form($form) {
-  $form['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration') );
-  $form['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset to defaults') );
-
-  if (!empty($_POST) && form_get_errors()) {
-    drupal_set_message(t('The settings have not been saved because of the errors.'), 'error');
-  }
-  $form['#submit']['system_settings_form_submit'] = array();
-  $form['#validate']['system_settings_form_validate'] = array();
-  $form['#theme'] = 'system_settings_form';
-  return $form;
-}
-
-function system_theme_settings_submit($form_id, $form_values) {
-  $op = isset($_POST['op']) ? $_POST['op'] : '';
-  $key = $form_values['var'];
-
-  // Exclude unnecessary elements.
-  unset($form_values['var'], $form_values['submit'], $form_values['reset'], $form_values['form_id']);
-
-  if ($op == t('Reset to defaults')) {
-    variable_del($key);
-    drupal_set_message(t('The configuration options have been reset to their default values.'));
-  }
-  else {
-    variable_set($key, $form_values);
-    drupal_set_message(t('The configuration options have been saved.'));
-  }
-
-  cache_clear_all();
-}
-
-/**
- * Execute the system_settings_form.
- *
- * If you want node type configure style handling of your checkboxes,
- * add an array_filter value to your form.
- *
- */
-function system_settings_form_submit($form_id, $form_values) {
-  $op = isset($form_values['op']) ? $form_values['op'] : '';
-
-  // Exclude unnecessary elements.
-  unset($form_values['submit'], $form_values['reset'], $form_values['form_id'], $form_values['op'], $form_values['form_token']);
-
-  foreach ($form_values as $key => $value) {
-    if ($op == t('Reset to defaults')) {
-      variable_del($key);
-    }
-    else {
-      if (is_array($value) && isset($form_values['array_filter'])) {
-        $value = array_keys(array_filter($value));
-      }
-      variable_set($key, $value);
-    }
-  }
-  if ($op == t('Reset to defaults')) {
-    drupal_set_message(t('The configuration options have been reset to their default values.'));
-  }
-  else {
-    drupal_set_message(t('The configuration options have been saved.'));
-  }
-
-  drupal_rebuild_theme_registry();
-}
-
-/**
- * Menu callback; displays a listing of all themes.
- */
-function system_themes_form() {
-
-  drupal_clear_css_cache();
-  $themes = system_theme_data();
-  ksort($themes);
-  $status = array();
-
-  foreach ($themes as $theme) {
-    $theme->screenshot = dirname($theme->filename) .'/screenshot.png';
-    $screenshot = file_exists($theme->screenshot) ? theme('image', $theme->screenshot, t('Screenshot for %theme theme', array('%theme' => $theme->info['name'])), '', array('class' => 'screenshot'), FALSE) : t('no screenshot');
-
-    $form[$theme->name]['screenshot'] = array('#value' => $screenshot);
-    $form[$theme->name]['info'] = array('#type' => 'value', '#value' => $theme->info);
-    $options[$theme->name] = '';
-    if (!empty($theme->status)) {
-      $status[] = $theme->name;
-    }
-    if (!empty($theme->status)) {
-      $form[$theme->name]['operations'] = array('#value' => l(t('configure'), 'admin/build/themes/settings/'. $theme->name) );
-    }
-    else {
-      // Dummy element for drupal_render. Cleaner than adding a check in the theme function.
-      $form[$theme->name]['operations'] = array();
-    }
-  }
-
-  $form['status'] = array('#type' => 'checkboxes', '#options' => $options, '#default_value' => $status);
-  $form['theme_default'] = array('#type' => 'radios', '#options' => $options, '#default_value' => variable_get('theme_default', 'garland'));
-  $form['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration') );
-  $form['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset to defaults') );
-
-  return $form;
-}
-
-function theme_system_themes_form($form) {
-  foreach (element_children($form) as $key) {
-    // Only look for themes
-    if (!isset($form[$key]['info'])) {
-      continue;
-    }
-
-    // Fetch info
-    $info = $form[$key]['info']['#value'];
-
-    // Style theme info
-    $theme = '<div class="theme-info"><h2>'. $info['name'] .'</h2><div class="description">'. $info['description'] .'</div></div>';
-
-    // Build rows
-    $row = array();
-    $row[] = drupal_render($form[$key]['screenshot']);
-    $row[] = $theme;
-    $row[] = $info['version'];
-    $row[] = array('data' => drupal_render($form['status'][$key]), 'align' => 'center');
-    if ($form['theme_default']) {
-      $row[] = array('data' => drupal_render($form['theme_default'][$key]), 'align' => 'center');
-      $row[] = array('data' => drupal_render($form[$key]['operations']), 'align' => 'center');
-    }
-    $rows[] = $row;
-  }
-
-  $header = array(t('Screenshot'), t('Name'), t('Version'), t('Enabled'), t('Default'), t('Operations'));
-  $output = theme('table', $header, $rows);
-  $output .= drupal_render($form);
-  return $output;
-}
-
-
-function system_themes_form_submit($form_id, $form_values) {
-
-  db_query("UPDATE {system} SET status = 0 WHERE type = 'theme'");
-
-  if ($form_values['op'] == t('Save configuration')) {
-    if (is_array($form_values['status'])) {
-      foreach ($form_values['status'] as $key => $choice) {
-        // Always enable the default theme, despite its status checkbox being checked:
-        if ($choice || $form_values['theme_default'] == $key) {
-          system_initialize_theme_blocks($key);
-          db_query("UPDATE {system} SET status = 1 WHERE type = 'theme' and name = '%s'", $key);
-        }
-      }
-    }
-    if (($admin_theme = variable_get('admin_theme', '0')) != '0' && $admin_theme != $form_values['theme_default']) {
-      drupal_set_message(t('Please note that the <a href="!admin_theme_page">administration theme</a> is still set to the %admin_theme theme; consequently, the theme on this page remains unchanged. All non-administrative sections of the site, however, will show the selected %selected_theme theme by default.', array(
-        '!admin_theme_page' => url('admin/settings/admin'),
-        '%admin_theme' => $admin_theme,
-        '%selected_theme' => $form_values['theme_default'],
-      )));
-    }
-    variable_set('theme_default', $form_values['theme_default']);
-  }
-  else {
-    variable_del('theme_default');
-    db_query("UPDATE {system} SET status = 1 WHERE type = 'theme' AND name = 'garland'");
-  }
-
-  list_themes(TRUE);
-  menu_rebuild();
-  drupal_set_message(t('The configuration options have been saved.'));
-  return 'admin/build/themes';
-}
-
-/**
- * Menu callback; provides module enable/disable interface.
- *
- * Modules can be enabled or disabled and set for throttling if the throttle module is enabled.
- * The list of modules gets populated by module.info files, which contain each module's name,
- * description and dependencies.
- * @sa drupal_parse_info_file for information on module.info descriptors.
- *
- * Dependency checking is performed to ensure that a module cannot be enabled if the module has
- * disabled dependencies and also to ensure that the module cannot be disabled if the module has
- * enabled dependents.
- *
- * @return
- *   The form array.
- */
-function system_modules($form_values = NULL) {
-  // Get current list of modules.
-  $files = module_rebuild_cache();
-  if ($confirm_form = system_modules_confirm_form($files, $form_values)) {
-    return $confirm_form;
-  }
-
-  // Store module list for validation callback.
-  $form['validation_modules'] = array('#type' => 'value', '#value' => $files);
-
-  // Create storage for disabled modules as browser will disable checkboxes.
-  $form['disabled_modules'] = array('#type' => 'value', '#value' => array());
-
-  // Array for disabling checkboxes in callback system_module_disable.
-  $disabled = array();
-  $throttle = array();
-  // Traverse the files retrieved and build the form.
-  foreach ($files as $filename => $file) {
-    $form['name'][$filename] = array('#value' => $file->info['name']);
-    $form['version'][$filename] = array('#value' => $file->info['version']);
-    $form['description'][$filename] = array('#value' => t($file->info['description']));
-    $options[$filename] = '';
-    if ($file->status) {
-      $status[] = $file->name;
-    }
-    if ($file->throttle) {
-      $throttle[] = $file->name;
-    }
-
-    $dependencies = array();
-    // Check for missing dependencies.
-    if (is_array($file->info['dependencies'])) {
-      foreach ($file->info['dependencies'] as $dependency) {
-        if (!isset($files[$dependency]) || !$files[$dependency]->status) {
-          if (isset($files[$dependency])) {
-            $dependencies[] = $files[$dependency]->info['name'] . t(' (<span class="admin-disabled">disabled</span>)');
-          }
-          else {
-            $dependencies[] = drupal_ucfirst($dependency) . t(' (<span class="admin-missing">missing</span>)');
-            $disabled[] = $filename;
-            $form['disabled_modules']['#value'][$filename] = FALSE;
-          }
-        }
-        else {
-          $dependencies[] = $files[$dependency]->info['name'] . t(' (<span class="admin-enabled">enabled</span>)');
-        }
-      }
-
-      // Add text for dependencies.
-      if (!empty($dependencies)) {
-        $form['description'][$filename]['dependencies'] = array(
-          '#value' => t('Depends on: !dependencies', array('!dependencies' => implode(', ', $dependencies))),
-          '#prefix' => '<div class="admin-dependencies">',
-          '#suffix' => '</div>',
-        );
-      }
-    }
-
-    // Mark dependents disabled so user can not remove modules being depended on.
-    $dependents = array();
-    foreach ($file->info['dependents'] as $dependent) {
-      if ($files[$dependent]->status == 1) {
-        $dependents[] = $files[$dependent]->info['name'] . t(' (<span class="admin-enabled">enabled</span>)');
-        $disabled[] = $filename;
-        $form['disabled_modules']['#value'][$filename] = TRUE;
-      }
-      else {
-        $dependents[] = $files[$dependent]->info['name'] . t(' (<span class="admin-disabled">disabled</span>)');
-      }
-    }
-
-    // Add text for enabled dependents.
-    if (!empty($dependents)) {
-      $form['description'][$filename]['required'] = array(
-        '#value' => t('Required by: !required', array('!required' => implode(', ', $dependents))),
-        '#prefix' => '<div class="admin-required">',
-        '#suffix' => '</div>',
-      );
-    }
-  }
-
-  $modules_required = drupal_required_modules();
-  // Merge in required modules.
-  foreach ($modules_required as $required) {
-    $disabled[] = $required;
-    $form['disabled_modules']['#value'][$required] = TRUE;
-  }
-
-  // Handle status checkboxes, including overriding
-  // the generated checkboxes for required modules.
-  $form['status'] = array(
-    '#type' => 'checkboxes',
-    '#default_value' => $status,
-    '#options' => $options,
-    '#process' => array(
-      'expand_checkboxes' => array(),
-      'system_modules_disable' => array($disabled),
-    ),
-  );
-
-  // Handle throttle checkboxes, including overriding the
-  // generated checkboxes for required modules.
-  if (module_exists('throttle')) {
-    $form['throttle'] = array(
-      '#type' => 'checkboxes',
-      '#default_value' => $throttle,
-      '#options' => $options,
-      '#process' => array(
-        'expand_checkboxes' => array(),
-        'system_modules_disable' => array(array_merge($modules_required, array('throttle'))),
-      ),
-    );
-  }
-
-  $form['buttons']['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Save configuration'),
-  );
-  $form['#multistep'] = TRUE;
-  $form['#action'] = url('admin/build/modules/list/confirm');
-
-  return $form;
-}
-
-/**
- * Form process callback function to disable check boxes.
- */
-function system_modules_disable($form, $edit, $disabled) {
-  foreach ($disabled as $key) {
-    $form[$key]['#attributes']['disabled'] = 'disabled';
-  }
-  return $form;
-}
-
-function system_modules_confirm_form($modules, $form_values = array()) {
-  $form = array();
-  $items = array();
-
-  // Check values for submitted dependency errors.
-  if ($dependencies = system_module_build_dependencies($modules, $form_values)) {
-    // preserve the already switched on modules
-    foreach ($modules as $name => $module) {
-      if ($module->status) {
-        $form['status'][$name] = array('#type' => 'hidden', '#value' => 1);
-      }
-    }
-
-    $form['validation_modules'] = array('#type' => 'value', '#value' => $modules);
-    $form['status']['#tree'] = TRUE;
-    foreach ($dependencies as $name => $missing_dependencies) {
-      $form['status'][$name] = array('#type' => 'hidden', '#value' => 1);
-      foreach ($missing_dependencies as $k => $dependency) {
-        $form['status'][$dependency] = array('#type' => 'hidden', '#value' => 1);
-        $info = $modules[$dependency]->info;
-        $missing_dependencies[$k] = $info['name'] ? $info['name'] : drupal_ucfirst($dependency);
-      }
-      $t_argument = array(
-        '@module' => $modules[$name]->info['name'],
-        '@dependencies' => implode(', ', $missing_dependencies),
-      );
-      $items[] = format_plural(count($missing_dependencies), 'You must enable the @dependencies module to install @module.', 'You must enable the @dependencies modules to install @module.', $t_argument);
-    }
-    $form['text'] = array('#value' => theme('item_list', $items));
-  }
-
-  if ($form) {
-    // Set some default form values
-    $form = confirm_form(
-      $form,
-      t('Some required modules must be enabled'),
-      'admin/build/modules',
-      t('Would you like to continue with enabling the above?'),
-      t('Continue'),
-      t('Cancel'));
-    return $form;
-  }
-}
-
-function system_module_build_dependencies($modules, $form_values) {
-  static $dependencies;
-
-  if (!isset($dependencies) && isset($form_values)) {
-    $dependencies = array();
-    foreach ($modules as $name => $module) {
-      // If the module is disabled, will be switched on and it has dependencies.
-      if (!$module->status && $form_values['status'][$name] && isset($module->info['dependencies'])) {
-        foreach ($module->info['dependencies'] as $dependency) {
-          if (!$form_values['status'][$dependency] && isset($modules[$dependency])) {
-            if (!isset($dependencies[$name])) {
-              $dependencies[$name] = array();
-            }
-            $dependencies[$name][] = $dependency;
-          }
-        }
-      }
-    }
-  }
-  return $dependencies;
-}
-
-/**
- * Submit callback; handles modules form submission.
- */
-function system_modules_submit($form_id, $form_values) {
-  include_once './includes/install.inc';
-  $new_modules = array();
-
-  // Merge in disabled active modules since they should be enabled.
-  // They don't appear because disabled checkboxes are not submitted
-  // by browsers.
-  $form_values['status'] = array_merge($form_values['status'], $form_values['disabled_modules']);
-
-  // Check values for dependency that we can't install.
-  if ($dependencies = system_module_build_dependencies($form_values['validation_modules'], $form_values)) {
-    // These are the modules that depend on existing modules.
-    foreach (array_keys($dependencies) as $name) {
-      $form_values['status'][$name] = 0;
-    }
-  }
-
-  $enable_modules = array();
-  $disable_modules = array();
-  foreach ($form_values['status'] as $key => $choice) {
-    if ($choice) {
-      if (drupal_get_installed_schema_version($key) == SCHEMA_UNINSTALLED) {
-        $new_modules[] = $key;
-      }
-      else {
-        $enable_modules[] = $key;
-      }
-    }
-    else {
-      $disable_modules[] = $key;
-    }
-  }
-
-  $old_module_list = module_list();
-
-  if (!empty($enable_modules)) {
-    module_enable($enable_modules);
-  }
-  if (!empty($disable_modules)) {
-    module_disable($disable_modules);
-  }
-
-  // Install new modules.
-  foreach ($new_modules as $key => $module) {
-    if (!drupal_check_module($module)) {
-      unset($new_modules[$key]);
-    }
-  }
-  drupal_install_modules($new_modules);
-
-  $current_module_list = module_list(TRUE, FALSE);
-
-  if (isset($form_values['throttle'])) {
-    foreach ($form_values['throttle'] as $key => $choice) {
-      db_query("UPDATE {system} SET throttle = %d WHERE type = 'module' and name = '%s'", $choice ? 1 : 0, $key);
-    }
-  }
-
-  if ($old_module_list != $current_module_list) {
-    drupal_rebuild_theme_registry();
-    menu_rebuild();
-    node_types_rebuild();
-    drupal_set_message(t('The configuration options have been saved.'));
-  }
-
-  // If there where unmet dependencies and they haven't confirmed don't redirect.
-  if ($dependencies && !isset($form_values['confirm'])) {
-    return FALSE;
-  }
-
-  drupal_clear_css_cache();
-
-  return 'admin/build/modules';
-}
-
-/**
- * Theme call back for the modules form.
- */
-function theme_system_modules($form) {
-  if (isset($form['confirm'])) {
-    return drupal_render($form);
-  }
-
-  // Individual table headers.
-  $header = array(t('Enabled'));
-  if (module_exists('throttle')) {
-    $header[] = t('Throttle');
-  }
-  $header[] = t('Name');
-  $header[] = t('Version');
-  $header[] = t('Description');
-
-  // Pull package information from module list and start grouping modules.
-  $modules = $form['validation_modules']['#value'];
-  foreach ($modules as $module) {
-    if (!isset($module->info['package']) || !$module->info['package']) {
-      $module->info['package'] = t('Other');
-    }
-    $packages[$module->info['package']][$module->name] = $module->info;
-  }
-  ksort($packages);
-
-  // Display packages.
-  $output = '';
-  foreach ($packages as $package => $modules) {
-    $rows = array();
-    foreach ($modules as $key => $module) {
-      $row = array();
-      $row[] = array('data' => drupal_render($form['status'][$key]), 'align' => 'center');
-
-      if (module_exists('throttle')) {
-        $row[] = array('data' => drupal_render($form['throttle'][$key]), 'align' => 'center');
-      }
-      $row[] = '<strong>'. drupal_render($form['name'][$key]) .'</strong>';
-      $row[] = drupal_render($form['version'][$key]);
-      $row[] = array('data' => drupal_render($form['description'][$key]), 'class' => 'description');
-      $rows[] = $row;
-    }
-    $fieldset = array(
-      '#title' => t($package),
-      '#collapsible' => TRUE,
-      '#collapsed' => ($package == 'Core - required'),
-      '#value' => theme('table', $header, $rows, array('class' => 'package')),
-    );
-    $output .= theme('fieldset', $fieldset);
-  }
-
-  $output .= drupal_render($form);
-  return $output;
-}
-
-/**
- * Uninstall functions
- */
-
-/**
- * Builds a form of currently disabled modules.
- *
- * @param
- *   $form_values Submitted form values.
- * @return
- *   A form array representing the currently disabled modules.
- */
-function system_modules_uninstall($form_values = NULL) {
-  // Make sure the install API is available.
-  include_once './includes/install.inc';
-
-  // Display the confirm form if any modules have been submitted.
-  if ($confirm_form = system_modules_uninstall_confirm_form($form_values)) {
-    return $confirm_form;
-  }
-
-  $form = array();
-
-  // Pull all disabled modules from the system table.
-  $disabled_modules = db_query("SELECT name, filename, info FROM {system} WHERE type = 'module' AND status = 0 AND schema_version > %d ORDER BY name", SCHEMA_UNINSTALLED);
-  while ($module = db_fetch_object($disabled_modules)) {
-
-    // Grab the module info
-    $info = unserialize($module->info);
-
-    // Load the .install file, and check for an uninstall hook.
-    // If the hook exists, the module can be uninstalled.
-    module_load_install($module->name);
-    if (module_hook($module->name, 'uninstall')) {
-      $form['modules'][$module->name]['name'] = array('#value' => $info['name'] ? $info['name'] : $module->name);
-      $form['modules'][$module->name]['description'] = array('#value' => t($info['description']));
-      $options[$module->name] = '';
-    }
-  }
-
-  // Only build the rest of the form if there are any modules available to uninstall.
-  if (!empty($options)) {
-    $form['uninstall'] = array(
-      '#type' => 'checkboxes',
-      '#options' => $options,
-    );
-    $form['buttons']['submit'] = array(
-      '#type' => 'button',
-      '#value' => t('Uninstall'),
-    );
-    $form['#multistep'] = TRUE;
-    $form['#action'] = url('admin/build/modules/uninstall/confirm');
-  }
-  else {
-    $form['modules'] = array();
-  }
-
-  return $form;
-}
-
-/**
- * Confirm uninstall of selected modules.
- *
- * @param
- *   $form_values Submitted form values.
- * @return
- *   A form array representing modules to confirm.
- */
-function system_modules_uninstall_confirm_form($form_values) {
-  // Nothing to build.
-  if (!isset($form_values)) {
-    return;
-  }
-
-  // Construct the hidden form elements and list items.
-  foreach (array_filter($form_values['uninstall']) as $module => $value) {
-    $info = drupal_parse_info_file(dirname(drupal_get_filename('module', $module)) .'/'. $module .'.info');
-    $uninstall[] = $info['name'];
-    $form['uninstall'][$module] = array('#type' => 'hidden',
-      '#value' => 1,
-    );
-  }
-
-  // Display a confirm form if modules have been selected.
-  if (isset($uninstall)) {
-    $form['uninstall']['#tree'] = TRUE;
-    $form['#multistep'] = TRUE;
-    $form['modules'] = array('#value' => '<p>'. t('The following modules will be completely uninstalled from your site, and <em>all data from these modules will be lost</em>!') .'</p>'. theme('item_list', $uninstall));
-    $form = confirm_form(
-      $form,
-      t('Confirm uninstall'),
-      'admin/build/modules/uninstall',
-      t('Would you like to continue with uninstalling the above?'),
-      t('Uninstall'),
-      t('Cancel'));
-    return $form;
-  }
-}
-
-/**
- * Themes a table of currently disabled modules.
- *
- * @param
- *   $form The form array representing the currently disabled modules.
- * @return
- *   An HTML string representing the table.
- */
-function theme_system_modules_uninstall($form) {
-  // No theming for the confirm form.
-  if (isset($form['confirm'])) {
-    return drupal_render($form);
-  }
-
-  // Table headers.
-  $header = array(t('Uninstall'),
-    t('Name'),
-    t('Description'),
-  );
-
-  // Display table.
-  $rows = array();
-  foreach (element_children($form['modules']) as $module) {
-    $rows[] = array(
-      array('data' => drupal_render($form['uninstall'][$module]), 'align' => 'center'),
-      '<strong>'. drupal_render($form['modules'][$module]['name']) .'</strong>',
-      array('data' => drupal_render($form['modules'][$module]['description']), 'class' => 'description'),
-    );
-  }
-
-  // Only display table if there are modules that can be uninstalled.
-  if (empty($rows)) {
-    $rows[] = array(array('data' => t('No modules are available to uninstall.'), 'colspan' => '3', 'align' => 'center', 'class' => 'message'));
-  }
-
-  $output  = theme('table', $header, $rows);
-  $output .= drupal_render($form);
-
-  return $output;
-}
-
-/**
- * Validates the submitted uninstall form.
- *
- * @param
- *   $form_id The form ID.
- * @param
- *   $form_values Submitted form values.
- */
-function system_modules_uninstall_validate($form_id, $form_values) {
-  // Form submitted, but no modules selected.
-  if (!count(array_filter($form_values['uninstall']))) {
-    drupal_set_message(t('No modules selected.'), 'error');
-    drupal_goto('admin/build/modules/uninstall');
-  }
-}
-
-/**
- * Processes the submitted uninstall form.
- *
- * @param
- *   $form_id The form ID.
- * @param
- *   $form_values Submitted form values.
- */
-function system_modules_uninstall_submit($form_id, $form_values) {
-  // Make sure the install API is available.
-  include_once './includes/install.inc';
-
-  // Call the uninstall routine for each selected module.
-  foreach (array_filter($form_values['uninstall']) as $module => $value) {
-    drupal_uninstall_module($module);
-  }
-  drupal_set_message(t('The selected modules have been uninstalled.'));
-  drupal_goto('admin/build/modules/uninstall');
-}
-
-/**
- * Menu callback: run cron manually.
- */
-function system_run_cron() {
-   // Run cron manually
-   if (drupal_cron_run()) {
-     drupal_set_message(t('Cron ran successfully'));
-   }
-   else {
-     drupal_set_message(t('Cron run failed'));
-   }
-
-   drupal_goto('admin/logs/status');
-}
-
-/**
- * Menu callback: return information about PHP.
- */
-function system_php() {
-  phpinfo(INFO_GENERAL | INFO_CONFIGURATION);
-  exit();
-}
-
-function _system_sql($data, $keys) {
-  $rows = array();
-  foreach ($keys as $key => $explanation) {
-    if (isset($data[$key])) {
-      $rows[] = array(check_plain($key), check_plain($data[$key]), $explanation);
-    }
-  }
-
-  return theme('table', array(t('Variable'), t('Value'), t('Description')), $rows);
-}
-
-/**
- * Menu callback: return information about PHP.
- */
-function system_sql() {
-
-  $result = db_query("SHOW STATUS");
-  while ($entry = db_fetch_object($result)) {
-   $data[$entry->Variable_name] = $entry->Value;
-  }
-
-  $output  = '<h2>'. t('Command counters') .'</h2>';
-  $output .= _system_sql($data, array(
-   'Com_select' => t('The number of <code>SELECT</code>-statements.'),
-   'Com_insert' => t('The number of <code>INSERT</code>-statements.'),
-   'Com_update' => t('The number of <code>UPDATE</code>-statements.'),
-   'Com_delete' => t('The number of <code>DELETE</code>-statements.'),
-   'Com_lock_tables' => t('The number of table locks.'),
-   'Com_unlock_tables' => t('The number of table unlocks.')
-  ));
-
-  $output .= '<h2>'. t('Query performance') .'</h2>';
-  $output .= _system_sql($data, array(
-   'Select_full_join' => t('The number of joins without an index; should be zero.'),
-   'Select_range_check' => t('The number of joins without an index; should be zero.'),
-   'Sort_scan' => t('The number of sorts done without using an index; should be zero.'),
-   'Table_locks_immediate' => t('The number of times a lock could be acquired immediately.'),
-   'Table_locks_waited' => t('The number of times the server had to wait for a lock.')
-  ));
-
-  $output .= '<h2>'. t('Query cache information') .'</h2>';
-  $output .= '<p>'. t('The MySQL query cache can improve performance of your site by storing the result of queries.  Then, if an identical query is received later, the MySQL server retrieves the result from the query cache rather than parsing and executing the statement again.') .'</p>';
-  $output .= _system_sql($data, array(
-   'Qcache_queries_in_cache' => t('The number of queries in the query cache.'),
-   'Qcache_hits' => t('The number of times that MySQL found previous results in the cache.'),
-   'Qcache_inserts' => t('The number of times that MySQL added a query to the cache (misses).'),
-   'Qcache_lowmem_prunes' => t('The number of times that MySQL had to remove queries from the cache because it ran out of memory.  Ideally should be zero.')
-  ));
-
-  return $output;
-}
-
-/**
- * Menu callback: displays the site status report. Can also be used as a pure check.
- *
- * @param $check
- *   If true, only returns a boolean whether there are system status errors.
- */
-function system_status($check = FALSE) {
-  // Load .install files
-  include_once './includes/install.inc';
-  drupal_load_updates();
-
-  // Check run-time requirements and status information
-  $requirements = module_invoke_all('requirements', 'runtime');
-  usort($requirements, '_system_sort_requirements');
-
-  if ($check) {
-    return drupal_requirements_severity($requirements) == REQUIREMENT_ERROR;
-  }
-
-  return theme('status_report', $requirements);
-}
-
-/**
- * Helper function to sort requirements.
- */
-function _system_sort_requirements($a, $b) {
-  if (!isset($a['weight'])) {
-    if (!isset($b['weight'])) {
-      return strcmp($a['title'], $b['title']);
-    }
-    return -$b['weight'];
-  }
-  return isset($b['weight']) ? $a['weight'] - $b['weight'] : $a['weight'];
-}
-
-/**
- * Theme status report
- */
-function theme_status_report(&$requirements) {
-  $i = 0;
-  $output = '<table class="system-status-report">';
-  foreach ($requirements as $requirement) {
-    if (empty($requirement['#type'])) {
-      $class = ++$i % 2 == 0 ? 'even' : 'odd';
-
-      $classes = array(
-        REQUIREMENT_INFO => 'info',
-        REQUIREMENT_OK => 'ok',
-        REQUIREMENT_WARNING => 'warning',
-        REQUIREMENT_ERROR => 'error',
-      );
-      $class = $classes[isset($requirement['severity']) ? (int)$requirement['severity'] : 0] .' '. $class;
-
-      // Output table row(s)
-      if (!empty($requirement['description'])) {
-        $output .= '<tr class="'. $class .' merge-down"><th>'. $requirement['title'] .'</th><td>'. $requirement['value'] .'</td></tr>';
-        $output .= '<tr class="'. $class .' merge-up"><td colspan="2">'. $requirement['description'] .'</td></tr>';
-      }
-      else {
-        $output .= '<tr class="'. $class .'"><th>'. $requirement['title'] .'</th><td>'. $requirement['value'] .'</td></tr>';
-      }
-    }
-  }
-
-  $output .= '</table>';
-  return $output;
-}
-
-/**
- * Menu callback; displays a module's settings page.
- */
-function system_settings_overview() {
-  // Check database setup if necessary
-  if (function_exists('db_check_setup') && empty($_POST)) {
-    db_check_setup();
-  }
-
-  $item = menu_get_item('admin/settings');
-  $content = system_admin_menu_block($item);
-
-  $output = theme('admin_block_content', $content);
-
-  return $output;
-}
-
-function system_logging_overview() {
-  $item = menu_get_item('admin/settings/logging');
-  $content = system_admin_menu_block($item);
-
-  $output = theme('admin_block_content', $content);
-
-  return $output;
-}
-/**
- * Menu callback; display theme configuration for entire site and individual themes.
- */
-function system_theme_settings($key = '') {
-  $directory_path = file_directory_path();
-  file_check_directory($directory_path, FILE_CREATE_DIRECTORY, 'file_directory_path');
-
-  // Default settings are defined in theme_get_settings() in includes/theme.inc
-  if ($key) {
-    $settings = theme_get_settings($key);
-    $var = str_replace('/', '_', 'theme_'. $key .'_settings');
-    $themes = system_theme_data();
-    $features = $themes[$key]->info['features'];
-  }
-  else {
-    $settings = theme_get_settings('');
-    $var = 'theme_settings';
-  }
-
-  $form['var'] = array('#type' => 'hidden', '#value' => $var);
-
-  // Check for a new uploaded logo, and use that instead.
-  if ($file = file_check_upload('logo_upload')) {
-    if ($info = image_get_info($file->filepath)) {
-      $parts = pathinfo($file->filename);
-      $filename = ($key) ? str_replace('/', '_', $key) .'_logo.'. $parts['extension'] : 'logo.'. $parts['extension'];
-
-      if ($file = file_save_upload('logo_upload', $filename, 1)) {
-        $_POST['default_logo'] = 0;
-        $_POST['logo_path'] = $file->filepath;
-        $_POST['toggle_logo'] = 1;
-      }
-    }
-    else {
-      form_set_error('file_upload', t('Only JPEG, PNG and GIF images are allowed to be used as logos.'));
-    }
-  }
-
-  // Check for a new uploaded favicon, and use that instead.
-  if ($file = file_check_upload('favicon_upload')) {
-    $parts = pathinfo($file->filename);
-    $filename = ($key) ? str_replace('/', '_', $key) .'_favicon.'. $parts['extension'] : 'favicon.'. $parts['extension'];
-
-    if ($file = file_save_upload('favicon_upload', $filename, 1)) {
-      $_POST['default_favicon'] = 0;
-      $_POST['favicon_path'] = $file->filepath;
-      $_POST['toggle_favicon'] = 1;
-    }
-  }
-
-  // Toggle settings
-  $toggles = array(
-    'logo'                 => t('Logo'),
-    'name'                 => t('Site name'),
-    'slogan'               => t('Site slogan'),
-    'mission'              => t('Mission statement'),
-    'node_user_picture'    => t('User pictures in posts'),
-    'comment_user_picture' => t('User pictures in comments'),
-    'search'               => t('Search box'),
-    'favicon'              => t('Shortcut icon')
-  );
-
-  // Some features are not always available
-  $disabled = array();
-  if (!variable_get('user_pictures', 0)) {
-    $disabled['toggle_node_user_picture'] = TRUE;
-    $disabled['toggle_comment_user_picture'] = TRUE;
-  }
-  if (!module_exists('search')) {
-    $disabled['toggle_search'] = TRUE;
-  }
-
-  $form['theme_settings'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Toggle display'),
-    '#description' => t('Enable or disable the display of certain page elements.'),
-  );
-  foreach ($toggles as $name => $title) {
-    if ((!$key) || in_array($name, $features)) {
-      // disable search box if search.module is disabled
-      $form['theme_settings']['toggle_'. $name] = array('#type' => 'checkbox', '#title' => $title, '#default_value' => $settings['toggle_'. $name]);
-      if (isset($disabled[$name])) {
-        $form['theme_settings']['toggle_'. $name]['#disabled'] = TRUE;
-      }
-    }
-  }
-
-  // System wide only settings.
-  if (!$key) {
-    // Create neat 2-column layout for the toggles
-    $form['theme_settings'] += array(
-      '#prefix' => '<div class="theme-settings-left">',
-      '#suffix' => '</div>',
-    );
-
-    // Toggle node display.
-    $node_types = node_get_types('names');
-    if ($node_types) {
-      $form['node_info'] = array(
-        '#type' => 'fieldset',
-        '#title' => t('Display post information on'),
-        '#description' =>  t('Enable or disable the <em>submitted by Username on date</em> text when displaying posts of the following type.'),
-        '#prefix' => '<div class="theme-settings-right">',
-        '#suffix' => '</div>',
-      );
-      foreach ($node_types as $type => $name) {
-        $form['node_info']["toggle_node_info_$type"] = array('#type' => 'checkbox', '#title' => $name, '#default_value' => $settings["toggle_node_info_$type"]);
-      }
-    }
-  }
-
-  // Logo settings
-  if ((!$key) || in_array('logo', $features)) {
-    $form['logo'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Logo image settings'),
-      '#description' => t('If toggled on, the following logo will be displayed.'),
-      '#attributes' => array('class' => 'theme-settings-bottom'),
-    );
-    $form['logo']["default_logo"] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Use the default logo'),
-      '#default_value' => $settings['default_logo'],
-      '#tree' => FALSE,
-      '#description' => t('Check here if you want the theme to use the logo supplied with it.')
-    );
-    $form['logo']['logo_path'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Path to custom logo'),
-      '#default_value' => $settings['logo_path'],
-      '#description' => t('The path to the file you would like to use as your logo file instead of the default logo.'));
-
-    $form['logo']['logo_upload'] = array(
-      '#type' => 'file',
-      '#title' => t('Upload logo image'),
-      '#maxlength' => 40,
-      '#description' => t("If you don't have direct file access to the server, use this field to upload your logo.")
-    );
-  }
-
-  if ((!$key) || in_array('favicon', $features)) {
-    $form['favicon'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Shortcut icon settings'),
-      '#description' => t("Your shortcut icon or 'favicon' is displayed in the address bar and bookmarks of most browsers.")
-    );
-    $form['favicon']['default_favicon'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Use the default shortcut icon.'),
-      '#default_value' => $settings['default_favicon'],
-      '#description' => t('Check here if you want the theme to use the default shortcut icon.')
-    );
-    $form['favicon']['favicon_path'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Path to custom icon'),
-      '#default_value' =>  $settings['favicon_path'],
-      '#description' => t('The path to the image file you would like to use as your custom shortcut icon.')
-    );
-
-    $form['favicon']['favicon_upload'] = array(
-      '#type' => 'file',
-      '#title' => t('Upload icon image'),
-      '#description' => t("If you don't have direct file access to the server, use this field to upload your shortcut icon.")
-    );
-  }
-
-  if ($key) {
-    // Template-specific settings
-    $function = $themes[$key]->prefix .'_settings';
-    if (function_exists($function)) {
-      if ($themes[$key]->template) {
-        // file is a template or a style of a template
-        $form['specific'] = array('#type' => 'fieldset', '#title' => t('Engine-specific settings'), '#description' => t('These settings only exist for all the templates and styles based on the %engine theme engine.', array('%engine' => $themes[$key]->prefix)));
-      }
-      else {
-        // file is a theme or a style of a theme
-        $form['specific'] = array('#type' => 'fieldset', '#title' => t('Theme-specific settings'), '#description' => t('These settings only exist for the %theme theme and all the styles based on it.', array('%theme' => $themes[$key]->prefix)));
-      }
-      $group = $function();
-      $form['specific'] = array_merge($form['specific'], (is_array($group) ? $group : array()));
-    }
-  }
-  $form['#attributes'] = array('enctype' => 'multipart/form-data');
-
-  return system_settings_form($form);
-}
-
-/**
- * Implementation of hook_node_type().
- *
- * Updates theme settings after a node type change.
- */
-function system_node_type($op, $info) {
-  if ($op == 'update' && !empty($info->old_type) && $info->type != $info->old_type) {
-    $old = 'toggle_node_info_'. $info->old_type;
-    $new = 'toggle_node_info_'. $info->type;
-
-    $theme_settings = variable_get('theme_settings', array());
-    if (isset($theme_settings[$old])) {
-      $theme_settings[$new] = $theme_settings[$old];
-      unset($theme_settings[$old]);
-      variable_set('theme_settings', $theme_settings);
-    }
-  }
-}
-
-/**
- * Output a confirmation form
- *
- * This function returns a complete form for confirming an action. A link is
- * offered to go back to the item that is being changed in case the user changes
- * his/her mind.
- *
- * You can check for the existence of $_POST[$name] (where $name
- * is usually 'confirm') to check if the confirmation was successful or
- * use the regular submit model.
- *
- * @param $form
- *   Additional elements to inject into the form, for example hidden elements.
- * @param $question
- *   The question to ask the user (e.g. "Are you sure you want to delete the
- *   block <em>foo</em>?").
- * @param $path
- *   The page to go to if the user denies the action.
- *   Can be either a drupal path, or an array with the keys 'path', 'query', 'fragment'.
- * @param $description
- *   Additional text to display (defaults to "This action cannot be undone.").
- * @param $yes
- *   A caption for the button which confirms the action (e.g. "Delete",
- *   "Replace", ...).
- * @param $no
- *   A caption for the link which denies the action (e.g. "Cancel").
- * @param $name
- *   The internal name used to refer to the confirmation item.
- * @return
- *   The form.
- */
-function confirm_form($form, $question, $path, $description = NULL, $yes = NULL, $no = NULL, $name = 'confirm') {
-  $description = isset($description) ? $description : t('This action cannot be undone.');
-
-  // Prepare cancel link
-  $query = $fragment = NULL;
-  if (is_array($path)) {
-    $query = isset($path['query']) ? $path['query'] : NULL;
-    $fragment = isset($path['fragment']) ? $path['fragment'] : NULL;
-    $path = isset($path['path']) ? $path['path'] : NULL;
-  }
-  $cancel = l($no ? $no : t('Cancel'), $path, array('query' => $query, 'fragment' => $fragment));
-
-  drupal_set_title($question);
-
-  // Confirm form fails duplication check, as the form values rarely change -- so skip it.
-  $form['#skip_duplicate_check'] = TRUE;
-
-  $form['#attributes'] = array('class' => 'confirmation');
-  $form['description'] = array('#value' => $description);
-  $form[$name] = array('#type' => 'hidden', '#value' => 1);
-
-  $form['actions'] = array('#prefix' => '<div class="container-inline">', '#suffix' => '</div>');
-  $form['actions']['submit'] = array('#type' => 'submit', '#value' => $yes ? $yes : t('Confirm'));
-  $form['actions']['cancel'] = array('#value' => $cancel);
-  $form['#theme'] = 'confirm_form';
-  return $form;
-}
-
-/**
- * Determine if a user is in compact mode.
- */
-function system_admin_compact_mode() {
-  global $user;
-  return (isset($user->admin_compact_mode)) ? $user->admin_compact_mode : variable_get('admin_compact_mode', FALSE);
-}
-
-/**
- * This function formats an administrative page for viewing.
- *
- * @param $blocks
- *   An array of blocks to display. Each array should include a
- *   'title', a 'description', a formatted 'content' and a
- *   'position' which will control which container it will be
- *   in. This is usually 'left' or 'right'.
- * @themeable
- */
-function theme_admin_page($blocks) {
-  $stripe = 0;
-  $container = array();
-
-  foreach ($blocks as $block) {
-    if ($block_output = theme('admin_block', $block)) {
-      if (empty($block['position'])) {
-        // perform automatic striping.
-        $block['position'] = ++$stripe % 2 ? 'left' : 'right';
-      }
-      if (!isset($container[$block['position']])) {
-        $container[$block['position']] = '';
-      }
-      $container[$block['position']] .= $block_output;
-    }
-  }
-
-  $output = '<div class="admin clear-block">';
-  $output .= '<div class="compact-link">';
-  if (system_admin_compact_mode()) {
-    $output .= l(t('Show descriptions'), 'admin/compact/off', array('title' => t('Produce a less compact layout that includes descriptions.')));
-  }
-  else {
-    $output .= l(t('Hide descriptions'), 'admin/compact/on', array('title' => t("Produce a more compact layout that doesn't include descriptions.")));
-  }
-  $output .= '</div>';
-
-  foreach ($container as $id => $data) {
-    $output .= '<div class="'. $id .' clear-block">';
-    $output .= $data;
-    $output .= '</div>';
-  }
-  $output .= '</div>';
-  return $output;
-}
-
-/**
- * This function formats an administrative block for display.
- *
- * @param $block
- *   An array containing information about the block. It should
- *   include a 'title', a 'description' and a formatted 'content'.
- * @themeable
- */
-function theme_admin_block($block) {
-  // Don't display the block if it has no content to display.
-  if (empty($block['content'])) {
-    return '';
-  }
-
-  $output = <<< EOT
-  <div class="admin-panel">
-    <h3>
-      $block[title]
-    </h3>
-    <div class="body">
-      <p class="description">
-        $block[description]
-      </p>
-      $block[content]
-    </div>
-  </div>
-EOT;
-  return $output;
-}
-
-/**
- * This function formats the content of an administrative block.
- *
- * @param $block
- *   An array containing information about the block. It should
- *   include a 'title', a 'description' and a formatted 'content'.
- * @themeable
- */
-function theme_admin_block_content($content) {
-  if (!$content) {
-    return '';
-  }
-
-  if (system_admin_compact_mode()) {
-    $output = '<ul class="menu">';
-    foreach ($content as $item) {
-      if (empty($item['attributes'])) {
-        $item['attributes'] = array();
-      }
-      $item['attributes'] += array('title' => $item['description']);
-      $output .= '<li class="leaf">'. l($item['title'], $item['path'], $item) .'</li>';
-    }
-    $output .= '</ul>';
-  }
-  else {
-    $output = '<dl class="admin-list">';
-    foreach ($content as $item) {
-      $output .= '<dt>'. l($item['title'], $item['path'], $item) .'</dt>';
-      $output .= '<dd>'. $item['description'] .'</dd>';
-    }
-    $output .= '</dl>';
-  }
-  return $output;
-}
-
-/**
- * Menu callback; prints a listing of admin tasks for each installed module.
- */
-function system_admin_by_module() {
-  return 'This page awaits rewrite'; // TODO: this needs to be rewritten for the new menu system.
-  $modules = module_rebuild_cache();
-  $menu_items = array();
-  foreach ($modules as $file) {
-    $module = $file->name;
-    if ($module == 'help') {
-      continue;
-    }
-
-    $admin_tasks = system_get_module_admin_tasks($module);
-
-    // Only display a section if there are any available tasks.
-    if (count($admin_tasks)) {
-
-      // Check for help links.
-      if (module_invoke($module, 'help', "admin/help#$module")) {
-        $admin_tasks[100] = l(t('Get help'), "admin/help/$module");
-      }
-
-      // Sort.
-      ksort($admin_tasks);
-
-      $menu_items[$file->info['name']] = array($file->info['description'], $admin_tasks);
-    }
-  }
-  return theme('system_admin_by_module', $menu_items);
-}
-
-function system_get_module_admin_tasks($module) {
-  return array(); // TODO: this needs to be rewritten for the new menu system.
-  $admin_access = user_access('administer access control');
-  $menu = menu_get_menu();
-  $admin_tasks = array();
-
-  // Check for permissions.
-  if (module_hook($module, 'perm') && $admin_access) {
-    $admin_tasks[-1] = l(t('Configure permissions'), 'admin/user/access', array('fragment' => 'module-'. $module));
-  }
-
-  // Check for menu items that are admin links.
-  if ($items = module_invoke($module, 'menu', TRUE)) {
-    foreach ($items as $item) {
-      $parts = explode('/', $item['path']);
-      $n = count($parts);
-      if ((!isset($item['type']) || ($item['type'] & MENU_VISIBLE_IN_TREE)) && ($parts[0] == 'admin') && ($n >= 3) && _menu_item_is_accessible($menu['path index'][$item['path']])) {
-        $admin_tasks[$item['title']] = l($item['title'], $item['path']);
-      }
-    }
-  }
-
-  return $admin_tasks;
-}
-
-/**
- * Theme output of the dashboard page.
- */
-function theme_system_admin_by_module($menu_items) {
-  $stripe = 0;
-  $output = '';
-  $container = array();
-
-  // Iterate over all modules
-  foreach ($menu_items as $module => $block) {
-    list($description, $items) = $block;
-
-    // Output links
-    if (count($items)) {
-      $block = array();
-      $block['title'] = $module;
-      $block['content'] = theme('item_list', $items);
-      $block['description'] = t($description);
-
-      if ($block_output = theme('admin_block', $block)) {
-        if (!$block['position']) {
-          // Perform automatic striping.
-          $block['position'] = ++$stripe % 2 ? 'left' : 'right';
-        }
-        $container[$block['position']] .= $block_output;
-      }
-    }
-  }
-
-  $output = '<div class="admin">';
-  foreach ($container as $id => $data) {
-    $output .= '<div class="'. $id .' clear-block">';
-    $output .= $data;
-    $output .= '</div>';
-  }
-  $output .= '</div>';
-
-  return $output;
-}
-
-/**
- * Implementation of hook_cron().
- *
- * Remove older rows from flood table
- */
-function system_cron() {
-  // Cleanup the flood
-  db_query('DELETE FROM {flood} WHERE timestamp < %d', time() - 3600);
-}
-
Index: modules/system/system.pages.inc
===================================================================
RCS file: modules/system/system.pages.inc
diff -N modules/system/system.pages.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/system/system.pages.inc	30 Apr 2007 07:06:44 -0000
@@ -0,0 +1,1787 @@
+<?php
+// $Id: $
+
+/**
+ * Provide the administration overview page.
+ */
+function system_main_admin_page($arg = NULL) {
+  // If we received an argument, they probably meant some other page.
+  // Let's 404 them since the menu system cannot be told we do not
+  // accept arguments.
+  if (isset($arg) && substr($arg, 0, 3) != 'by-') {
+    return drupal_not_found();
+  }
+
+  // Check for status report errors.
+  if (system_status(TRUE)) {
+    drupal_set_message(t('One or more problems were detected with your Drupal installation. Check the <a href="@status">status report</a> for more information.', array('@status' => url('admin/logs/status'))), 'error');
+  }
+
+  $map = arg(NULL);
+  $result = db_query("SELECT * FROM {menu} WHERE path LIKE 'admin/%%' AND depth = 2 AND visible = 1 AND path != 'admin/help' ORDER BY mleft");
+  while ($item = db_fetch_object($result)) {
+    _menu_translate($item, $map, MENU_RENDER_LINK);
+    if (!$item->access) {
+      continue;
+    }
+    $block = (array)$item;
+    $block['content'] = '';
+    if ($item->block_callback && function_exists($item->block_callback)) {
+      $function = $item->block_callback;
+      $block['content'] .= $function();
+    }
+    $block['content'] .= theme('admin_block_content', system_admin_menu_block($item));
+    $blocks[] = $block;
+  }
+  return theme('admin_page', $blocks);
+}
+
+
+function system_admin_compact_page($mode = 'off') {
+  global $user;
+  user_save($user, array('admin_compact_mode' => ($mode == 'on')));
+  drupal_goto('admin');
+}
+
+/**
+ * This function allows selection of the theme to show in administration sections.
+ */
+function system_admin_theme_settings() {
+  $themes = system_theme_data();
+  ksort($themes);
+  $options[0] = t('System default');
+  foreach ($themes as $theme) {
+    $options[$theme->name] = $theme->info['name'];
+  }
+
+  $form['admin_theme'] = array(
+    '#type' => 'select',
+    '#options' => $options,
+    '#title' => t('Administration theme'),
+    '#description' => t('Choose which theme the administration pages should display in. If you choose "System default" the administration pages will use the same theme as the rest of the site.'),
+    '#default_value' => variable_get('admin_theme', '0'),
+  );
+
+  // In order to give it our own submit, we have to give it the default submit
+  // too because the presence of a #submit will prevent the default #submit
+  // from being used. Also we want ours first.
+  $form['#submit']['system_admin_theme_submit'] = array();
+  $form['#submit']['system_settings_form_submit'] = array();
+  return system_settings_form($form);
+}
+
+
+function system_admin_theme_submit($form_id, $form_values) {
+  // If we're changing themes, make sure the theme has its blocks initialized.
+  if ($form_values['admin_theme'] != variable_get('admin_theme', '0')) {
+    $result = db_query("SELECT status FROM {blocks} WHERE theme = '%s'", $form_values['admin_theme']);
+    if (!db_num_rows($result)) {
+      system_initialize_theme_blocks($form_values['admin_theme']);
+    }
+  }
+}
+
+function system_site_information_settings() {
+  $form['site_name'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Name'),
+    '#default_value' => variable_get('site_name', 'Drupal'),
+    '#description' => t('The name of this website.'),
+    '#required' => TRUE
+  );
+  $form['site_mail'] = array(
+    '#type' => 'textfield',
+    '#title' => t('E-mail address'),
+    '#default_value' => variable_get('site_mail', ini_get('sendmail_from')),
+    '#description' => t('A valid e-mail address to be used as the "From" address by the auto-mailer during registration, new password requests, notifications, etc.  To lessen the likelihood of e-mail being marked as spam, this e-mail address should use the same domain as the website.'),
+    '#required' => TRUE,
+  );
+  $form['site_slogan'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Slogan'),
+    '#default_value' => variable_get('site_slogan', ''),
+    '#description' => t('The slogan of this website. Some themes display a slogan when available.')
+  );
+
+  $form['site_mission'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Mission'),
+    '#default_value' => variable_get('site_mission', ''),
+    '#description' => t('Your site\'s mission statement or focus.')
+  );
+  $form['site_footer'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Footer message'),
+    '#default_value' => variable_get('site_footer', ''),
+    '#description' => t('This text will be displayed at the bottom of each page. Useful for adding a copyright notice to your pages.')
+  );
+  $form['anonymous'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Anonymous user'),
+    '#default_value' => variable_get('anonymous', t('Anonymous')),
+    '#description' => t('The name used to indicate anonymous users.')
+  );
+  $form['site_frontpage'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Default front page'),
+    '#default_value' => variable_get('site_frontpage', 'node'),
+    '#size' => 40,
+    '#description' => t('The home page displays content from this relative URL. If unsure, specify "node".'),
+    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
+  );
+
+  return system_settings_form($form);
+}
+
+function system_clean_url_settings() {
+  $form['clean_url'] = array(
+    '#type' => 'radios',
+    '#title' => t('Clean URLs'),
+    '#default_value' => variable_get('clean_url', 0),
+    '#options' => array(t('Disabled'), t('Enabled')),
+    '#description' => t('This option makes Drupal emit "clean" URLs (i.e. without <code>?q=</code> in the URL).'),
+  );
+
+  if (!variable_get('clean_url', 0)) {
+    if (strpos(request_uri(), '?q=') !== FALSE) {
+      drupal_add_js(array('cleanURL' => array('success' => t('Your server has been successfully tested to support this feature.'), 'failure' => t('Your system configuration does not currently support this feature. The <a href="http://drupal.org/node/15365">handbook page on Clean URLs</a> has additional troubleshooting information.'), 'testing' => t('Testing clean URLs...'))), 'setting');
+      drupal_add_js(drupal_get_path('module', 'system') .'/system.js', 'module');
+      drupal_add_js('
+// Global Killswitch
+if (Drupal.jsEnabled) {
+  $(document).ready(function() {
+    Drupal.cleanURLsSettingsCheck();
+  });
+}', 'inline');
+
+      $form['clean_url']['#description'] .= ' <span>'. t('Before enabling clean URLs, you must perform a test to determine if your server is properly configured. If you are able to see this page again after clicking the "Run the clean URL test" link, the test has succeeded and the radio buttons above will be available. If instead you are directed to a "Page not found" error, you will need to change the configuration of your server. The <a href="@handbook">handbook page on Clean URLs</a> has additional troubleshooting information.', array('@handbook' => 'http://drupal.org/node/15365')) .'</span>';
+
+      $form['clean_url']['#disabled'] = TRUE;
+      $form['clean_url']['#prefix'] = '<div id="clean-url">';
+      $form['clean_url']['#suffix'] = '<p>'. t('<a href="@clean_url">Run the clean url test</a>.', array('@clean_url' => base_path() .'admin/settings/clean-urls')) .'</p></div>';
+    }
+    else {
+      $form['clean_url']['#description'] .= ' '. t('Your server has been successfully tested to support this feature.');
+    }
+  }
+
+  return system_settings_form($form);
+}
+
+function system_error_reporting_settings() {
+
+  $form['site_403'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Default 403 (access denied) page'),
+    '#default_value' => variable_get('site_403', ''),
+    '#size' => 40,
+    '#description' => t('This page is displayed when the requested document is denied to the current user. If unsure, specify nothing.'),
+    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
+  );
+
+  $form['site_404'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Default 404 (not found) page'),
+    '#default_value' =>  variable_get('site_404', ''),
+    '#size' => 40,
+    '#description' => t('This page is displayed when no other content matches the requested document. If unsure, specify nothing.'),
+    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
+  );
+
+  $form['error_level'] = array(
+    '#type' => 'select', '#title' => t('Error reporting'), '#default_value' => variable_get('error_level', 1),
+    '#options' => array(t('Write errors to the log'), t('Write errors to the log and to the screen')),
+    '#description' =>  t('Where Drupal, PHP and SQL errors are logged. On a production server it is recommended that errors are only written to the error log. On a test server it can be helpful to write logs to the screen.')
+  );
+
+  return system_settings_form($form);
+}
+
+function system_performance_settings() {
+
+  $description = '<p>'. t("The normal cache mode is suitable for most sites and does not cause any side effects. The aggressive cache mode causes Drupal to skip the loading (init) and unloading (exit) of enabled modules when serving a cached page. This results in an additional performance boost but can cause unwanted side effects.") .'</p>';
+
+  $problem_modules = array_unique(array_merge(module_implements('init'), module_implements('exit')));
+  sort($problem_modules);
+
+  if (count($problem_modules) > 0) {
+    $description .= '<p>'. t('<strong class="error">The following enabled modules are incompatible with aggressive mode caching and will not function properly: %modules</strong>', array('%modules' => implode(', ', $problem_modules))) .'.</p>';
+  }
+  else {
+    $description .= '<p>'. t('<strong class="ok">Currently, all enabled modules are compatible with the aggressive caching policy.</strong> Please note, if you use aggressive caching and enable new modules, you will need to check this page again to ensure compatibility.') .'</p>';
+  }
+  $form['page_cache'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Page cache'),
+    '#description' => t('Enabling the cache will offer a significant performance boost. Drupal can store and send compressed cached pages requested by <em>anonymous</em> users. By caching a web page, Drupal does not have to construct the page each time someone wants to view it.'),
+  );
+
+  $form['page_cache']['cache'] = array(
+    '#type' => 'radios',
+    '#title' => t('Caching mode'),
+    '#default_value' => variable_get('cache', CACHE_DISABLED),
+    '#options' => array(CACHE_DISABLED => t('Disabled'), CACHE_NORMAL => t('Normal (recommended, no side effects)'), CACHE_AGGRESSIVE => t('Aggressive (experts only, possible side effects)')),
+    '#description' => $description
+  );
+
+  $period = drupal_map_assoc(array(0, 60, 180, 300, 600, 900, 1800, 2700, 3600, 10800, 21600, 32400, 43200, 86400), 'format_interval');
+  $period[0] = t('none');
+  $form['page_cache']['cache_lifetime'] = array(
+    '#type' => 'select',
+    '#title' => t('Minimum cache lifetime'),
+    '#default_value' => variable_get('cache_lifetime', 0),
+    '#options' => $period,
+    '#description' => t('On high-traffic sites it can become necessary to enforce a minimum cache lifetime. The minimum cache lifetime is the minimum amount of time that will go by before the cache is emptied and recreated. A larger minimum cache lifetime offers better performance, but users will not see new content for a longer period of time.')
+  );
+
+  $form['bandwidth_optimizations'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Bandwidth optimizations'),
+    '#description' => t('These options can help reduce both the size and number of requests made to your website. This can reduce the server load, the bandwidth used, and the average page loading time for your visitors.')
+  );
+
+  $directory = file_directory_path();
+  $is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC);
+  $form['bandwidth_optimizations']['preprocess_css'] = array(
+    '#type' => 'radios',
+    '#title' => t('Aggregate and compress CSS files'),
+    '#default_value' => variable_get('preprocess_css', FALSE) && $is_writable,
+    '#disabled' => !$is_writable,
+    '#options' => array(t('Disabled'), t('Enabled')),
+    '#description' => t("Some Drupal modules include their own CSS files. When these modules are enabled, each module's CSS file adds an additional HTTP request to the page, which can increase the load time of each page. These HTTP requests can also slightly increase server load. It is recommended to only turn this option on when your site is in production, as it can interfere with theme development. This option is disabled if you have not set up your files directory, or if your download method is set to private."),
+  );
+
+  $form['#submit']['system_settings_form_submit'] = array();
+  $form['#submit']['drupal_clear_css_cache'] = array();
+
+  return system_settings_form($form);
+}
+
+function system_file_system_settings() {
+
+  $form['file_directory_path'] = array(
+    '#type' => 'textfield',
+    '#title' => t('File system path'),
+    '#default_value' => file_directory_path(),
+    '#maxlength' => 255,
+    '#description' => t('A file system path where the files will be stored. This directory has to exist and be writable by Drupal. If the download method is set to public this directory has to be relative to the Drupal installation directory, and be accessible over the web. When download method is set to private this directory should not be accessible over the web. Changing this location after the site has been in use will cause problems so only change this setting on an existing site if you know what you are doing.'),
+    '#after_build' => array('system_check_directory'),
+  );
+
+  $form['file_directory_temp'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Temporary directory'),
+    '#default_value' => file_directory_temp(),
+    '#maxlength' => 255,
+    '#description' => t('Location where uploaded files will be kept during previews. Relative paths will be resolved relative to the Drupal installation directory.'),
+    '#after_build' => array('system_check_directory'),
+  );
+
+  $form['file_downloads'] = array(
+    '#type' => 'radios',
+    '#title' => t('Download method'),
+    '#default_value' => variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC),
+    '#options' => array(FILE_DOWNLOADS_PUBLIC => t('Public - files are available using HTTP directly.'), FILE_DOWNLOADS_PRIVATE => t('Private - files are transferred by Drupal.')),
+    '#description' => t('If you want any sort of access control on the downloading of files, this needs to be set to <em>private</em>. You can change this at any time, however all download URLs will change and there may be unexpected problems so it is not recommended.')
+  );
+
+  return system_settings_form($form);
+}
+
+function system_image_toolkit_settings() {
+  $toolkits_available = image_get_available_toolkits();
+  if (count($toolkits_available) > 1) {
+    $form['image_toolkit'] = array(
+      '#type' => 'radios',
+      '#title' => t('Select an image processing toolkit'),
+      '#default_value' => variable_get('image_toolkit', image_get_toolkit()),
+      '#options' => $toolkits_available
+    );
+  }
+  else {
+    $form['image_toolkit'] = array('#value' => '<p>'. t("No image toolkits found. Drupal will use PHP's built-in GD library for image handling.") .'</p>');
+  }
+  $form['image_toolkit_settings'] = image_toolkit_invoke('settings');
+  return system_settings_form($form);
+}
+
+function system_rss_feeds_settings() {
+
+  $form['feed_default_items'] = array(
+    '#type' => 'select',
+    '#title' => t('Number of items per feed'),
+    '#default_value' => variable_get('feed_default_items', 10),
+    '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30)),
+    '#description' => t('The default number of items to include in a feed.')
+  );
+  $form['feed_item_length'] = array(
+    '#type' => 'select',
+    '#title' => t('Display of XML feed items'),
+    '#default_value' => variable_get('feed_item_length', 'teaser'),
+    '#options' => array('title' => t('Titles only'), 'teaser' => t('Titles plus teaser'), 'fulltext' => t('Full text')),
+    '#description' => t('Global setting for the length of XML feed items that are output by default.')
+  );
+
+  return system_settings_form($form);
+}
+
+function system_date_time_settings() {
+  // Date settings:
+  $zones = _system_zonelist();
+
+  // Date settings: possible date formats
+  $dateshort = array('Y-m-d H:i', 'm/d/Y - H:i', 'd/m/Y - H:i', 'Y/m/d - H:i',
+           'd.m.Y - H:i', 'm/d/Y - g:ia', 'd/m/Y - g:ia', 'Y/m/d - g:ia',
+           'M j Y - H:i', 'j M Y - H:i', 'Y M j - H:i',
+           'M j Y - g:ia', 'j M Y - g:ia', 'Y M j - g:ia');
+  $datemedium = array('D, Y-m-d H:i', 'D, m/d/Y - H:i', 'D, d/m/Y - H:i',
+          'D, Y/m/d - H:i', 'F j, Y - H:i', 'j F, Y - H:i', 'Y, F j - H:i',
+          'D, m/d/Y - g:ia', 'D, d/m/Y - g:ia', 'D, Y/m/d - g:ia',
+          'F j, Y - g:ia', 'j F Y - g:ia', 'Y, F j - g:ia', 'j. F Y - G:i');
+  $datelong = array('l, F j, Y - H:i', 'l, j F, Y - H:i', 'l, Y,  F j - H:i',
+        'l, F j, Y - g:ia', 'l, j F Y - g:ia', 'l, Y,  F j - g:ia', 'l, j. F Y - G:i');
+
+  // Date settings: construct choices for user
+  foreach ($dateshort as $f) {
+    $dateshortchoices[$f] = format_date(time(), 'custom', $f);
+  }
+  foreach ($datemedium as $f) {
+    $datemediumchoices[$f] = format_date(time(), 'custom', $f);
+  }
+  foreach ($datelong as $f) {
+    $datelongchoices[$f] = format_date(time(), 'custom', $f);
+  }
+
+  $form['date_default_timezone'] = array(
+    '#type' => 'select',
+    '#title' => t('Default time zone'),
+    '#default_value' => variable_get('date_default_timezone', 0),
+    '#options' => $zones,
+    '#description' => t('Select the default site time zone.')
+  );
+
+  $form['configurable_timezones'] = array(
+    '#type' => 'radios',
+    '#title' => t('Configurable time zones'),
+    '#default_value' => variable_get('configurable_timezones', 1),
+    '#options' => array(t('Disabled'), t('Enabled')),
+    '#description' => t('Enable or disable user-configurable time zones. When enabled, users can set their own time zone and dates will be updated accordingly.')
+  );
+
+  $form['date_format_short'] = array(
+    '#type' => 'select',
+    '#title' => t('Short date format'),
+    '#default_value' => variable_get('date_format_short', $dateshort[1]),
+    '#options' => $dateshortchoices,
+    '#description' => t('The short format of date display.')
+  );
+
+  $form['date_format_medium'] = array(
+    '#type' => 'select',
+    '#title' => t('Medium date format'),
+    '#default_value' => variable_get('date_format_medium', $datemedium[1]),
+    '#options' => $datemediumchoices,
+    '#description' => t('The medium sized date display.')
+  );
+
+  $form['date_format_long'] = array(
+    '#type' => 'select',
+    '#title' => t('Long date format'),
+    '#default_value' => variable_get('date_format_long', $datelong[0]),
+    '#options' => $datelongchoices,
+    '#description' => t('Longer date format used for detailed display.')
+  );
+
+  $form['date_first_day'] = array(
+    '#type' => 'select',
+    '#title' => t('First day of week'),
+    '#default_value' => variable_get('date_first_day', 0),
+    '#options' => array(0 => t('Sunday'), 1 => t('Monday'), 2 => t('Tuesday'), 3 => t('Wednesday'), 4 => t('Thursday'), 5 => t('Friday'), 6 => t('Saturday')),
+    '#description' => t('The first day of the week for calendar views.')
+  );
+
+  return system_settings_form($form);
+}
+
+function system_site_maintenance_settings() {
+
+  $form['site_offline'] = array(
+    '#type' => 'radios',
+    '#title' => t('Site status'),
+    '#default_value' => variable_get('site_offline', 0),
+    '#options' => array(t('Online'), t('Off-line')),
+    '#description' => t('When set to "Online", all visitors will be able to browse your site normally. When set to "Off-line", only users with the "administer site configuration" permission will be able to access your site to perform maintenance; all other visitors will see the site off-line message configured below. Authorized users can log in during "Off-line" mode directly via the <a href="@user-login">user login</a> page.', array('@user-login' => url('user'))),
+  );
+
+  $form['site_offline_message'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Site off-line message'),
+    '#default_value' => variable_get('site_offline_message', t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => variable_get('site_name', 'Drupal')))),
+    '#description' => t('Message to show visitors when the site is in off-line mode.')
+  );
+
+  return system_settings_form($form);
+}
+
+/**
+ * Checks the existence of the directory specified in $form_element. This
+ * function is called from the system_settings form to check both the
+ * file_directory_path and file_directory_temp directories. If validation
+ * fails, the form element is flagged with an error from within the
+ * file_check_directory function.
+ *
+ * @param $form_element
+ *   The form element containing the name of the directory to check.
+ */
+function system_check_directory($form_element) {
+  file_check_directory($form_element['#value'], FILE_CREATE_DIRECTORY, $form_element['#parents'][0]);
+  return $form_element;
+}
+
+/**
+ * Retrieves the current status of an array of files in the system table.
+ */
+function system_get_files_database(&$files, $type) {
+  // Extract current files from database.
+  $result = db_query("SELECT filename, name, type, status, throttle, schema_version FROM {system} WHERE type = '%s'", $type);
+  while ($file = db_fetch_object($result)) {
+    if (isset($files[$file->name]) && is_object($files[$file->name])) {
+      $file->old_filename = $file->filename;
+      foreach ($file as $key => $value) {
+        if (!isset($files[$file->name]) || !isset($files[$file->name]->$key)) {
+          $files[$file->name]->$key = $value;
+        }
+      }
+    }
+  }
+}
+
+function system_theme_default() {
+  // Prepare defaults for themes.
+  return array(
+    'regions' => array(
+      'left' => 'Left sidebar',
+      'right' => 'Right sidebar',
+      'content' => 'Content',
+      'header' => 'Header',
+      'footer' => 'Footer',
+    ),
+    'description' => '',
+    'features' => array(
+      'comment_user_picture',
+      'favicon',
+      'mission',
+      'logo',
+      'name',
+      'node_user_picture',
+      'search',
+      'slogan'
+    ),
+  );
+}
+
+/**
+ * Collect data about all currently available themes
+ */
+function system_theme_data() {
+  include_once './includes/install.inc';
+
+  // Find themes
+  $themes = drupal_system_listing('\.theme$', 'themes');
+
+  // Find theme engines
+  $engines = drupal_system_listing('\.engine$', 'themes/engines');
+
+  // can't iterate over array itself as it uses a copy of the array items
+  foreach (array_keys($themes) as $key) {
+    drupal_get_filename('theme', $themes[$key]->name, $themes[$key]->filename);
+    drupal_load('theme', $themes[$key]->name);
+    $themes[$key]->owner = $themes[$key]->filename;
+    $themes[$key]->prefix = $key;
+  }
+
+  // Remove all theme engines from the system table
+  db_query("DELETE FROM {system} WHERE type = 'theme_engine'");
+
+  foreach ($engines as $engine) {
+    // Insert theme engine into system table
+    drupal_get_filename('theme_engine', $engine->name, $engine->filename);
+    drupal_load('theme_engine', $engine->name);
+    db_query("INSERT INTO {system} (name, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', %d, %d, %d)", $engine->name, 'theme_engine', $engine->filename, 1, 0, 0);
+
+    // Add templates to the site listing
+    foreach (call_user_func($engine->name .'_templates') as $template) {
+      // Do not double-insert templates with theme files in their directory,
+      // but do register their engine data.
+      if (array_key_exists($template->name, $themes)) {
+        $themes[$template->name]->template = TRUE;
+        $themes[$template->name]->owner = $engine->filename;
+        $themes[$template->name]->prefix = $engine->name;
+      }
+      else {
+        $template->template = TRUE;
+        $template->name = basename(dirname($template->filename));
+        $template->owner = $engine->filename;
+        $template->prefix = $engine->name;
+
+        $themes[$template->name] = $template;
+      }
+    }
+  }
+
+  // Find styles in each theme's directory.
+  foreach ($themes as $theme) {
+    foreach (file_scan_directory(dirname($theme->filename), 'style.css$') as $style) {
+      $style->style = TRUE;
+      $style->template = isset($theme->template) ? $theme->template : FALSE;
+      $style->name = basename(dirname($style->filename));
+      $style->owner = $theme->filename;
+      $style->prefix = !empty($theme->template) ? $theme->prefix : $theme->name;
+      // do not double-insert styles with theme files in their directory
+      if (array_key_exists($style->name, $themes)) {
+        continue;
+      }
+      $themes[$style->name] = $style;
+    }
+  }
+
+  // Extract current files from database.
+  system_get_files_database($themes, 'theme');
+
+  $defaults = system_theme_default();
+  // Read info files for the owner
+  foreach (array_keys($themes) as $key) {
+    $themes[$key]->info = drupal_parse_info_file(dirname($themes[$key]->filename) .'/'. $themes[$key]->name .'.info') + $defaults;
+  }
+
+  db_query("DELETE FROM {system} WHERE type = 'theme'");
+
+  foreach ($themes as $theme) {
+    db_query("INSERT INTO {system} (name, owner, info, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', '%s', %d, %d, %d)", $theme->name, $theme->owner, serialize($theme->info), 'theme', $theme->filename, isset($theme->status) ? $theme->status : 0, 0, 0);
+  }
+
+  return $themes;
+}
+
+
+function system_theme_settings_submit($form_id, $form_values) {
+  $op = isset($_POST['op']) ? $_POST['op'] : '';
+  $key = $form_values['var'];
+
+  // Exclude unnecessary elements.
+  unset($form_values['var'], $form_values['submit'], $form_values['reset'], $form_values['form_id']);
+
+  if ($op == t('Reset to defaults')) {
+    variable_del($key);
+    drupal_set_message(t('The configuration options have been reset to their default values.'));
+  }
+  else {
+    variable_set($key, $form_values);
+    drupal_set_message(t('The configuration options have been saved.'));
+  }
+
+  cache_clear_all();
+}
+
+/**
+ * Execute the system_settings_form.
+ *
+ * If you want node type configure style handling of your checkboxes,
+ * add an array_filter value to your form.
+ *
+ */
+function system_settings_form_submit($form_id, $form_values) {
+  $op = isset($form_values['op']) ? $form_values['op'] : '';
+
+  // Exclude unnecessary elements.
+  unset($form_values['submit'], $form_values['reset'], $form_values['form_id'], $form_values['op'], $form_values['form_token']);
+
+  foreach ($form_values as $key => $value) {
+    if ($op == t('Reset to defaults')) {
+      variable_del($key);
+    }
+    else {
+      if (is_array($value) && isset($form_values['array_filter'])) {
+        $value = array_keys(array_filter($value));
+      }
+      variable_set($key, $value);
+    }
+  }
+  if ($op == t('Reset to defaults')) {
+    drupal_set_message(t('The configuration options have been reset to their default values.'));
+  }
+  else {
+    drupal_set_message(t('The configuration options have been saved.'));
+  }
+
+  drupal_rebuild_theme_registry();
+}
+
+/**
+ * Menu callback; displays a listing of all themes.
+ */
+function system_themes_form() {
+
+  drupal_clear_css_cache();
+  $themes = system_theme_data();
+  ksort($themes);
+  $status = array();
+
+  foreach ($themes as $theme) {
+    $theme->screenshot = dirname($theme->filename) .'/screenshot.png';
+    $screenshot = file_exists($theme->screenshot) ? theme('image', $theme->screenshot, t('Screenshot for %theme theme', array('%theme' => $theme->info['name'])), '', array('class' => 'screenshot'), FALSE) : t('no screenshot');
+
+    $form[$theme->name]['screenshot'] = array('#value' => $screenshot);
+    $form[$theme->name]['info'] = array('#type' => 'value', '#value' => $theme->info);
+    $options[$theme->name] = '';
+    if (!empty($theme->status)) {
+      $status[] = $theme->name;
+    }
+    if (!empty($theme->status)) {
+      $form[$theme->name]['operations'] = array('#value' => l(t('configure'), 'admin/build/themes/settings/'. $theme->name) );
+    }
+    else {
+      // Dummy element for drupal_render. Cleaner than adding a check in the theme function.
+      $form[$theme->name]['operations'] = array();
+    }
+  }
+
+  $form['status'] = array('#type' => 'checkboxes', '#options' => $options, '#default_value' => $status);
+  $form['theme_default'] = array('#type' => 'radios', '#options' => $options, '#default_value' => variable_get('theme_default', 'garland'));
+  $form['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration') );
+  $form['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset to defaults') );
+
+  return $form;
+}
+
+function theme_system_themes_form($form) {
+  foreach (element_children($form) as $key) {
+    // Only look for themes
+    if (!isset($form[$key]['info'])) {
+      continue;
+    }
+
+    // Fetch info
+    $info = $form[$key]['info']['#value'];
+
+    // Style theme info
+    $theme = '<div class="theme-info"><h2>'. $info['name'] .'</h2><div class="description">'. $info['description'] .'</div></div>';
+
+    // Build rows
+    $row = array();
+    $row[] = drupal_render($form[$key]['screenshot']);
+    $row[] = $theme;
+    $row[] = $info['version'];
+    $row[] = array('data' => drupal_render($form['status'][$key]), 'align' => 'center');
+    if ($form['theme_default']) {
+      $row[] = array('data' => drupal_render($form['theme_default'][$key]), 'align' => 'center');
+      $row[] = array('data' => drupal_render($form[$key]['operations']), 'align' => 'center');
+    }
+    $rows[] = $row;
+  }
+
+  $header = array(t('Screenshot'), t('Name'), t('Version'), t('Enabled'), t('Default'), t('Operations'));
+  $output = theme('table', $header, $rows);
+  $output .= drupal_render($form);
+  return $output;
+}
+
+
+function system_themes_form_submit($form_id, $form_values) {
+
+  db_query("UPDATE {system} SET status = 0 WHERE type = 'theme'");
+
+  if ($form_values['op'] == t('Save configuration')) {
+    if (is_array($form_values['status'])) {
+      foreach ($form_values['status'] as $key => $choice) {
+        // Always enable the default theme, despite its status checkbox being checked:
+        if ($choice || $form_values['theme_default'] == $key) {
+          system_initialize_theme_blocks($key);
+          db_query("UPDATE {system} SET status = 1 WHERE type = 'theme' and name = '%s'", $key);
+        }
+      }
+    }
+    if (($admin_theme = variable_get('admin_theme', '0')) != '0' && $admin_theme != $form_values['theme_default']) {
+      drupal_set_message(t('Please note that the <a href="!admin_theme_page">administration theme</a> is still set to the %admin_theme theme; consequently, the theme on this page remains unchanged. All non-administrative sections of the site, however, will show the selected %selected_theme theme by default.', array(
+        '!admin_theme_page' => url('admin/settings/admin'),
+        '%admin_theme' => $admin_theme,
+        '%selected_theme' => $form_values['theme_default'],
+      )));
+    }
+    variable_set('theme_default', $form_values['theme_default']);
+  }
+  else {
+    variable_del('theme_default');
+    db_query("UPDATE {system} SET status = 1 WHERE type = 'theme' AND name = 'garland'");
+  }
+
+  list_themes(TRUE);
+  menu_rebuild();
+  drupal_set_message(t('The configuration options have been saved.'));
+  return 'admin/build/themes';
+}
+
+/**
+ * Menu callback; provides module enable/disable interface.
+ *
+ * Modules can be enabled or disabled and set for throttling if the throttle module is enabled.
+ * The list of modules gets populated by module.info files, which contain each module's name,
+ * description and dependencies.
+ * @sa drupal_parse_info_file for information on module.info descriptors.
+ *
+ * Dependency checking is performed to ensure that a module cannot be enabled if the module has
+ * disabled dependencies and also to ensure that the module cannot be disabled if the module has
+ * enabled dependents.
+ *
+ * @return
+ *   The form array.
+ */
+function system_modules($form_values = NULL) {
+  // Get current list of modules.
+  $files = module_rebuild_cache();
+  if ($confirm_form = system_modules_confirm_form($files, $form_values)) {
+    return $confirm_form;
+  }
+
+  // Store module list for validation callback.
+  $form['validation_modules'] = array('#type' => 'value', '#value' => $files);
+
+  // Create storage for disabled modules as browser will disable checkboxes.
+  $form['disabled_modules'] = array('#type' => 'value', '#value' => array());
+
+  // Array for disabling checkboxes in callback system_module_disable.
+  $disabled = array();
+  $throttle = array();
+  // Traverse the files retrieved and build the form.
+  foreach ($files as $filename => $file) {
+    $form['name'][$filename] = array('#value' => $file->info['name']);
+    $form['version'][$filename] = array('#value' => $file->info['version']);
+    $form['description'][$filename] = array('#value' => t($file->info['description']));
+    $options[$filename] = '';
+    if ($file->status) {
+      $status[] = $file->name;
+    }
+    if ($file->throttle) {
+      $throttle[] = $file->name;
+    }
+
+    $dependencies = array();
+    // Check for missing dependencies.
+    if (is_array($file->info['dependencies'])) {
+      foreach ($file->info['dependencies'] as $dependency) {
+        if (!isset($files[$dependency]) || !$files[$dependency]->status) {
+          if (isset($files[$dependency])) {
+            $dependencies[] = $files[$dependency]->info['name'] . t(' (<span class="admin-disabled">disabled</span>)');
+          }
+          else {
+            $dependencies[] = drupal_ucfirst($dependency) . t(' (<span class="admin-missing">missing</span>)');
+            $disabled[] = $filename;
+            $form['disabled_modules']['#value'][$filename] = FALSE;
+          }
+        }
+        else {
+          $dependencies[] = $files[$dependency]->info['name'] . t(' (<span class="admin-enabled">enabled</span>)');
+        }
+      }
+
+      // Add text for dependencies.
+      if (!empty($dependencies)) {
+        $form['description'][$filename]['dependencies'] = array(
+          '#value' => t('Depends on: !dependencies', array('!dependencies' => implode(', ', $dependencies))),
+          '#prefix' => '<div class="admin-dependencies">',
+          '#suffix' => '</div>',
+        );
+      }
+    }
+
+    // Mark dependents disabled so user can not remove modules being depended on.
+    $dependents = array();
+    foreach ($file->info['dependents'] as $dependent) {
+      if ($files[$dependent]->status == 1) {
+        $dependents[] = $files[$dependent]->info['name'] . t(' (<span class="admin-enabled">enabled</span>)');
+        $disabled[] = $filename;
+        $form['disabled_modules']['#value'][$filename] = TRUE;
+      }
+      else {
+        $dependents[] = $files[$dependent]->info['name'] . t(' (<span class="admin-disabled">disabled</span>)');
+      }
+    }
+
+    // Add text for enabled dependents.
+    if (!empty($dependents)) {
+      $form['description'][$filename]['required'] = array(
+        '#value' => t('Required by: !required', array('!required' => implode(', ', $dependents))),
+        '#prefix' => '<div class="admin-required">',
+        '#suffix' => '</div>',
+      );
+    }
+  }
+
+  $modules_required = drupal_required_modules();
+  // Merge in required modules.
+  foreach ($modules_required as $required) {
+    $disabled[] = $required;
+    $form['disabled_modules']['#value'][$required] = TRUE;
+  }
+
+  // Handle status checkboxes, including overriding
+  // the generated checkboxes for required modules.
+  $form['status'] = array(
+    '#type' => 'checkboxes',
+    '#default_value' => $status,
+    '#options' => $options,
+    '#process' => array(
+      'expand_checkboxes' => array(),
+      'system_modules_disable' => array($disabled),
+    ),
+  );
+
+  // Handle throttle checkboxes, including overriding the
+  // generated checkboxes for required modules.
+  if (module_exists('throttle')) {
+    $form['throttle'] = array(
+      '#type' => 'checkboxes',
+      '#default_value' => $throttle,
+      '#options' => $options,
+      '#process' => array(
+        'expand_checkboxes' => array(),
+        'system_modules_disable' => array(array_merge($modules_required, array('throttle'))),
+      ),
+    );
+  }
+
+  $form['buttons']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save configuration'),
+  );
+  $form['#multistep'] = TRUE;
+  $form['#action'] = url('admin/build/modules/list/confirm');
+
+  return $form;
+}
+
+/**
+ * Form process callback function to disable check boxes.
+ */
+function system_modules_disable($form, $edit, $disabled) {
+  foreach ($disabled as $key) {
+    $form[$key]['#attributes']['disabled'] = 'disabled';
+  }
+  return $form;
+}
+
+function system_modules_confirm_form($modules, $form_values = array()) {
+  $form = array();
+  $items = array();
+
+  // Check values for submitted dependency errors.
+  if ($dependencies = system_module_build_dependencies($modules, $form_values)) {
+    // preserve the already switched on modules
+    foreach ($modules as $name => $module) {
+      if ($module->status) {
+        $form['status'][$name] = array('#type' => 'hidden', '#value' => 1);
+      }
+    }
+
+    $form['validation_modules'] = array('#type' => 'value', '#value' => $modules);
+    $form['status']['#tree'] = TRUE;
+    foreach ($dependencies as $name => $missing_dependencies) {
+      $form['status'][$name] = array('#type' => 'hidden', '#value' => 1);
+      foreach ($missing_dependencies as $k => $dependency) {
+        $form['status'][$dependency] = array('#type' => 'hidden', '#value' => 1);
+        $info = $modules[$dependency]->info;
+        $missing_dependencies[$k] = $info['name'] ? $info['name'] : drupal_ucfirst($dependency);
+      }
+      $t_argument = array(
+        '@module' => $modules[$name]->info['name'],
+        '@dependencies' => implode(', ', $missing_dependencies),
+      );
+      $items[] = format_plural(count($missing_dependencies), 'You must enable the @dependencies module to install @module.', 'You must enable the @dependencies modules to install @module.', $t_argument);
+    }
+    $form['text'] = array('#value' => theme('item_list', $items));
+  }
+
+  if ($form) {
+    // Set some default form values
+    $form = confirm_form(
+      $form,
+      t('Some required modules must be enabled'),
+      'admin/build/modules',
+      t('Would you like to continue with enabling the above?'),
+      t('Continue'),
+      t('Cancel'));
+    return $form;
+  }
+}
+
+function system_module_build_dependencies($modules, $form_values) {
+  static $dependencies;
+
+  if (!isset($dependencies) && isset($form_values)) {
+    $dependencies = array();
+    foreach ($modules as $name => $module) {
+      // If the module is disabled, will be switched on and it has dependencies.
+      if (!$module->status && $form_values['status'][$name] && isset($module->info['dependencies'])) {
+        foreach ($module->info['dependencies'] as $dependency) {
+          if (!$form_values['status'][$dependency] && isset($modules[$dependency])) {
+            if (!isset($dependencies[$name])) {
+              $dependencies[$name] = array();
+            }
+            $dependencies[$name][] = $dependency;
+          }
+        }
+      }
+    }
+  }
+  return $dependencies;
+}
+
+/**
+ * Submit callback; handles modules form submission.
+ */
+function system_modules_submit($form_id, $form_values) {
+  include_once './includes/install.inc';
+  $new_modules = array();
+
+  // Merge in disabled active modules since they should be enabled.
+  // They don't appear because disabled checkboxes are not submitted
+  // by browsers.
+  $form_values['status'] = array_merge($form_values['status'], $form_values['disabled_modules']);
+
+  // Check values for dependency that we can't install.
+  if ($dependencies = system_module_build_dependencies($form_values['validation_modules'], $form_values)) {
+    // These are the modules that depend on existing modules.
+    foreach (array_keys($dependencies) as $name) {
+      $form_values['status'][$name] = 0;
+    }
+  }
+
+  $enable_modules = array();
+  $disable_modules = array();
+  foreach ($form_values['status'] as $key => $choice) {
+    if ($choice) {
+      if (drupal_get_installed_schema_version($key) == SCHEMA_UNINSTALLED) {
+        $new_modules[] = $key;
+      }
+      else {
+        $enable_modules[] = $key;
+      }
+    }
+    else {
+      $disable_modules[] = $key;
+    }
+  }
+
+  $old_module_list = module_list();
+
+  if (!empty($enable_modules)) {
+    module_enable($enable_modules);
+  }
+  if (!empty($disable_modules)) {
+    module_disable($disable_modules);
+  }
+
+  // Install new modules.
+  foreach ($new_modules as $key => $module) {
+    if (!drupal_check_module($module)) {
+      unset($new_modules[$key]);
+    }
+  }
+  drupal_install_modules($new_modules);
+
+  $current_module_list = module_list(TRUE, FALSE);
+
+  if (isset($form_values['throttle'])) {
+    foreach ($form_values['throttle'] as $key => $choice) {
+      db_query("UPDATE {system} SET throttle = %d WHERE type = 'module' and name = '%s'", $choice ? 1 : 0, $key);
+    }
+  }
+
+  if ($old_module_list != $current_module_list) {
+    drupal_rebuild_theme_registry();
+    menu_rebuild();
+    node_types_rebuild();
+    drupal_set_message(t('The configuration options have been saved.'));
+  }
+
+  // If there where unmet dependencies and they haven't confirmed don't redirect.
+  if ($dependencies && !isset($form_values['confirm'])) {
+    return FALSE;
+  }
+
+  drupal_clear_css_cache();
+
+  return 'admin/build/modules';
+}
+
+/**
+ * Theme call back for the modules form.
+ */
+function theme_system_modules($form) {
+  if (isset($form['confirm'])) {
+    return drupal_render($form);
+  }
+
+  // Individual table headers.
+  $header = array(t('Enabled'));
+  if (module_exists('throttle')) {
+    $header[] = t('Throttle');
+  }
+  $header[] = t('Name');
+  $header[] = t('Version');
+  $header[] = t('Description');
+
+  // Pull package information from module list and start grouping modules.
+  $modules = $form['validation_modules']['#value'];
+  foreach ($modules as $module) {
+    if (!isset($module->info['package']) || !$module->info['package']) {
+      $module->info['package'] = t('Other');
+    }
+    $packages[$module->info['package']][$module->name] = $module->info;
+  }
+  ksort($packages);
+
+  // Display packages.
+  $output = '';
+  foreach ($packages as $package => $modules) {
+    $rows = array();
+    foreach ($modules as $key => $module) {
+      $row = array();
+      $row[] = array('data' => drupal_render($form['status'][$key]), 'align' => 'center');
+
+      if (module_exists('throttle')) {
+        $row[] = array('data' => drupal_render($form['throttle'][$key]), 'align' => 'center');
+      }
+      $row[] = '<strong>'. drupal_render($form['name'][$key]) .'</strong>';
+      $row[] = drupal_render($form['version'][$key]);
+      $row[] = array('data' => drupal_render($form['description'][$key]), 'class' => 'description');
+      $rows[] = $row;
+    }
+    $fieldset = array(
+      '#title' => t($package),
+      '#collapsible' => TRUE,
+      '#collapsed' => ($package == 'Core - required'),
+      '#value' => theme('table', $header, $rows, array('class' => 'package')),
+    );
+    $output .= theme('fieldset', $fieldset);
+  }
+
+  $output .= drupal_render($form);
+  return $output;
+}
+
+/**
+ * Uninstall functions
+ */
+
+/**
+ * Builds a form of currently disabled modules.
+ *
+ * @param
+ *   $form_values Submitted form values.
+ * @return
+ *   A form array representing the currently disabled modules.
+ */
+function system_modules_uninstall($form_values = NULL) {
+  // Make sure the install API is available.
+  include_once './includes/install.inc';
+
+  // Display the confirm form if any modules have been submitted.
+  if ($confirm_form = system_modules_uninstall_confirm_form($form_values)) {
+    return $confirm_form;
+  }
+
+  $form = array();
+
+  // Pull all disabled modules from the system table.
+  $disabled_modules = db_query("SELECT name, filename, info FROM {system} WHERE type = 'module' AND status = 0 AND schema_version > %d ORDER BY name", SCHEMA_UNINSTALLED);
+  while ($module = db_fetch_object($disabled_modules)) {
+
+    // Grab the module info
+    $info = unserialize($module->info);
+
+    // Load the .install file, and check for an uninstall hook.
+    // If the hook exists, the module can be uninstalled.
+    module_load_install($module->name);
+    if (module_hook($module->name, 'uninstall')) {
+      $form['modules'][$module->name]['name'] = array('#value' => $info['name'] ? $info['name'] : $module->name);
+      $form['modules'][$module->name]['description'] = array('#value' => t($info['description']));
+      $options[$module->name] = '';
+    }
+  }
+
+  // Only build the rest of the form if there are any modules available to uninstall.
+  if (!empty($options)) {
+    $form['uninstall'] = array(
+      '#type' => 'checkboxes',
+      '#options' => $options,
+    );
+    $form['buttons']['submit'] = array(
+      '#type' => 'button',
+      '#value' => t('Uninstall'),
+    );
+    $form['#multistep'] = TRUE;
+    $form['#action'] = url('admin/build/modules/uninstall/confirm');
+  }
+  else {
+    $form['modules'] = array();
+  }
+
+  return $form;
+}
+
+/**
+ * Confirm uninstall of selected modules.
+ *
+ * @param
+ *   $form_values Submitted form values.
+ * @return
+ *   A form array representing modules to confirm.
+ */
+function system_modules_uninstall_confirm_form($form_values) {
+  // Nothing to build.
+  if (!isset($form_values)) {
+    return;
+  }
+
+  // Construct the hidden form elements and list items.
+  foreach (array_filter($form_values['uninstall']) as $module => $value) {
+    $info = drupal_parse_info_file(dirname(drupal_get_filename('module', $module)) .'/'. $module .'.info');
+    $uninstall[] = $info['name'];
+    $form['uninstall'][$module] = array('#type' => 'hidden',
+      '#value' => 1,
+    );
+  }
+
+  // Display a confirm form if modules have been selected.
+  if (isset($uninstall)) {
+    $form['uninstall']['#tree'] = TRUE;
+    $form['#multistep'] = TRUE;
+    $form['modules'] = array('#value' => '<p>'. t('The following modules will be completely uninstalled from your site, and <em>all data from these modules will be lost</em>!') .'</p>'. theme('item_list', $uninstall));
+    $form = confirm_form(
+      $form,
+      t('Confirm uninstall'),
+      'admin/build/modules/uninstall',
+      t('Would you like to continue with uninstalling the above?'),
+      t('Uninstall'),
+      t('Cancel'));
+    return $form;
+  }
+}
+
+/**
+ * Themes a table of currently disabled modules.
+ *
+ * @param
+ *   $form The form array representing the currently disabled modules.
+ * @return
+ *   An HTML string representing the table.
+ */
+function theme_system_modules_uninstall($form) {
+  // No theming for the confirm form.
+  if (isset($form['confirm'])) {
+    return drupal_render($form);
+  }
+
+  // Table headers.
+  $header = array(t('Uninstall'),
+    t('Name'),
+    t('Description'),
+  );
+
+  // Display table.
+  $rows = array();
+  foreach (element_children($form['modules']) as $module) {
+    $rows[] = array(
+      array('data' => drupal_render($form['uninstall'][$module]), 'align' => 'center'),
+      '<strong>'. drupal_render($form['modules'][$module]['name']) .'</strong>',
+      array('data' => drupal_render($form['modules'][$module]['description']), 'class' => 'description'),
+    );
+  }
+
+  // Only display table if there are modules that can be uninstalled.
+  if (empty($rows)) {
+    $rows[] = array(array('data' => t('No modules are available to uninstall.'), 'colspan' => '3', 'align' => 'center', 'class' => 'message'));
+  }
+
+  $output  = theme('table', $header, $rows);
+  $output .= drupal_render($form);
+
+  return $output;
+}
+
+/**
+ * Validates the submitted uninstall form.
+ *
+ * @param
+ *   $form_id The form ID.
+ * @param
+ *   $form_values Submitted form values.
+ */
+function system_modules_uninstall_validate($form_id, $form_values) {
+  // Form submitted, but no modules selected.
+  if (!count(array_filter($form_values['uninstall']))) {
+    drupal_set_message(t('No modules selected.'), 'error');
+    drupal_goto('admin/build/modules/uninstall');
+  }
+}
+
+/**
+ * Processes the submitted uninstall form.
+ *
+ * @param
+ *   $form_id The form ID.
+ * @param
+ *   $form_values Submitted form values.
+ */
+function system_modules_uninstall_submit($form_id, $form_values) {
+  // Make sure the install API is available.
+  include_once './includes/install.inc';
+
+  // Call the uninstall routine for each selected module.
+  foreach (array_filter($form_values['uninstall']) as $module => $value) {
+    drupal_uninstall_module($module);
+  }
+  drupal_set_message(t('The selected modules have been uninstalled.'));
+  drupal_goto('admin/build/modules/uninstall');
+}
+
+/**
+ * Menu callback: run cron manually.
+ */
+function system_run_cron() {
+   // Run cron manually
+   if (drupal_cron_run()) {
+     drupal_set_message(t('Cron ran successfully'));
+   }
+   else {
+     drupal_set_message(t('Cron run failed'));
+   }
+
+   drupal_goto('admin/logs/status');
+}
+
+/**
+ * Menu callback: return information about PHP.
+ */
+function system_php() {
+  phpinfo(INFO_GENERAL | INFO_CONFIGURATION);
+  exit();
+}
+
+function _system_sql($data, $keys) {
+  $rows = array();
+  foreach ($keys as $key => $explanation) {
+    if (isset($data[$key])) {
+      $rows[] = array(check_plain($key), check_plain($data[$key]), $explanation);
+    }
+  }
+
+  return theme('table', array(t('Variable'), t('Value'), t('Description')), $rows);
+}
+
+/**
+ * Menu callback: return information about PHP.
+ */
+function system_sql() {
+
+  $result = db_query("SHOW STATUS");
+  while ($entry = db_fetch_object($result)) {
+   $data[$entry->Variable_name] = $entry->Value;
+  }
+
+  $output  = '<h2>'. t('Command counters') .'</h2>';
+  $output .= _system_sql($data, array(
+   'Com_select' => t('The number of <code>SELECT</code>-statements.'),
+   'Com_insert' => t('The number of <code>INSERT</code>-statements.'),
+   'Com_update' => t('The number of <code>UPDATE</code>-statements.'),
+   'Com_delete' => t('The number of <code>DELETE</code>-statements.'),
+   'Com_lock_tables' => t('The number of table locks.'),
+   'Com_unlock_tables' => t('The number of table unlocks.')
+  ));
+
+  $output .= '<h2>'. t('Query performance') .'</h2>';
+  $output .= _system_sql($data, array(
+   'Select_full_join' => t('The number of joins without an index; should be zero.'),
+   'Select_range_check' => t('The number of joins without an index; should be zero.'),
+   'Sort_scan' => t('The number of sorts done without using an index; should be zero.'),
+   'Table_locks_immediate' => t('The number of times a lock could be acquired immediately.'),
+   'Table_locks_waited' => t('The number of times the server had to wait for a lock.')
+  ));
+
+  $output .= '<h2>'. t('Query cache information') .'</h2>';
+  $output .= '<p>'. t('The MySQL query cache can improve performance of your site by storing the result of queries.  Then, if an identical query is received later, the MySQL server retrieves the result from the query cache rather than parsing and executing the statement again.') .'</p>';
+  $output .= _system_sql($data, array(
+   'Qcache_queries_in_cache' => t('The number of queries in the query cache.'),
+   'Qcache_hits' => t('The number of times that MySQL found previous results in the cache.'),
+   'Qcache_inserts' => t('The number of times that MySQL added a query to the cache (misses).'),
+   'Qcache_lowmem_prunes' => t('The number of times that MySQL had to remove queries from the cache because it ran out of memory.  Ideally should be zero.')
+  ));
+
+  return $output;
+}
+
+/**
+ * Menu callback: displays the site status report. Can also be used as a pure check.
+ *
+ * @param $check
+ *   If true, only returns a boolean whether there are system status errors.
+ */
+function system_status($check = FALSE) {
+  // Load .install files
+  include_once './includes/install.inc';
+  drupal_load_updates();
+
+  // Check run-time requirements and status information
+  $requirements = module_invoke_all('requirements', 'runtime');
+  usort($requirements, '_system_sort_requirements');
+
+  if ($check) {
+    return drupal_requirements_severity($requirements) == REQUIREMENT_ERROR;
+  }
+
+  return theme('status_report', $requirements);
+}
+
+/**
+ * Helper function to sort requirements.
+ */
+function _system_sort_requirements($a, $b) {
+  if (!isset($a['weight'])) {
+    if (!isset($b['weight'])) {
+      return strcmp($a['title'], $b['title']);
+    }
+    return -$b['weight'];
+  }
+  return isset($b['weight']) ? $a['weight'] - $b['weight'] : $a['weight'];
+}
+
+/**
+ * Theme status report
+ */
+function theme_status_report(&$requirements) {
+  $i = 0;
+  $output = '<table class="system-status-report">';
+  foreach ($requirements as $requirement) {
+    if (empty($requirement['#type'])) {
+      $class = ++$i % 2 == 0 ? 'even' : 'odd';
+
+      $classes = array(
+        REQUIREMENT_INFO => 'info',
+        REQUIREMENT_OK => 'ok',
+        REQUIREMENT_WARNING => 'warning',
+        REQUIREMENT_ERROR => 'error',
+      );
+      $class = $classes[isset($requirement['severity']) ? (int)$requirement['severity'] : 0] .' '. $class;
+
+      // Output table row(s)
+      if (!empty($requirement['description'])) {
+        $output .= '<tr class="'. $class .' merge-down"><th>'. $requirement['title'] .'</th><td>'. $requirement['value'] .'</td></tr>';
+        $output .= '<tr class="'. $class .' merge-up"><td colspan="2">'. $requirement['description'] .'</td></tr>';
+      }
+      else {
+        $output .= '<tr class="'. $class .'"><th>'. $requirement['title'] .'</th><td>'. $requirement['value'] .'</td></tr>';
+      }
+    }
+  }
+
+  $output .= '</table>';
+  return $output;
+}
+
+/**
+ * Menu callback; displays a module's settings page.
+ */
+function system_settings_overview() {
+  // Check database setup if necessary
+  if (function_exists('db_check_setup') && empty($_POST)) {
+    db_check_setup();
+  }
+
+  $item = menu_get_item('admin/settings');
+  $content = system_admin_menu_block($item);
+
+  $output = theme('admin_block_content', $content);
+
+  return $output;
+}
+
+function system_logging_overview() {
+  $item = menu_get_item('admin/settings/logging');
+  $content = system_admin_menu_block($item);
+
+  $output = theme('admin_block_content', $content);
+
+  return $output;
+}
+/**
+ * Menu callback; display theme configuration for entire site and individual themes.
+ */
+function system_theme_settings($key = '') {
+  $directory_path = file_directory_path();
+  file_check_directory($directory_path, FILE_CREATE_DIRECTORY, 'file_directory_path');
+
+  // Default settings are defined in theme_get_settings() in includes/theme.inc
+  if ($key) {
+    $settings = theme_get_settings($key);
+    $var = str_replace('/', '_', 'theme_'. $key .'_settings');
+    $themes = system_theme_data();
+    $features = $themes[$key]->info['features'];
+  }
+  else {
+    $settings = theme_get_settings('');
+    $var = 'theme_settings';
+  }
+
+  $form['var'] = array('#type' => 'hidden', '#value' => $var);
+
+  // Check for a new uploaded logo, and use that instead.
+  if ($file = file_check_upload('logo_upload')) {
+    if ($info = image_get_info($file->filepath)) {
+      $parts = pathinfo($file->filename);
+      $filename = ($key) ? str_replace('/', '_', $key) .'_logo.'. $parts['extension'] : 'logo.'. $parts['extension'];
+
+      if ($file = file_save_upload('logo_upload', $filename, 1)) {
+        $_POST['default_logo'] = 0;
+        $_POST['logo_path'] = $file->filepath;
+        $_POST['toggle_logo'] = 1;
+      }
+    }
+    else {
+      form_set_error('file_upload', t('Only JPEG, PNG and GIF images are allowed to be used as logos.'));
+    }
+  }
+
+  // Check for a new uploaded favicon, and use that instead.
+  if ($file = file_check_upload('favicon_upload')) {
+    $parts = pathinfo($file->filename);
+    $filename = ($key) ? str_replace('/', '_', $key) .'_favicon.'. $parts['extension'] : 'favicon.'. $parts['extension'];
+
+    if ($file = file_save_upload('favicon_upload', $filename, 1)) {
+      $_POST['default_favicon'] = 0;
+      $_POST['favicon_path'] = $file->filepath;
+      $_POST['toggle_favicon'] = 1;
+    }
+  }
+
+  // Toggle settings
+  $toggles = array(
+    'logo'                 => t('Logo'),
+    'name'                 => t('Site name'),
+    'slogan'               => t('Site slogan'),
+    'mission'              => t('Mission statement'),
+    'node_user_picture'    => t('User pictures in posts'),
+    'comment_user_picture' => t('User pictures in comments'),
+    'search'               => t('Search box'),
+    'favicon'              => t('Shortcut icon')
+  );
+
+  // Some features are not always available
+  $disabled = array();
+  if (!variable_get('user_pictures', 0)) {
+    $disabled['toggle_node_user_picture'] = TRUE;
+    $disabled['toggle_comment_user_picture'] = TRUE;
+  }
+  if (!module_exists('search')) {
+    $disabled['toggle_search'] = TRUE;
+  }
+
+  $form['theme_settings'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Toggle display'),
+    '#description' => t('Enable or disable the display of certain page elements.'),
+  );
+  foreach ($toggles as $name => $title) {
+    if ((!$key) || in_array($name, $features)) {
+      // disable search box if search.module is disabled
+      $form['theme_settings']['toggle_'. $name] = array('#type' => 'checkbox', '#title' => $title, '#default_value' => $settings['toggle_'. $name]);
+      if (isset($disabled[$name])) {
+        $form['theme_settings']['toggle_'. $name]['#disabled'] = TRUE;
+      }
+    }
+  }
+
+  // System wide only settings.
+  if (!$key) {
+    // Create neat 2-column layout for the toggles
+    $form['theme_settings'] += array(
+      '#prefix' => '<div class="theme-settings-left">',
+      '#suffix' => '</div>',
+    );
+
+    // Toggle node display.
+    $node_types = node_get_types('names');
+    if ($node_types) {
+      $form['node_info'] = array(
+        '#type' => 'fieldset',
+        '#title' => t('Display post information on'),
+        '#description' =>  t('Enable or disable the <em>submitted by Username on date</em> text when displaying posts of the following type.'),
+        '#prefix' => '<div class="theme-settings-right">',
+        '#suffix' => '</div>',
+      );
+      foreach ($node_types as $type => $name) {
+        $form['node_info']["toggle_node_info_$type"] = array('#type' => 'checkbox', '#title' => $name, '#default_value' => $settings["toggle_node_info_$type"]);
+      }
+    }
+  }
+
+  // Logo settings
+  if ((!$key) || in_array('logo', $features)) {
+    $form['logo'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Logo image settings'),
+      '#description' => t('If toggled on, the following logo will be displayed.'),
+      '#attributes' => array('class' => 'theme-settings-bottom'),
+    );
+    $form['logo']["default_logo"] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Use the default logo'),
+      '#default_value' => $settings['default_logo'],
+      '#tree' => FALSE,
+      '#description' => t('Check here if you want the theme to use the logo supplied with it.')
+    );
+    $form['logo']['logo_path'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Path to custom logo'),
+      '#default_value' => $settings['logo_path'],
+      '#description' => t('The path to the file you would like to use as your logo file instead of the default logo.'));
+
+    $form['logo']['logo_upload'] = array(
+      '#type' => 'file',
+      '#title' => t('Upload logo image'),
+      '#maxlength' => 40,
+      '#description' => t("If you don't have direct file access to the server, use this field to upload your logo.")
+    );
+  }
+
+  if ((!$key) || in_array('favicon', $features)) {
+    $form['favicon'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Shortcut icon settings'),
+      '#description' => t("Your shortcut icon or 'favicon' is displayed in the address bar and bookmarks of most browsers.")
+    );
+    $form['favicon']['default_favicon'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Use the default shortcut icon.'),
+      '#default_value' => $settings['default_favicon'],
+      '#description' => t('Check here if you want the theme to use the default shortcut icon.')
+    );
+    $form['favicon']['favicon_path'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Path to custom icon'),
+      '#default_value' =>  $settings['favicon_path'],
+      '#description' => t('The path to the image file you would like to use as your custom shortcut icon.')
+    );
+
+    $form['favicon']['favicon_upload'] = array(
+      '#type' => 'file',
+      '#title' => t('Upload icon image'),
+      '#description' => t("If you don't have direct file access to the server, use this field to upload your shortcut icon.")
+    );
+  }
+
+  if ($key) {
+    // Template-specific settings
+    $function = $themes[$key]->prefix .'_settings';
+    if (function_exists($function)) {
+      if ($themes[$key]->template) {
+        // file is a template or a style of a template
+        $form['specific'] = array('#type' => 'fieldset', '#title' => t('Engine-specific settings'), '#description' => t('These settings only exist for all the templates and styles based on the %engine theme engine.', array('%engine' => $themes[$key]->prefix)));
+      }
+      else {
+        // file is a theme or a style of a theme
+        $form['specific'] = array('#type' => 'fieldset', '#title' => t('Theme-specific settings'), '#description' => t('These settings only exist for the %theme theme and all the styles based on it.', array('%theme' => $themes[$key]->prefix)));
+      }
+      $group = $function();
+      $form['specific'] = array_merge($form['specific'], (is_array($group) ? $group : array()));
+    }
+  }
+  $form['#attributes'] = array('enctype' => 'multipart/form-data');
+
+  return system_settings_form($form);
+}
+
+
+/**
+ * This function formats an administrative page for viewing.
+ *
+ * @param $blocks
+ *   An array of blocks to display. Each array should include a
+ *   'title', a 'description', a formatted 'content' and a
+ *   'position' which will control which container it will be
+ *   in. This is usually 'left' or 'right'.
+ * @themeable
+ */
+function theme_admin_page($blocks) {
+  $stripe = 0;
+  $container = array();
+
+  foreach ($blocks as $block) {
+    if ($block_output = theme('admin_block', $block)) {
+      if (empty($block['position'])) {
+        // perform automatic striping.
+        $block['position'] = ++$stripe % 2 ? 'left' : 'right';
+      }
+      if (!isset($container[$block['position']])) {
+        $container[$block['position']] = '';
+      }
+      $container[$block['position']] .= $block_output;
+    }
+  }
+
+  $output = '<div class="admin clear-block">';
+  $output .= '<div class="compact-link">';
+  if (system_admin_compact_mode()) {
+    $output .= l(t('Show descriptions'), 'admin/compact/off', array('title' => t('Produce a less compact layout that includes descriptions.')));
+  }
+  else {
+    $output .= l(t('Hide descriptions'), 'admin/compact/on', array('title' => t("Produce a more compact layout that doesn't include descriptions.")));
+  }
+  $output .= '</div>';
+
+  foreach ($container as $id => $data) {
+    $output .= '<div class="'. $id .' clear-block">';
+    $output .= $data;
+    $output .= '</div>';
+  }
+  $output .= '</div>';
+  return $output;
+}
+
+/**
+ * This function formats an administrative block for display.
+ *
+ * @param $block
+ *   An array containing information about the block. It should
+ *   include a 'title', a 'description' and a formatted 'content'.
+ * @themeable
+ */
+function theme_admin_block($block) {
+  // Don't display the block if it has no content to display.
+  if (empty($block['content'])) {
+    return '';
+  }
+
+  $output = <<< EOT
+  <div class="admin-panel">
+    <h3>
+      $block[title]
+    </h3>
+    <div class="body">
+      <p class="description">
+        $block[description]
+      </p>
+      $block[content]
+    </div>
+  </div>
+EOT;
+  return $output;
+}
+
+/**
+ * Menu callback; prints a listing of admin tasks for each installed module.
+ */
+function system_admin_by_module() {
+  return 'This page awaits rewrite'; // TODO: this needs to be rewritten for the new menu system.
+  $modules = module_rebuild_cache();
+  $menu_items = array();
+  foreach ($modules as $file) {
+    $module = $file->name;
+    if ($module == 'help') {
+      continue;
+    }
+
+    $admin_tasks = system_get_module_admin_tasks($module);
+
+    // Only display a section if there are any available tasks.
+    if (count($admin_tasks)) {
+
+      // Check for help links.
+      if (module_invoke($module, 'help', "admin/help#$module")) {
+        $admin_tasks[100] = l(t('Get help'), "admin/help/$module");
+      }
+
+      // Sort.
+      ksort($admin_tasks);
+
+      $menu_items[$file->info['name']] = array($file->info['description'], $admin_tasks);
+    }
+  }
+  return theme('system_admin_by_module', $menu_items);
+}
+
+function system_get_module_admin_tasks($module) {
+  return array(); // TODO: this needs to be rewritten for the new menu system.
+  $admin_access = user_access('administer access control');
+  $menu = menu_get_menu();
+  $admin_tasks = array();
+
+  // Check for permissions.
+  if (module_hook($module, 'perm') && $admin_access) {
+    $admin_tasks[-1] = l(t('Configure permissions'), 'admin/user/access', array('fragment' => 'module-'. $module));
+  }
+
+  // Check for menu items that are admin links.
+  if ($items = module_invoke($module, 'menu', TRUE)) {
+    foreach ($items as $item) {
+      $parts = explode('/', $item['path']);
+      $n = count($parts);
+      if ((!isset($item['type']) || ($item['type'] & MENU_VISIBLE_IN_TREE)) && ($parts[0] == 'admin') && ($n >= 3) && _menu_item_is_accessible($menu['path index'][$item['path']])) {
+        $admin_tasks[$item['title']] = l($item['title'], $item['path']);
+      }
+    }
+  }
+
+  return $admin_tasks;
+}
+
+/**
+ * Theme output of the dashboard page.
+ */
+function theme_system_admin_by_module($menu_items) {
+  $stripe = 0;
+  $output = '';
+  $container = array();
+
+  // Iterate over all modules
+  foreach ($menu_items as $module => $block) {
+    list($description, $items) = $block;
+
+    // Output links
+    if (count($items)) {
+      $block = array();
+      $block['title'] = $module;
+      $block['content'] = theme('item_list', $items);
+      $block['description'] = t($description);
+
+      if ($block_output = theme('admin_block', $block)) {
+        if (!$block['position']) {
+          // Perform automatic striping.
+          $block['position'] = ++$stripe % 2 ? 'left' : 'right';
+        }
+        $container[$block['position']] .= $block_output;
+      }
+    }
+  }
+
+  $output = '<div class="admin">';
+  foreach ($container as $id => $data) {
+    $output .= '<div class="'. $id .' clear-block">';
+    $output .= $data;
+    $output .= '</div>';
+  }
+  $output .= '</div>';
+
+  return $output;
+}
+
+/**
+ * Implementation of hook_cron().
+ *
+ * Remove older rows from flood table
+ */
+function system_cron() {
+  // Cleanup the flood
+  db_query('DELETE FROM {flood} WHERE timestamp < %d', time() - 3600);
+}
+
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.775
diff -u -p -r1.775 user.module
--- modules/user/user.module	24 Apr 2007 13:53:15 -0000	1.775
+++ modules/user/user.module	30 Apr 2007 07:06:44 -0000
@@ -9,6 +9,276 @@
 define('USERNAME_MAX_LENGTH', 60);
 define('EMAIL_MAX_LENGTH', 64);
 
+
+/**
+ * Implementation of hook_menu().
+ */
+function user_menu() {
+  $items['user/autocomplete'] = array(
+    'title' => t('User autocomplete'),
+    'page callback' => 'user_autocomplete',
+    'access callback' => 'user_access',
+    'access arguments' => array('access user profiles'),
+    'type' => MENU_CALLBACK,
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+
+  // Registration and login pages.
+  $items['user'] = array(
+    'title' => t('Log in'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('user_login'),
+    'access callback' => 'user_is_anonymous',
+    'type' => MENU_CALLBACK,
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+
+  $items['user/login'] = array(
+    'title' => t('Log in'),
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+  );
+
+  $items['user/register'] = array(
+    'title' => t('Create new account'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('user_register'),
+    'access callback' => 'user_register_access',
+    'type' => MENU_LOCAL_TASK,
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+
+  $items['user/password'] = array(
+    'title' => t('Request new password'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('user_pass'),
+    'access callback' => 'user_is_anonymous',
+    'type' => MENU_LOCAL_TASK,
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+  $items['user/reset/%/%/%'] = array(
+    'title' => t('Reset password'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('user_pass_reset', 2, 3, 4),
+    'access callback' => TRUE,
+    'type' => MENU_CALLBACK,
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+  $items['user/help'] = array(
+    'title' => t('Help'),
+    'page callback' => 'user_help_page',
+    'type' => MENU_CALLBACK,
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+
+  // Admin user pages
+  $items['admin/user'] = array(
+    'title' => t('User management'),
+    'description' => t('Manage your site\'s users, groups and access to site features.'),
+    'position' => 'left',
+    'page callback' => 'system_admin_menu_block_page',
+    'access arguments' => array('administer site configuration'),
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+  $items['admin/user/user'] = array(
+    'title' => t('Users'),
+    'description' => t('List, add, and edit users.'),
+    'page callback' => 'user_admin',
+    'page arguments' => array('list'),
+    'access arguments' => array('administer users'),
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+  $items['admin/user/user/list'] = array(
+    'title' => t('List'),
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'weight' => -10,
+  );
+  $items['admin/user/user/create'] = array(
+    'title' => t('Add user'),
+    'page arguments' => array('create'),
+    'type' => MENU_LOCAL_TASK,
+  );
+  $items['admin/user/settings'] = array(
+    'title' => t('User settings'),
+    'description' => t('Configure default behavior of users, including registration requirements, e-mails, and user pictures.'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('user_admin_settings'),
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+
+  // Admin access pages
+  $items['admin/user/access'] = array(
+    'title' => t('Access control'),
+    'description' => t('Determine access to features by selecting permissions for roles.'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('user_admin_perm'),
+    'access arguments' => array('administer access control'),
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+  $items['admin/user/roles'] = array(
+    'title' => t('Roles'),
+    'description' => t('List, edit, or add user roles.'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('user_admin_new_role'),
+    'access arguments' => array('administer access control'),
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+  $items['admin/user/roles/edit'] = array(
+    'title' => t('Edit role'),
+    'page arguments' => array('user_admin_role'),
+    'type' => MENU_CALLBACK,
+  );
+  $items['admin/user/rules'] = array(
+    'title' => t('Access rules'),
+    'description' => t('List and create rules to disallow usernames, e-mail addresses, and IP addresses.'),
+    'page callback' => 'user_admin_access',
+    'access arguments' => array('administer access control'),
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+  $items['admin/user/rules/list'] = array(
+    'title' => t('List'),
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'weight' => -10,
+  );
+  $items['admin/user/rules/add'] = array(
+    'title' => t('Add rule'),
+    'page callback' => 'user_admin_access_add',
+    'type' => MENU_LOCAL_TASK,
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+  $items['admin/user/rules/check'] = array(
+    'title' => t('Check rules'),
+    'page callback' => 'user_admin_access_check',
+    'type' => MENU_LOCAL_TASK,
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+  $items['admin/user/rules/edit'] = array(
+    'title' => t('Edit rule'),
+    'page callback' => 'user_admin_access_edit',
+    'type' => MENU_CALLBACK,
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+  $items['admin/user/rules/delete'] = array(
+    'title' => t('Delete rule'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('user_admin_access_delete_confirm'),
+    'type' => MENU_CALLBACK,
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+
+  if (module_exists('search')) {
+    $items['admin/user/search'] = array(
+      'title' => t('Search users'),
+      'description' => t('Search users by name.'),
+      'page callback' => 'user_admin',
+      'page arguments' => array('search'),
+      'access arguments' => array('administer users'),
+      'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+    );
+  }
+
+  $items['logout'] = array(
+    'title' => t('Log out'),
+    'access callback' => 'user_is_logged_in',
+    'page callback' => 'user_logout',
+    'weight' => 10,
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+
+  $items['user/%user_current'] = array(
+    'title' => t('My account'),
+    'page callback' => 'user_view',
+    'page arguments' => array(1),
+    'access callback' => 'user_view_access',
+    'access arguments' => array(1),
+    'parent' => '',
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+
+  $items['user/%user/view'] = array(
+    'title' => t('View'),
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'weight' => -10,
+  );
+
+  $items['user/%user/delete'] = array(
+    'title' => t('Delete'),
+    'page callback' => 'user_edit',
+    'access callback' => 'user_access',
+    'access arguments' => array('administer users'),
+    'type' => MENU_CALLBACK,
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+
+  $items['user/%user/edit'] = array(
+    'title' => t('Edit'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('user_edit'),
+    'access callback' => 'user_edit_access',
+    'access arguments' => array(1),
+    'type' => MENU_LOCAL_TASK,
+    'includes' => drupal_get_path('module', 'user') . '/user.pages.inc',
+  );
+
+  $empty_account = new stdClass();
+  if (($categories = _user_categories($empty_account)) && (count($categories) > 1)) {
+    foreach ($categories as $key => $category) {
+      $items['user/%user/edit/'. $category['name']] = array(
+        'title' => $category['title'],
+        'page arguments' => array('user_edit', 3),
+        'type' => $category['name'] == 'account' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
+        'weight' => $category['weight'],
+      );
+    }
+  }
+  return $items;
+}
+
+function user_init() {
+  drupal_add_css(drupal_get_path('module', 'user') .'/user.css', 'module');
+}
+
+function user_current_load($arg) {
+  return user_load($arg);
+}
+
+function user_current_to_arg() {
+  return $GLOBALS['user']->uid;
+}
+
+
+function user_is_anonymous() {
+  return !$GLOBALS['user']->uid;
+}
+
+function user_is_logged_in() {
+  return (bool)$GLOBALS['user']->uid;
+}
+
+function user_register_access() {
+  return !$GLOBALS['user']->uid && variable_get('user_register', 1);
+}
+
+function user_view_access($account) {
+  return $account && $account->uid &&
+    (
+      // Always let users view their own profile.
+      ($GLOBALS['user']->uid == $account->uid) ||
+      // Administrators can view all accounts.
+      user_access('administer users') ||
+      // The user is not blocked and logged in at least once.
+      ($account->access && $account->status && user_access('access user profiles'))
+    );
+}
+
+function user_edit_access($account) {
+  return ($GLOBALS['user']->uid == $account->uid) || array('administer users');
+}
+
+function user_load_self($arg) {
+  $arg[1] = user_load($GLOBALS['user']->uid);
+  return $arg;
+}
+
 /**
  * Invokes hook_user() in every module.
  *
@@ -281,73 +551,9 @@ function user_save($account, $array = ar
   return $user;
 }
 
+
 /**
- * Verify the syntax of the given name.
- */
-function user_validate_name($name) {
-  if (!strlen($name)) return t('You must enter a username.');
-  if (substr($name, 0, 1) == ' ') return t('The username cannot begin with a space.');
-  if (substr($name, -1) == ' ') return t('The username cannot end with a space.');
-  if (strpos($name, '  ') !== FALSE) return t('The username cannot contain multiple spaces in a row.');
-  if (ereg("[^\x80-\xF7 [:alnum:]@_.-]", $name)) return t('The username contains an illegal character.');
-  if (preg_match('/[\x{80}-\x{A0}'.          // Non-printable ISO-8859-1 + NBSP
-                   '\x{AD}'.                 // Soft-hyphen
-                   '\x{2000}-\x{200F}'.      // Various space characters
-                   '\x{2028}-\x{202F}'.      // Bidirectional text overrides
-                   '\x{205F}-\x{206F}'.      // Various text hinting characters
-                   '\x{FEFF}'.               // Byte order mark
-                   '\x{FF01}-\x{FF60}'.      // Full-width latin
-                   '\x{FFF9}-\x{FFFD}'.      // Replacement characters
-                   '\x{0}]/u',               // NULL byte
-                   $name)) {
-    return t('The username contains an illegal character.');
-  }
-  if (strpos($name, '@') !== FALSE && !eregi('@([0-9a-z](-?[0-9a-z])*.)+[a-z]{2}([zmuvtg]|fo|me)?$', $name)) return t('The username is not a valid authentication ID.');
-  if (strlen($name) > USERNAME_MAX_LENGTH) return t('The username %name is too long: it must be %max characters or less.', array('%name' => $name, '%max' => USERNAME_MAX_LENGTH));
-}
-
-function user_validate_mail($mail) {
-  if (!$mail) return t('You must enter an e-mail address.');
-  if (!valid_email_address($mail)) {
-    return t('The e-mail address %mail is not valid.', array('%mail' => $mail));
-  }
-}
-
-function user_validate_picture($file, &$edit, $user) {
-  global $form_values;
-  // Initialize the picture:
-  $form_values['picture'] = $user->picture;
-
-  // Check that uploaded file is an image, with a maximum file size
-  // and maximum height/width.
-  $info = image_get_info($file->filepath);
-  list($maxwidth, $maxheight) = explode('x', variable_get('user_picture_dimensions', '85x85'));
-
-  if (!$info || !$info['extension']) {
-    form_set_error('picture_upload', t('The uploaded file was not an image.'));
-  }
-  else if (image_get_toolkit()) {
-    image_scale($file->filepath, $file->filepath, $maxwidth, $maxheight);
-  }
-  else if (filesize($file->filepath) > (variable_get('user_picture_file_size', '30') * 1000)) {
-    form_set_error('picture_upload', t('The uploaded image is too large; the maximum file size is %size kB.', array('%size' => variable_get('user_picture_file_size', '30'))));
-  }
-  else if ($info['width'] > $maxwidth || $info['height'] > $maxheight) {
-    form_set_error('picture_upload', t('The uploaded image is too large; the maximum dimensions are %dimensions pixels.', array('%dimensions' => variable_get('user_picture_dimensions', '85x85'))));
-  }
-
-  if (!form_get_errors()) {
-    if ($file = file_save_upload('picture_upload', variable_get('user_picture_path', 'pictures') .'/picture-'. $user->uid .'.'. $info['extension'], 1)) {
-      $form_values['picture'] = $file->filepath;
-    }
-    else {
-      form_set_error('picture_upload', t("Failed to upload the picture image; the %directory directory doesn't exist or is not writable.", array('%directory' => variable_get('user_picture_path', 'pictures'))));
-    }
-  }
-}
-
-/**
- * Generate a random alphanumeric password.
+ * Generate a random alphanumeric password.
  */
 function user_password($length = 10) {
   // This variable contains the list of allowable characters for the
@@ -430,22 +636,6 @@ function user_is_blocked($name) {
   return $deny;
 }
 
-function user_fields() {
-  static $fields;
-
-  if (!$fields) {
-    $result = db_query('SELECT * FROM {users} WHERE uid = 1');
-    if (db_num_rows($result)) {
-      $fields = array_keys(db_fetch_array($result));
-    }
-    else {
-      // Make sure we return the default fields at least
-      $fields = array('uid', 'name', 'pass', 'mail', 'picture', 'mode', 'sort', 'threshold', 'theme', 'signature', 'created', 'access', 'login', 'status', 'timezone', 'language', 'init', 'data');
-    }
-  }
-
-  return $fields;
-}
 
 /**
  * Implementation of hook_perm().
@@ -466,6 +656,7 @@ function user_file_download($file) {
   }
 }
 
+
 /**
  * Implementation of hook_search().
  */
@@ -659,2194 +850,25 @@ function user_block($op = 'list', $delta
   }
 }
 
-function theme_user_picture($account) {
-  if (variable_get('user_pictures', 0)) {
-    if ($account->picture && file_exists($account->picture)) {
-      $picture = file_create_url($account->picture);
-    }
-    else if (variable_get('user_picture_default', '')) {
-      $picture = variable_get('user_picture_default', '');
-    }
-
-    if (isset($picture)) {
-      $alt = t("@user's picture", array('@user' => $account->name ? $account->name : variable_get('anonymous', t('Anonymous'))));
-      $picture = theme('image', $picture, $alt, $alt, '', FALSE);
-      if (!empty($account->uid) && user_access('access user profiles')) {
-        $picture = l($picture, "user/$account->uid", array('attributes' => array('title' => t('View user profile.')), 'html' => TRUE));
-      }
-
-      return "<div class=\"picture\">$picture</div>";
-    }
-  }
-}
-
 /**
- * Theme a user page
- * @param $account the user object
- * @param $fields a multidimensional array for the fields, in the form of array (
- *   'category1' => array(item_array1, item_array2), 'category2' => array(item_array3,
- *    .. etc.). Item arrays are formatted as array(array('title' => 'item title',
- * 'value' => 'item value', 'class' => 'class-name'), ... etc.). Module names are incorporated
- * into the CSS class.
- *
- * @ingroup themeable
+ * Retrieve a list of all user setting/information categories and sort them by weight.
  */
-function theme_user_profile($account, $fields) {
-  $output = '<div class="profile">';
-  $output .= theme('user_picture', $account);
-  foreach ($fields as $category => $items) {
-    if (strlen($category) > 0) {
-      $output .= '<h2 class="title">'. $category .'</h2>';
-    }
-    $output .= '<dl>';
-    foreach ($items as $item) {
-      if (isset($item['title'])) {
-        $output .= '<dt class="'. $item['class'] .'">'. $item['title'] .'</dt>';
-      }
-      $output .= '<dd class="'. $item['class'] .'">'. $item['value'] .'</dd>';
-    }
-    $output .= '</dl>';
-  }
-  $output .= '</div>';
-
-  return $output;
-}
+function _user_categories($account) {
+  $categories = array();
 
-/**
- * Make a list of users.
- * @param $items an array with user objects. Should contain at least the name and uid
- *
- * @ingroup themeable
- */
-function theme_user_list($users, $title = NULL) {
-  if (!empty($users)) {
-    foreach ($users as $user) {
-      $items[] = theme('username', $user);
+  foreach (module_list() as $module) {
+    if ($data = module_invoke($module, 'user', 'categories', NULL, $account, '')) {
+      $categories = array_merge($data, $categories);
     }
   }
-  return theme('item_list', $items, $title);
-}
-
-function user_is_anonymous() {
-  return !$GLOBALS['user']->uid;
-}
-
-function user_is_logged_in() {
-  return (bool)$GLOBALS['user']->uid;
-}
-
-function user_register_access() {
-  return !$GLOBALS['user']->uid && variable_get('user_register', 1);
-}
 
-function user_view_access($account) {
-  return $account && $account->uid &&
-    (
-      // Always let users view their own profile.
-      ($GLOBALS['user']->uid == $account->uid) ||
-      // Administrators can view all accounts.
-      user_access('administer users') ||
-      // The user is not blocked and logged in at least once.
-      ($account->access && $account->status && user_access('access user profiles'))
-    );
-}
+  usort($categories, '_user_sort');
 
-function user_edit_access($account) {
-  return ($GLOBALS['user']->uid == $account->uid) || array('administer users');
+  return $categories;
 }
 
-function user_load_self($arg) {
-  $arg[1] = user_load($GLOBALS['user']->uid);
-  return $arg;
+function _user_sort($a, $b) {
+  $a = (array)$a + array('weight' => 0, 'title' => '');
+  $b = (array)$b + array('weight' => 0, 'title' => '');
+  return $a['weight'] < $b['weight'] ? -1 : ($a['weight'] > $b['weight'] ? 1 : ($a['title'] < $b['title'] ? -1 : 1));
 }
-
-/**
- * Implementation of hook_menu().
- */
-function user_menu() {
-  $items['user/autocomplete'] = array(
-    'title' => t('User autocomplete'),
-    'page callback' => 'user_autocomplete',
-    'access callback' => 'user_access',
-    'access arguments' => array('access user profiles'),
-    'type' => MENU_CALLBACK,
-  );
-
-  // Registration and login pages.
-  $items['user'] = array(
-    'title' => t('Log in'),
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('user_login'),
-    'access callback' => 'user_is_anonymous',
-    'type' => MENU_CALLBACK,
-  );
-
-  $items['user/login'] = array(
-    'title' => t('Log in'),
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-  );
-
-  $items['user/register'] = array(
-    'title' => t('Create new account'),
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('user_register'),
-    'access callback' => 'user_register_access',
-    'type' => MENU_LOCAL_TASK,
-  );
-
-  $items['user/password'] = array(
-    'title' => t('Request new password'),
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('user_pass'),
-    'access callback' => 'user_is_anonymous',
-    'type' => MENU_LOCAL_TASK,
-  );
-  $items['user/reset/%/%/%'] = array(
-    'title' => t('Reset password'),
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('user_pass_reset', 2, 3, 4),
-    'access callback' => TRUE,
-    'type' => MENU_CALLBACK,
-  );
-  $items['user/help'] = array(
-    'title' => t('Help'),
-    'page callback' => 'user_help_page',
-    'type' => MENU_CALLBACK,
-  );
-
-  // Admin user pages
-  $items['admin/user'] = array(
-    'title' => t('User management'),
-    'description' => t('Manage your site\'s users, groups and access to site features.'),
-    'position' => 'left',
-    'page callback' => 'system_admin_menu_block_page',
-    'access arguments' => array('administer site configuration'),
-  );
-  $items['admin/user/user'] = array(
-    'title' => t('Users'),
-    'description' => t('List, add, and edit users.'),
-    'page callback' => 'user_admin',
-    'page arguments' => array('list'),
-    'access arguments' => array('administer users'));
-  $items['admin/user/user/list'] = array(
-    'title' => t('List'),
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-    'weight' => -10,
-  );
-  $items['admin/user/user/create'] = array(
-    'title' => t('Add user'),
-    'page arguments' => array('create'),
-    'type' => MENU_LOCAL_TASK,
-  );
-  $items['admin/user/settings'] = array(
-    'title' => t('User settings'),
-    'description' => t('Configure default behavior of users, including registration requirements, e-mails, and user pictures.'),
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('user_admin_settings'),
-  );
-
-  // Admin access pages
-  $items['admin/user/access'] = array(
-    'title' => t('Access control'),
-    'description' => t('Determine access to features by selecting permissions for roles.'),
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('user_admin_perm'),
-    'access arguments' => array('administer access control'),
-  );
-  $items['admin/user/roles'] = array(
-    'title' => t('Roles'),
-    'description' => t('List, edit, or add user roles.'),
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('user_admin_new_role'),
-    'access arguments' => array('administer access control'),
-  );
-  $items['admin/user/roles/edit'] = array(
-    'title' => t('Edit role'),
-    'page arguments' => array('user_admin_role'),
-    'type' => MENU_CALLBACK,
-  );
-  $items['admin/user/rules'] = array(
-    'title' => t('Access rules'),
-    'description' => t('List and create rules to disallow usernames, e-mail addresses, and IP addresses.'),
-    'page callback' => 'user_admin_access',
-    'access arguments' => array('administer access control'),
-  );
-  $items['admin/user/rules/list'] = array(
-    'title' => t('List'),
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-    'weight' => -10,
-  );
-  $items['admin/user/rules/add'] = array(
-    'title' => t('Add rule'),
-    'page callback' => 'user_admin_access_add',
-    'type' => MENU_LOCAL_TASK,
-  );
-  $items['admin/user/rules/check'] = array(
-    'title' => t('Check rules'),
-    'page callback' => 'user_admin_access_check',
-    'type' => MENU_LOCAL_TASK,
-  );
-  $items['admin/user/rules/edit'] = array(
-    'title' => t('Edit rule'),
-    'page callback' => 'user_admin_access_edit',
-    'type' => MENU_CALLBACK,
-  );
-  $items['admin/user/rules/delete'] = array(
-    'title' => t('Delete rule'),
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('user_admin_access_delete_confirm'),
-    'type' => MENU_CALLBACK,
-  );
-
-  if (module_exists('search')) {
-    $items['admin/user/search'] = array(
-      'title' => t('Search users'),
-      'description' => t('Search users by name.'),
-      'page callback' => 'user_admin',
-      'page arguments' => array('search'),
-      'access arguments' => array('administer users'),
-    );
-  }
-
-  $items['logout'] = array(
-    'title' => t('Log out'),
-    'access callback' => 'user_is_logged_in',
-    'page callback' => 'user_logout',
-    'weight' => 10,
-  );
-
-  $items['user/%user_current'] = array(
-    'title' => t('My account'),
-    'page callback' => 'user_view',
-    'page arguments' => array(1),
-    'access callback' => 'user_view_access',
-    'access arguments' => array(1),
-    'parent' => '',
-  );
-
-  $items['user/%user/view'] = array(
-    'title' => t('View'),
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-    'weight' => -10,
-  );
-
-  $items['user/%user/delete'] = array(
-    'title' => t('Delete'),
-    'page callback' => 'user_edit',
-    'access callback' => 'user_access',
-    'access arguments' => array('administer users'),
-    'type' => MENU_CALLBACK,
-  );
-
-  $items['user/%user/edit'] = array(
-    'title' => t('Edit'),
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('user_edit'),
-    'access callback' => 'user_edit_access',
-    'access arguments' => array(1),
-    'type' => MENU_LOCAL_TASK,
-  );
-
-  $empty_account = new stdClass();
-  if (($categories = _user_categories($empty_account)) && (count($categories) > 1)) {
-    foreach ($categories as $key => $category) {
-      $items['user/%user/edit/'. $category['name']] = array(
-        'title' => $category['title'],
-        'page arguments' => array('user_edit', 3),
-        'type' => $category['name'] == 'account' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
-        'weight' => $category['weight'],
-      );
-    }
-  }
-  return $items;
-}
-
-function user_init() {
-  drupal_add_css(drupal_get_path('module', 'user') .'/user.css', 'module');
-}
-
-function user_current_load($arg) {
-  return user_load($arg);
-}
-
-function user_current_to_arg() {
-  return $GLOBALS['user']->uid;
-}
-
-/**
- * Accepts an user object, $account, or a DA name and returns an associative
- * array of modules and DA names. Called at external login.
- */
-function user_get_authmaps($authname = NULL) {
-  $result = db_query("SELECT authname, module FROM {authmap} WHERE authname = '%s'", $authname);
-  if (db_num_rows($result) > 0) {
-    while ($authmap = db_fetch_object($result)) {
-      $authmaps[$authmap->module] = $authmap->authname;
-    }
-    return $authmaps;
-  }
-  else {
-    return 0;
-  }
-}
-
-function user_set_authmaps($account, $authmaps) {
-  foreach ($authmaps as $key => $value) {
-    $module = explode('_', $key, 2);
-    if ($value) {
-      db_query("UPDATE {authmap} SET authname = '%s' WHERE uid = %d AND module = '%s'", $value, $account->uid, $module[1]);
-      if (!db_affected_rows()) {
-        db_query("INSERT INTO {authmap} (authname, uid, module) VALUES ('%s', %d, '%s')", $value, $account->uid, $module[1]);
-      }
-    }
-    else {
-      db_query("DELETE FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module[1]);
-    }
-  }
-}
-
-function user_auth_help_links() {
-  $links = array();
-  foreach (module_list() as $module) {
-    if (module_hook($module, 'auth')) {
-      $links[] = l(module_invoke($module, 'info', 'name'), 'user/help', array('fragment' => $module));
-    }
-  }
-  return $links;
-}
-
-/*** User features *********************************************************/
-
-
-
-function user_login($msg = '') {
-  global $user;
-
-  // If we are already logged on, go to the user page instead.
-  if ($user->uid) {
-    drupal_goto('user/'. $user->uid);
-  }
-
-  // Display login form:
-  if ($msg) {
-    $form['message'] = array('#value' => '<p>'. check_plain($msg) .'</p>');
-  }
-  $form['name'] = array('#type' => 'textfield',
-    '#title' => t('Username'),
-    '#size' => 60,
-    '#maxlength' => USERNAME_MAX_LENGTH,
-    '#required' => TRUE,
-    '#attributes' => array('tabindex' => '1'),
-  );
-  if (variable_get('drupal_authentication_service', FALSE) && count(user_auth_help_links()) > 0) {
-    $form['name']['#description'] = t('Enter your @s username, or an ID from one of our affiliates: !a.', array('@s' => variable_get('site_name', 'Drupal'), '!a' => implode(', ', user_auth_help_links())));
-  }
-  else {
-    $form['name']['#description'] = t('Enter your @s username.', array('@s' => variable_get('site_name', 'Drupal')));
-  }
-  $form['pass'] = array('#type' => 'password',
-    '#title' => t('Password'),
-    '#description' => t('Enter the password that accompanies your username.'),
-    '#required' => TRUE,
-    '#attributes' => array('tabindex' => '2'),
-  );
-  $form['submit'] = array('#type' => 'submit', '#value' => t('Log in'), '#weight' => 2, '#attributes' => array('tabindex' => '3'));
-
-  return $form;
-}
-
-function user_login_validate($form_id, $form_values) {
-  if ($form_values['name']) {
-    if (user_is_blocked($form_values['name'])) {
-      // blocked in user administration
-      form_set_error('name', t('The username %name has not been activated or is blocked.', array('%name' => $form_values['name'])));
-    }
-    else if (drupal_is_denied('user', $form_values['name'])) {
-      // denied by access controls
-      form_set_error('name', t('The name %name is a reserved username.', array('%name' => $form_values['name'])));
-    }
-    else if ($form_values['pass']) {
-      $user = user_authenticate($form_values['name'], trim($form_values['pass']));
-
-      if (!$user->uid) {
-        form_set_error('name', t('Sorry, unrecognized username or password. <a href="@password">Have you forgotten your password?</a>', array('@password' => url('user/password'))));
-        watchdog('user', 'Login attempt failed for %user.', array('%user' => $form_values['name']));
-      }
-    }
-  }
-}
-
-function user_login_submit($form_id, $form_values) {
-  global $user;
-  if ($user->uid) {
-    watchdog('user', 'Session opened for %name.', array('%name' => $user->name));
-
-    // Update the user table timestamp noting user has logged in.
-    db_query("UPDATE {users} SET login = %d WHERE uid = %d", time(), $user->uid);
-
-    user_module_invoke('login', $form_values, $user);
-
-    sess_regenerate();
-    return 'user/'. $user->uid;
-  }
-}
-
-function user_authenticate($name, $pass) {
-  global $user;
-
-  // Try to log in the user locally. Don't set $user unless successful.
-  if ($account = user_load(array('name' => $name, 'pass' => $pass, 'status' => 1))) {
-    $user = $account;
-    return $user;
-  }
-
-  // Strip name and server from ID:
-  if ($server = strrchr($name, '@')) {
-    $name = substr($name, 0, strlen($name) - strlen($server));
-    $server = substr($server, 1);
-  }
-
-  // When possible, determine corresponding external auth source. Invoke
-  // source, and log in user if successful:
-  if ($server && ($result = user_get_authmaps("$name@$server"))) {
-    if (module_invoke(key($result), 'auth', $name, $pass, $server)) {
-      $user = user_external_load("$name@$server");
-      watchdog('user', 'External load by %user using module %module.', array('%user' => $name .'@'. $server, '%module' => key($result)));
-    }
-  }
-
-  // Try each external authentication source in series. Register user if
-  // successful.
-  else {
-    foreach (module_implements('auth') as $module) {
-      if (module_invoke($module, 'auth', $name, $pass, $server)) {
-        if ($server) {
-          $name .= '@'. $server;
-        }
-        $user = user_load(array('name' => $name));
-        if (!$user->uid) { // Register this new user.
-          $userinfo = array('name' => $name, 'pass' => user_password(), 'init' => $name, 'status' => 1);
-          if ($server) {
-            $userinfo["authname_$module"] = $name;
-          }
-          $user = user_save('', $userinfo);
-          watchdog('user', 'New external user: %user using module %module.', array('%user' => $name, '%module' => $module), WATCHDOG_NOTICE, l(t('edit'), 'user/'. $user->uid .'/edit'));
-          break;
-        }
-      }
-    }
-  }
-  return $user;
-}
-
-/**
- * Menu callback; logs the current user out, and redirects to the home page.
- */
-function user_logout() {
-  global $user;
-
-  watchdog('user', 'Session closed for %name.', array('%name' => $user->name));
-
-  // Destroy the current session:
-  session_destroy();
-  module_invoke_all('user', 'logout', NULL, $user);
-
-  // Load the anonymous user
-  $user = drupal_anonymous_user();
-
-  drupal_goto();
-}
-
-function user_pass() {
-  $form['name'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Username or e-mail address'),
-    '#size' => 60,
-    '#maxlength' => max(USERNAME_MAX_LENGTH, EMAIL_MAX_LENGTH),
-    '#required' => TRUE,
-  );
-  $form['submit'] = array('#type' => 'submit', '#value' => t('E-mail new password'));
-
-  return $form;
-}
-
-function user_pass_validate($form_id, $form_values) {
-  $name = trim($form_values['name']);
-  if (valid_email_address($name)) {
-    $account = user_load(array('mail' => $name, 'status' => 1));
-  }
-  else {
-    $account = user_load(array('name' => $name, 'status' => 1));
-  }
-  if (isset($account->uid)) {
-    form_set_value(array('#parents' => array('account')), $account);
-  }
-  else {
-    form_set_error('name', t('Sorry, %name is not recognized as a user name or an e-mail address.', array('%name' => $name)));
-  }
-}
-
-function user_pass_submit($form_id, $form_values) {
-  global $base_url;
-
-  $account = $form_values['account'];
-  $from = variable_get('site_mail', ini_get('sendmail_from'));
-
-  // Mail one time login URL and instructions.
-  $variables = array('!username' => $account->name, '!site' => variable_get('site_name', 'Drupal'), '!login_url' => user_pass_reset_url($account), '!uri' => $base_url, '!uri_brief' => substr($base_url, strlen('http://')), '!mailto' => $account->mail, '!date' => format_date(time()), '!login_uri' => url('user', array('absolute' => TRUE)), '!edit_uri' => url('user/'. $account->uid .'/edit', array('absolute' => TRUE)));
-  $subject = _user_mail_text('pass_subject', $variables);
-  $body = _user_mail_text('pass_body', $variables);
-  $mail_success = drupal_mail('user-pass', $account->mail, $subject, $body, $from);
-
-  if ($mail_success) {
-    watchdog('user', 'Password reset instructions mailed to %name at %email.', array('%name' => $account->name, '%email' => $account->mail));
-    drupal_set_message(t('Further instructions have been sent to your e-mail address.'));
-  }
-  else {
-    watchdog('user', 'Error mailing password reset instructions to %name at %email.', array('%name' => $account->name, '%email' => $account->mail), WATCHDOG_ERROR);
-    drupal_set_message(t('Unable to send mail. Please contact the site admin.'));
-  }
-  return 'user';
-}
-
-/**
- * Menu callback; process one time login link and redirects to the user page on success.
- */
-function user_pass_reset($uid, $timestamp, $hashed_pass, $action = NULL) {
-  global $user;
-
-  // Check if the user is already logged in. The back button is often the culprit here.
-  if ($user->uid) {
-    drupal_set_message(t('You have already used this one-time login link. It is not necessary to use this link to login anymore. You are already logged in.'));
-    drupal_goto();
-  }
-  else {
-    // Time out, in seconds, until login URL expires. 24 hours = 86400 seconds.
-    $timeout = 86400;
-    $current = time();
-    // Some redundant checks for extra security ?
-    if ($timestamp < $current && $account = user_load(array('uid' => $uid, 'status' => 1)) ) {
-      // 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.'));
-        drupal_goto('user/password');
-      }
-      else if ($account->uid && $timestamp > $account->login && $timestamp < $current && $hashed_pass == user_pass_rehash($account->pass, $timestamp, $account->login)) {
-        // First stage is a confirmation form, then login
-        if ($action == 'login') {
-          watchdog('user', 'User %name used one-time login link at time %timestamp.', array('%name' => $account->name, '%timestamp' => $timestamp));
-          // Update the user table noting user has logged in.
-          // And this also makes this hashed password a one-time-only login.
-          db_query("UPDATE {users} SET login = %d WHERE uid = %d", time(), $account->uid);
-          // Now we can set the new user.
-          $user = $account;
-          // And proceed with normal login, going to user page.
-          $edit = array();
-          user_module_invoke('login', $edit, $user);
-          drupal_set_message(t('You have just used your one-time login link. It is no longer necessary to use this link to login. Please change your password.'));
-          drupal_goto('user/'. $user->uid .'/edit');
-        }
-        else {
-          $form['message'] = array('#value' => t('<p>This is a one-time login for %user_name and will expire on %expiration_date</p><p>Click on this button to login to the site and change your password.</p>', array('%user_name' => $account->name, '%expiration_date' => format_date($timestamp + $timeout))));
-          $form['help'] = array('#value' => '<p>'. t('This login can be used only once.') .'</p>');
-          $form['submit'] = array('#type' => 'submit', '#value' => t('Log in'));
-          $form['#action'] = url("user/reset/$uid/$timestamp/$hashed_pass/login");
-          return $form;
-        }
-      }
-      else {
-        drupal_set_message(t('You have tried to use a one-time login link which has either been used or is no longer valid. Please request a new one using the form below.'));
-        drupal_goto('user/password');
-      }
-    }
-    else {
-      // Deny access, no more clues.
-      // Everything will be in the watchdog's URL for the administrator to check.
-      drupal_access_denied();
-    }
-  }
-}
-
-function user_pass_reset_url($account) {
-  $timestamp = time();
-  return url("user/reset/$account->uid/$timestamp/". user_pass_rehash($account->pass, $timestamp, $account->login), array('absolute' => TRUE));
-}
-
-function user_pass_rehash($password, $timestamp, $login) {
-  return md5($timestamp . $password . $login);
-}
-
-function user_register() {
-  global $user;
-
-  $admin = user_access('administer users');
-
-  // If we aren't admin but already logged on, go to the user page instead.
-  if (!$admin && $user->uid) {
-    drupal_goto('user/'. $user->uid);
-  }
-
-  $form = array();
-
-  // Display the registration form.
-  if (!$admin) {
-    $form['user_registration_help'] = array('#value' => filter_xss_admin(variable_get('user_registration_help', '')));
-  }
-  $affiliates = user_auth_help_links();
-  if (!$admin && count($affiliates) > 0) {
-    $affiliates = implode(', ', $affiliates);
-    $form['affiliates'] = array('#value' => '<p>'. t('Note: if you have an account with one of our affiliates (!s), you may <a href="@login_uri">login now</a> instead of registering.', array('!s' => $affiliates, '@login_uri' => url('user'))) .'</p>');
-  }
-  // Merge in the default user edit fields.
-  $form = array_merge($form, user_edit_form(NULL, NULL, TRUE));
-  if ($admin) {
-    $form['account']['notify'] = array(
-     '#type' => 'checkbox',
-     '#title' => t('Notify user of new account')
-    );
-    // Redirect back to page which initiated the create request; usually admin/user/user/create
-    $form['destination'] = array('#type' => 'hidden', '#value' => $_GET['q']);
-  }
-
-  // Create a dummy variable for pass-by-reference parameters.
-  $null = NULL;
-  $extra = _user_forms($null, NULL, NULL, 'register');
-
-  // Remove form_group around default fields if there are no other groups.
-  if (!$extra) {
-    foreach (array('name', 'mail', 'pass', 'status', 'roles', 'notify') as $key) {
-      if (isset($form['account'][$key])) {
-        $form[$key] = $form['account'][$key];
-      }
-    }
-    unset($form['account']);
-  }
-  else {
-    $form = array_merge($form, $extra);
-  }
-  $form['submit'] = array('#type' => 'submit', '#value' => t('Create new account'), '#weight' => 30);
-
-  return $form;
-}
-
-function user_register_validate($form_id, $form_values) {
-  user_module_invoke('validate', $form_values, $form_values, 'account');
-}
-
-function user_register_submit($form_id, $form_values) {
-  global $base_url;
-  $admin = user_access('administer users');
-
-  $mail = $form_values['mail'];
-  $name = $form_values['name'];
-  if (!variable_get('user_email_verification', TRUE) || $admin) {
-    $pass = $form_values['pass'];
-  }
-  else {
-    $pass = user_password();
-  };
-  $notify = isset($form_values['notify']) ? $form_values['notify'] : NULL;
-  $from = variable_get('site_mail', ini_get('sendmail_from'));
-  if (isset($form_values['roles'])) {
-    $roles = array_filter($form_values['roles']);     // Remove unset roles
-  }
-  else {
-    $roles = array();
-  }
-
-  if (!$admin && array_intersect(array_keys($form_values), array('uid', 'roles', 'init', 'session', 'status'))) {
-    watchdog('security', 'Detected malicious attempt to alter protected user fields.', array(), WATCHDOG_WARNING);
-    return 'user/register';
-  }
-  //the unset below is needed to prevent these form values from being saved as user data
-  unset($form_values['form_token'], $form_values['submit'], $form_values['op'], $form_values['notify'], $form_values['form_id'], $form_values['affiliates'], $form_values['destination']);
-
-  $merge_data = array('pass' => $pass, 'init' => $mail, 'roles' => $roles);
-  if (!$admin) {
-    // Set the user's status because it was not displayed in the form.
-    $merge_data['status'] = variable_get('user_register', 1) == 1;
-  }
-  $account = user_save('', array_merge($form_values, $merge_data));
-  watchdog('user', 'New user: %name %email.', array('%name' => $name, '%email' => '<'. $mail .'>'), WATCHDOG_NOTICE, l(t('edit'), 'user/'. $account->uid .'/edit'));
-
-  $variables = array('!username' => $name, '!site' => variable_get('site_name', 'Drupal'), '!password' => $pass, '!uri' => $base_url, '!uri_brief' => substr($base_url, strlen('http://')), '!mailto' => $mail, '!date' => format_date(time()), '!login_uri' => url('user', array('absolute' => TRUE)), '!edit_uri' => url('user/'. $account->uid .'/edit', array('absolute' => TRUE)), '!login_url' => user_pass_reset_url($account));
-
-  // The first user may login immediately, and receives a customized welcome e-mail.
-  if ($account->uid == 1) {
-    drupal_mail('user-register-admin', $mail, t('Drupal user account details for !s', array('!s' => $name)), strtr(t("!username,\n\nYou may now login to !uri using the following username and password:\n\n  username: !username\n  password: !password\n\n!edit_uri\n\n--drupal"), $variables), $from);
-    drupal_set_message(t('<p>Welcome to Drupal. You are user #1, which gives you full and immediate access. All future registrants will receive their passwords via e-mail, so please make sure your website e-mail address is set properly under the general settings on the <a href="@settings">site information settings page</a>.</p><p> Your password is <strong>%pass</strong>. You may change your password below.</p>', array('%pass' => $pass, '@settings' => url('admin/settings/site-information'))));
-    user_authenticate($account->name, trim($pass));
-
-    return 'user/1/edit';
-  }
-  else {
-    if ($admin && !$notify) {
-      drupal_set_message(t('Created a new user account. No e-mail has been sent.'));
-    }
-    else if (!variable_get('user_email_verification', TRUE) && $account->status && !$admin) {
-      // No e-mail verification is required, create new user account, and login user immediately.
-      $subject = _user_mail_text('welcome_subject', $variables);
-      $body = _user_mail_text('welcome_body', $variables);
-      drupal_mail('user-register-welcome', $mail, $subject, $body, $from);
-      user_authenticate($account->name, trim($pass));
-      return '';
-    }
-    else if ($account->status || $notify) {
-      // Create new user account, no administrator approval required.
-      $subject = $notify ? _user_mail_text('admin_subject', $variables) : _user_mail_text('welcome_subject', $variables);
-      $body = $notify ? _user_mail_text('admin_body', $variables) : _user_mail_text('welcome_body', $variables);
-
-      drupal_mail(($notify ? 'user-register-notify' : 'user-register-welcome'), $mail, $subject, $body, $from);
-
-      if ($notify) {
-        drupal_set_message(t('Password and further instructions have been e-mailed to the new user %user.', array('%user' => $name)));
-      }
-      else {
-        drupal_set_message(t('Your password and further instructions have been sent to your e-mail address.'));
-        return '';
-      }
-    }
-    else {
-      // Create new user account, administrator approval required.
-      $subject = _user_mail_text('approval_subject', $variables);
-      $body = _user_mail_text('approval_body', $variables);
-
-      drupal_mail('user-register-approval-user', $mail, $subject, $body, $from);
-      drupal_mail('user-register-approval-admin', $from, $subject, t("!username has applied for an account.\n\n!edit_uri", $variables), $from);
-      drupal_set_message(t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.<br />In the meantime, your password and further instructions have been sent to your e-mail address.'));
-
-    }
-  }
-}
-
-function user_edit_form($uid, $edit, $register = FALSE) {
-  $admin = user_access('administer users');
-
-  // Account information:
-  $form['account'] = array('#type' => 'fieldset',
-    '#title' => t('Account information'),
-  );
-  if (user_access('change own username') || $admin || $register) {
-    $form['account']['name'] = array('#type' => 'textfield',
-      '#title' => t('Username'),
-      '#default_value' => $edit['name'],
-      '#maxlength' => USERNAME_MAX_LENGTH,
-      '#description' => t('Your preferred username; punctuation is not allowed except for periods, hyphens, and underscores.'),
-      '#required' => TRUE,
-    );
-  }
-  $form['account']['mail'] = array('#type' => 'textfield',
-    '#title' => t('E-mail address'),
-    '#default_value' => $edit['mail'],
-    '#maxlength' => EMAIL_MAX_LENGTH,
-    '#description' => t('A valid e-mail address. All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'),
-    '#required' => TRUE,
-  );
-  if (!$register) {
-    $form['account']['pass'] = array('#type' => 'password_confirm',
-      '#description' => t('To change the current user password, enter the new password in both fields.'),
-      '#size' => 25,
-    );
-  }
-  elseif (!variable_get('user_email_verification', TRUE) || $admin) {
-    $form['account']['pass'] = array(
-      '#type' => 'password_confirm',
-      '#description' => t('Provide a password for the new account in both fields.'),
-      '#required' => TRUE,
-      '#size' => 25,
-    );
-  }
-  if ($admin) {
-    $form['account']['status'] = array('#type' => 'radios', '#title' => t('Status'), '#default_value' => isset($edit['status']) ? $edit['status'] : 1, '#options' => array(t('Blocked'), t('Active')));
-  }
-  if (user_access('administer access control')) {
-    $roles = user_roles(1);
-    unset($roles[DRUPAL_AUTHENTICATED_RID]);
-    if ($roles) {
-      $default = empty($edit['roles']) ? array() : array_keys($edit['roles']);
-      $form['account']['roles'] = array('#type' => 'checkboxes', '#title' => t('Roles'), '#default_value' => $default, '#options' => $roles, '#description' => t('The user receives the combined permissions of the %au role, and all roles selected here.', array('%au' => t('authenticated user'))));
-    }
-  }
-
-  // Signature:
-  if (variable_get('user_signatures', 0) && module_exists('comment') && !$register) {
-    $form['signature_settings'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Signature settings'),
-      '#weight' => 1,
-    );
-    $form['signature_settings']['signature'] = array(
-      '#type' => 'textarea',
-      '#title' => t('Signature'),
-      '#default_value' => $edit['signature'],
-      '#description' => t('Your signature will be publicly displayed at the end of your comments.'),
-    );
-  }
-
-  // Picture/avatar:
-  if (variable_get('user_pictures', 0) && !$register) {
-    $form['picture'] = array('#type' => 'fieldset', '#title' => t('Picture'), '#weight' => 1);
-    $picture = theme('user_picture', (object)$edit);
-    if ($picture) {
-      $form['picture']['current_picture'] = array('#value' => $picture);
-      $form['picture']['picture_delete'] = array('#type' => 'checkbox', '#title' => t('Delete picture'), '#description' => t('Check this box to delete your current picture.'));
-    }
-    else {
-      $form['picture']['picture_delete'] = array('#type' => 'hidden');
-    }
-    $form['picture']['picture_upload'] = array('#type' => 'file', '#title' => t('Upload picture'), '#size' => 48, '#description' => t('Your virtual face or picture. Maximum dimensions are %dimensions and the maximum size is %size kB.', array('%dimensions' => variable_get('user_picture_dimensions', '85x85'), '%size' => variable_get('user_picture_file_size', '30'))) .' '. variable_get('user_picture_guidelines', ''));
-  }
-
-  return $form;
-}
-
-function _user_edit_validate($uid, &$edit) {
-  $user = user_load(array('uid' => $uid));
-  // Validate the username:
-  if (user_access('change own username') || user_access('administer users') || arg(1) == 'register') {
-    if ($error = user_validate_name($edit['name'])) {
-      form_set_error('name', $error);
-    }
-    else if (db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != %d AND LOWER(name) = LOWER('%s')", $uid, $edit['name'])) > 0) {
-      form_set_error('name', t('The name %name is already taken.', array('%name' => $edit['name'])));
-    }
-    else if (drupal_is_denied('user', $edit['name'])) {
-      form_set_error('name', t('The name %name has been denied access.', array('%name' => $edit['name'])));
-    }
-  }
-
-  // Validate the e-mail address:
-  if ($error = user_validate_mail($edit['mail'])) {
-    form_set_error('mail', $error);
-  }
-  else if (db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != %d AND LOWER(mail) = LOWER('%s')", $uid, $edit['mail'])) > 0) {
-    form_set_error('mail', t('The e-mail address %email is already registered. <a href="@password">Have you forgotten your password?</a>', array('%email' => $edit['mail'], '@password' => url('user/password'))));
-  }
-  else if (drupal_is_denied('mail', $edit['mail'])) {
-    form_set_error('mail', t('The e-mail address %email has been denied access.', array('%email' => $edit['mail'])));
-  }
-
-  // If required, validate the uploaded picture.
-  if ($file = file_check_upload('picture_upload')) {
-    user_validate_picture($file, $edit, $user);
-  }
-}
-
-function _user_edit_submit($uid, &$edit) {
-  $user = user_load(array('uid' => $uid));
-  // Delete picture if requested, and if no replacement picture was given.
-  if (!empty($edit['picture_delete'])) {
-    if ($user->picture && file_exists($user->picture)) {
-      file_delete($user->picture);
-    }
-    $edit['picture'] = '';
-  }
-  if (isset($edit['roles'])) {
-    $edit['roles'] = array_filter($edit['roles']);
-  }
-}
-
-function user_edit($category = 'account') {
-  global $user;
-
-  $account = user_load(array('uid' => arg(1)));
-  if ($account === FALSE) {
-    drupal_set_message(t('The account does not exist or has already been deleted.'));
-    drupal_goto('admin/user/user');
-  }
-  $op = !empty($_POST['op']) ? $_POST['op'] : '';
-  $edit = $op ? $_POST : (array)$account;
-
-  if (arg(2) == 'delete') {
-    if ($edit['confirm']) {
-      user_delete($edit, $account->uid);
-      drupal_goto('admin/user/user');
-    }
-    else {
-      return drupal_get_form('user_confirm_delete', $account->name, $account->uid);
-    }
-  }
-  else if ($op == t('Delete')) {
-    if ($_REQUEST['destination']) {
-      $destination = drupal_get_destination();
-      unset($_REQUEST['destination']);
-    }
-    // Note: we redirect from user/uid/edit to user/uid/delete to make the tabs disappear.
-    drupal_goto("user/$account->uid/delete", $destination);
-  }
-
-  $form = _user_forms($edit, $account, $category);
-  $form['_category'] = array('#type' => 'value', '#value' => $category);
-  $form['_account'] = array('#type' => 'value', '#value' => $account);
-  $form['submit'] = array('#type' => 'submit', '#value' => t('Submit'), '#weight' => 30);
-  if (user_access('administer users')) {
-    $form['delete'] = array('#type' => 'submit', '#value' => t('Delete'), '#weight' => 31);
-  }
-  $form['#attributes']['enctype'] = 'multipart/form-data';
-
-  drupal_set_title(check_plain($account->name));
-  return $form;
-}
-
-function user_confirm_delete($name, $uid) {
-  return confirm_form(array(),
-    t('Are you sure you want to delete the account %name?', array('%name' => $name)),
-    'user/'. $uid,
-    t('All submissions made by this user will be attributed to the anonymous account. This action cannot be undone.'),
-    t('Delete'), t('Cancel'));
-}
-
-/**
- * Delete a user.
- *
- * @param $edit An array of submitted form values.
- * @param $uid The user ID of the user to delete.
- */
-function user_delete($edit, $uid) {
-  $account = user_load(array('uid' => $uid));
-  sess_destroy_uid($uid);
-  db_query('DELETE FROM {users} WHERE uid = %d', $uid);
-  db_query('DELETE FROM {users_roles} WHERE uid = %d', $uid);
-  db_query('DELETE FROM {authmap} WHERE uid = %d', $uid);
-  $variables = array('%name' => $account->name, '%email' => '<'. $account->mail .'>');
-  watchdog('user', 'Deleted user: %name %email.', $variables, WATCHDOG_NOTICE);
-  drupal_set_message(t('%name has been deleted.', $variables));
-  module_invoke_all('user', 'delete', $edit, $account);
-}
-
-function user_edit_validate($form_id, $form_values) {
-  user_module_invoke('validate', $form_values, $form_values['_account'], $form_values['_category']);
-  // Validate input to ensure that non-privileged users can't alter protected data.
-  if ((!user_access('administer users') && array_intersect(array_keys($form_values), array('uid', 'init', 'session'))) || (!user_access('administer access control') && isset($form_values['roles']))) {
-    watchdog('security', 'Detected malicious attempt to alter protected user fields.', array(), WATCHDOG_WARNING);
-    // set this to a value type field
-    form_set_error('category', t('Detected malicious attempt to alter protected user fields.'));
-  }
-}
-
-function user_edit_submit($form_id, $form_values) {
-  $account = $form_values['_account'];
-  $category = $form_values['_category'];
-  unset($form_values['_account'], $form_values['op'], $form_values['submit'], $form_values['delete'], $form_values['form_token'], $form_values['form_id'], $form_values['_category']);
-  user_module_invoke('submit', $form_values, $account, $category);
-  user_save($account, $form_values, $category);
-
-  // Clear the page cache because pages can contain usernames and/or profile information:
-  cache_clear_all();
-
-  drupal_set_message(t('The changes have been saved.'));
-  return 'user/'. $account->uid;
-}
-
-function user_view($account) {
-  global $user;
-
-  drupal_set_title(check_plain($account->name));
-  // Retrieve and merge all profile fields:
-  $fields = array();
-  foreach (module_list() as $module) {
-    if ($data = module_invoke($module, 'user', 'view', '', $account)) {
-      foreach ($data as $category => $items) {
-        foreach ($items as $key => $item) {
-          $item['class'] = "$module-". $item['class'];
-          $fields[$category][$key] = $item;
-        }
-      }
-    }
-  }
-
-  drupal_alter('profile', $fields, $account);
-
-  drupal_set_title(check_plain($account->name));
-  return theme('user_profile', $account, $fields);
-}
-
-/*** Administrative features ***********************************************/
-
-function _user_mail_text($messageid, $variables = array()) {
-
-  // Check if an admin setting overrides the default string.
-  if ($admin_setting = variable_get('user_mail_'. $messageid, FALSE)) {
-    return strtr($admin_setting, $variables);
-  }
-  // No override, return with default strings.
-  else {
-    switch ($messageid) {
-      case 'welcome_subject':
-        return t('Account details for !username at !site', $variables);
-      case 'welcome_body':
-        return t("!username,\n\nThank you for registering at !site. 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);
-      case 'admin_subject':
-        return t('An administrator created an account for you at !site', $variables);
-      case 'admin_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);
-      case 'approval_subject':
-        return t('Account details for !username at !site (pending admin approval)', $variables);
-      case '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 granted, you may 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 may wish to change your password at !edit_uri\n\n\n--  !site team", $variables);
-      case 'pass_subject':
-        return t('Replacement login information for !username at !site', $variables);
-      case 'pass_body':
-        return t("!username,\n\nA request to reset the password for your account has been made at !site.\n\nYou may now log in to !uri_brief 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. It expires after one day and nothing will happen if it's not used.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.", $variables);
-    }
-  }
-}
-
-function user_admin_check_user() {
-  $form['user'] = array('#type' => 'fieldset', '#title' => t('Username'));
-  $form['user']['test'] = array('#type' => 'textfield', '#title' => '', '#description' => t('Enter a username to check if it will be denied or allowed.'), '#size' => 30, '#maxlength' => USERNAME_MAX_LENGTH);
-  $form['user']['type'] = array('#type' => 'hidden', '#value' => 'user');
-  $form['user']['submit'] = array('#type' => 'submit', '#value' => t('Check username'));
-  $form['#submit']['user_admin_access_check_submit'] = array();
-  $form['#validate']['user_admin_access_check_validate'] = array();
-  $form['#theme'] = 'user_admin_access_check';
-  return $form;
-}
-
-function user_admin_check_mail() {
-  $form['mail'] = array('#type' => 'fieldset', '#title' => t('E-mail'));
-  $form['mail']['test'] = array('#type' => 'textfield', '#title' => '', '#description' => t('Enter an e-mail address to check if it will be denied or allowed.'), '#size' => 30, '#maxlength' => EMAIL_MAX_LENGTH);
-  $form['mail']['type'] = array('#type' => 'hidden', '#value' => 'mail');
-  $form['mail']['submit'] = array('#type' => 'submit', '#value' => t('Check e-mail'));
-  $form['#submit']['user_admin_access_check_submit'] = array();
-  $form['#validate']['user_admin_access_check_validate'] = array();
-  $form['#theme'] = 'user_admin_access_check';
-  return $form;
-}
-
-function user_admin_check_host() {
-  $form['host'] = array('#type' => 'fieldset', '#title' => t('Hostname'));
-  $form['host']['test'] = array('#type' => 'textfield', '#title' => '', '#description' => t('Enter a hostname or IP address to check if it will be denied or allowed.'), '#size' => 30, '#maxlength' => 64);
-  $form['host']['type'] = array('#type' => 'hidden', '#value' => 'host');
-  $form['host']['submit'] = array('#type' => 'submit', '#value' => t('Check hostname'));
-  $form['#submit']['user_admin_access_check_submit'] = array();
-  $form['#validate']['user_admin_access_check_validate'] = array();
-  $form['#theme'] = 'user_admin_access_check';
-  return $form;
-}
-
-/**
- * Menu callback: check an access rule
- */
-function user_admin_access_check() {
-  $output = drupal_get_form('user_admin_check_user');
-  $output .= drupal_get_form('user_admin_check_mail');
-  $output .= drupal_get_form('user_admin_check_host');
-  return $output;
-}
-
-function user_admin_access_check_validate($form_id, $form_values) {
-  if (empty($form_values['test'])) {
-    form_set_error($form_values['type'], t('No value entered. Please enter a test string and try again.'));
-  }
-}
-
-function user_admin_access_check_submit($form_id, $form_values) {
-  switch ($form_values['type']) {
-    case 'user':
-      if (drupal_is_denied('user', $form_values['test'])) {
-        drupal_set_message(t('The username %name is not allowed.', array('%name' => $form_values['test'])));
-      }
-      else {
-        drupal_set_message(t('The username %name is allowed.', array('%name' => $form_values['test'])));
-      }
-      break;
-    case 'mail':
-      if (drupal_is_denied('mail', $form_values['test'])) {
-        drupal_set_message(t('The e-mail address %mail is not allowed.', array('%mail' => $form_values['test'])));
-      }
-      else {
-        drupal_set_message(t('The e-mail address %mail is allowed.', array('%mail' => $form_values['test'])));
-      }
-      break;
-    case 'host':
-      if (drupal_is_denied('host', $form_values['test'])) {
-        drupal_set_message(t('The hostname %host is not allowed.', array('%host' => $form_values['test'])));
-      }
-      else {
-        drupal_set_message(t('The hostname %host is allowed.', array('%host' => $form_values['test'])));
-      }
-      break;
-    default:
-      break;
-  }
-}
-
-/**
- * Menu callback: add an access rule
- */
-function user_admin_access_add($mask = NULL, $type = NULL) {
-  if ($edit = $_POST) {
-    if (!$edit['mask']) {
-      form_set_error('mask', t('You must enter a mask.'));
-    }
-    else {
-      $aid = db_next_id('{access}_aid');
-      db_query("INSERT INTO {access} (aid, mask, type, status) VALUES ('%s', '%s', '%s', %d)", $aid, $edit['mask'], $edit['type'], $edit['status']);
-      drupal_set_message(t('The access rule has been added.'));
-      drupal_goto('admin/user/rules');
-    }
-  }
-  else {
-    $edit['mask'] = $mask;
-    $edit['type'] = $type;
-  }
-  return drupal_get_form('user_admin_access_add_form', $edit, t('Add rule'));
-}
-
-/**
- * Menu callback: delete an access rule
- */
-function user_admin_access_delete_confirm($aid = 0) {
-  $access_types = array('user' => t('username'), 'mail' => t('e-mail'), 'host' => t('host'));
-  $edit = db_fetch_object(db_query('SELECT aid, type, status, mask FROM {access} WHERE aid = %d', $aid));
-
-  $form = array();
-  $form['aid'] = array('#type' => 'hidden', '#value' => $aid);
-  $output = confirm_form($form,
-                  t('Are you sure you want to delete the @type rule for %rule?', array('@type' => $access_types[$edit->type], '%rule' => $edit->mask)),
-                  'admin/user/rules',
-                  t('This action cannot be undone.'),
-                  t('Delete'),
-                  t('Cancel'));
-  return $output;
-}
-
-function user_admin_access_delete_confirm_submit($form_id, $form_values) {
-  db_query('DELETE FROM {access} WHERE aid = %d', $form_values['aid']);
-  drupal_set_message(t('The access rule has been deleted.'));
-  return 'admin/user/rules';
-}
-
-/**
- * Menu callback: edit an access rule
- */
-function user_admin_access_edit($aid = 0) {
-  if ($edit = $_POST) {
-    if (!$edit['mask']) {
-      form_set_error('mask', t('You must enter a mask.'));
-    }
-    else {
-      db_query("UPDATE {access} SET mask = '%s', type = '%s', status = '%s' WHERE aid = %d", $edit['mask'], $edit['type'], $edit['status'], $aid);
-      drupal_set_message(t('The access rule has been saved.'));
-      drupal_goto('admin/user/rules');
-    }
-  }
-  else {
-    $edit = db_fetch_array(db_query('SELECT aid, type, status, mask FROM {access} WHERE aid = %d', $aid));
-  }
-  return drupal_get_form('user_admin_access_edit_form', $edit, t('Save rule'));
-}
-
-function user_admin_access_form($edit, $submit) {
-  $form['status'] = array(
-    '#type' => 'radios',
-    '#title' => t('Access type'),
-    '#default_value' => isset($edit['status']) ? $edit['status'] : array(),
-    '#options' => array('1' => t('Allow'), '0' => t('Deny')),
-  );
-  $type_options = array('user' => t('Username'), 'mail' => t('E-mail'), 'host' => t('Host'));
-  $form['type'] = array(
-    '#type' => 'radios',
-    '#title' => t('Rule type'),
-    '#default_value' => (isset($type_options[$edit['type']]) ? $edit['type'] : 'user'),
-    '#options' => $type_options,
-  );
-  $form['mask'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Mask'),
-    '#size' => 30,
-    '#maxlength' => 64,
-    '#default_value' => $edit['mask'],
-    '#description' => '%: '. t('Matches any number of characters, even zero characters') .'.<br />_: '. t('Matches exactly one character.'),
-    '#required' => TRUE,
-  );
-  $form['submit'] = array('#type' => 'submit', '#value' => $submit);
-
-  return $form;
-}
-
-/**
- * Menu callback: list all access rules
- */
-function user_admin_access() {
-  $header = array(array('data' => t('Access type'), 'field' => 'status'), array('data' => t('Rule type'), 'field' => 'type'), array('data' => t('Mask'), 'field' => 'mask'), array('data' => t('Operations'), 'colspan' => 2));
-  $result = db_query("SELECT aid, type, status, mask FROM {access}". tablesort_sql($header));
-  $access_types = array('user' => t('username'), 'mail' => t('e-mail'), 'host' => t('host'));
-  $rows = array();
-  while ($rule = db_fetch_object($result)) {
-    $rows[] = array($rule->status ? t('allow') : t('deny'), $access_types[$rule->type], $rule->mask, l(t('edit'), 'admin/user/rules/edit/'. $rule->aid), l(t('delete'), 'admin/user/rules/delete/'. $rule->aid));
-  }
-  if (empty($rows)) {
-    $rows[] = array(array('data' => '<em>'. t('There are currently no access rules.') .'</em>', 'colspan' => 5));
-  }
-  return theme('table', $header, $rows);
-}
-
-/**
- * Retrieve an array of roles matching specified conditions.
- *
- * @param $membersonly
- *   Set this to TRUE to exclude the 'anonymous' role.
- * @param $permission
- *   A string containing a permission. If set, only roles containing that permission are returned.
- *
- * @return
- *   An associative array with the role id as the key and the role name as value.
- */
-function user_roles($membersonly = 0, $permission = 0) {
-  $roles = array();
-
-  if ($permission) {
-    $result = db_query("SELECT r.* FROM {role} r INNER JOIN {permission} p ON r.rid = p.rid WHERE p.perm LIKE '%%%s%%' ORDER BY r.name", $permission);
-  }
-  else {
-    $result = db_query('SELECT * FROM {role} ORDER BY name');
-  }
-  while ($role = db_fetch_object($result)) {
-    if (!$membersonly || ($membersonly && $role->rid != DRUPAL_ANONYMOUS_RID)) {
-      $roles[$role->rid] = $role->name;
-    }
-  }
-  return $roles;
-}
-
-/**
- * Menu callback: administer permissions.
- */
-function user_admin_perm($rid = NULL) {
-  if (is_numeric($rid)) {
-    $result = db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid WHERE r.rid = %d', $rid);
-  }
-  else {
-    $result = db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid ORDER BY name');
-  }
-
-  // Compile role array:
-  // Add a comma at the end so when searching for a permission, we can
-  // always search for "$perm," to make sure we do not confuse
-  // permissions that are substrings of each other.
-  while ($role = db_fetch_object($result)) {
-    $role_permissions[$role->rid] = $role->perm .',';
-  }
-
-  if (is_numeric($rid)) {
-    $result = db_query('SELECT rid, name FROM {role} r WHERE r.rid = %d ORDER BY name', $rid);
-  }
-  else {
-    $result = db_query('SELECT rid, name FROM {role} ORDER BY name');
-  }
-
-  $role_names = array();
-  while ($role = db_fetch_object($result)) {
-    $role_names[$role->rid] = $role->name;
-  }
-
-  // Render role/permission overview:
-  $options = array();
-  foreach (module_list(FALSE, FALSE, TRUE) as $module) {
-    if ($permissions = module_invoke($module, 'perm')) {
-      $form['permission'][] = array(
-        '#value' => $module,
-      );
-      asort($permissions);
-      foreach ($permissions as $perm) {
-        $options[$perm] = '';
-        $form['permission'][$perm] = array('#value' => t($perm));
-        foreach ($role_names as $rid => $name) {
-          // Builds arrays for checked boxes for each role
-          if (strpos($role_permissions[$rid], $perm .',') !== FALSE) {
-            $status[$rid][] = $perm;
-          }
-        }
-      }
-    }
-  }
-
-  // Have to build checkboxes here after checkbox arrays are built
-  foreach ($role_names as $rid => $name) {
-    $form['checkboxes'][$rid] = array('#type' => 'checkboxes', '#options' => $options, '#default_value' => isset($status[$rid]) ? $status[$rid] : array());
-    $form['role_names'][$rid] = array('#value' => $name, '#tree' => TRUE);
-  }
-  $form['submit'] = array('#type' => 'submit', '#value' => t('Save permissions'));
-
-  return $form;
-}
-
-function theme_user_admin_perm($form) {
-  foreach (element_children($form['permission']) as $key) {
-    // Don't take form control structures
-    if (is_array($form['permission'][$key])) {
-      $row = array();
-      // Module name
-      if (is_numeric($key)) {
-        $row[] = array('data' => t('@module module', array('@module' => drupal_render($form['permission'][$key]))), 'class' => 'module', 'id' => 'module-'. $form['permission'][$key]['#value'], 'colspan' => count($form['role_names']) + 1);
-      }
-      else {
-        $row[] = array('data' => drupal_render($form['permission'][$key]), 'class' => 'permission');
-        foreach (element_children($form['checkboxes']) as $rid) {
-          if (is_array($form['checkboxes'][$rid])) {
-            $row[] = array('data' => drupal_render($form['checkboxes'][$rid][$key]), 'align' => 'center', 'title' => t($key));
-          }
-        }
-      }
-      $rows[] = $row;
-    }
-  }
-  $header[] = (t('Permission'));
-  foreach (element_children($form['role_names']) as $rid) {
-    if (is_array($form['role_names'][$rid])) {
-      $header[] = drupal_render($form['role_names'][$rid]);
-    }
-  }
-  $output = theme('table', $header, $rows, array('id' => 'permissions'));
-  $output .= drupal_render($form);
-  return $output;
-}
-
-function user_admin_perm_submit($form_id, $form_values) {
-  // Save permissions:
-  $result = db_query('SELECT * FROM {role}');
-  while ($role = db_fetch_object($result)) {
-    if (isset($form_values[$role->rid])) {
-      // Delete, so if we clear every checkbox we reset that role;
-      // otherwise permissions are active and denied everywhere.
-      db_query('DELETE FROM {permission} WHERE rid = %d', $role->rid);
-      $form_values[$role->rid] = array_filter($form_values[$role->rid]);
-      if (count($form_values[$role->rid])) {
-        db_query("INSERT INTO {permission} (rid, perm) VALUES (%d, '%s')", $role->rid, implode(', ', array_keys($form_values[$role->rid])));
-      }
-    }
-  }
-
-  drupal_set_message(t('The changes have been saved.'));
-
-  // Clear the cached pages and menus:
-  menu_rebuild();
-
-}
-
-/**
- * Menu callback: administer roles.
- */
-function user_admin_role() {
-  $id = arg(4);
-  if ($id) {
-    if (DRUPAL_ANONYMOUS_RID == $id || DRUPAL_AUTHENTICATED_RID == $id) {
-      drupal_goto('admin/user/roles');
-    }
-    // Display the edit role form.
-    $role = db_fetch_object(db_query('SELECT * FROM {role} WHERE rid = %d', $id));
-    $form['name'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Role name'),
-      '#default_value' => $role->name,
-      '#size' => 30,
-      '#required' => TRUE,
-      '#maxlength' => 64,
-      '#description' => t('The name for this role. Example: "moderator", "editorial board", "site architect".'),
-    );
-    $form['rid'] = array(
-      '#type' => 'value',
-      '#value' => $id,
-    );
-    $form['submit'] = array(
-      '#type' => 'submit',
-      '#value' => t('Save role'),
-    );
-    $form['delete'] = array(
-      '#type' => 'submit',
-      '#value' => t('Delete role'),
-    );
-  }
-  else {
-    $form['name'] = array(
-      '#type' => 'textfield',
-      '#size' => 32,
-      '#maxlength' => 64,
-    );
-    $form['submit'] = array(
-      '#type' => 'submit',
-      '#value' => t('Add role'),
-    );
-    $form['#submit']['user_admin_role_submit'] = array();
-    $form['#validate']['user_admin_role_validate'] = array();
-  }
-  return $form;
-}
-
-function user_admin_role_validate($form_id, $form_values) {
-  if ($form_values['name']) {
-    if ($form_values['op'] == t('Save role')) {
-      if (db_result(db_query("SELECT COUNT(*) FROM {role} WHERE name = '%s' AND rid != %d", $form_values['name'], $form_values['rid']))) {
-        form_set_error('name', t('The role name %name already exists. Please choose another role name.', array('%name' => $form_values['name'])));
-      }
-    }
-    else if ($form_values['op'] == t('Add role')) {
-      if (db_result(db_query("SELECT COUNT(*) FROM {role} WHERE name = '%s'", $form_values['name']))) {
-        form_set_error('name', t('The role name %name already exists. Please choose another role name.', array('%name' => $form_values['name'])));
-      }
-    }
-  }
-  else {
-    form_set_error('name', t('You must specify a valid role name.'));
-  }
-}
-
-function user_admin_role_submit($form_id, $form_values) {
-  if ($form_values['op'] == t('Save role')) {
-    db_query("UPDATE {role} SET name = '%s' WHERE rid = %d", $form_values['name'], $form_values['rid']);
-    drupal_set_message(t('The role has been renamed.'));
-  }
-  else if ($form_values['op'] == t('Delete role')) {
-    db_query('DELETE FROM {role} WHERE rid = %d', $form_values['rid']);
-    db_query('DELETE FROM {permission} WHERE rid = %d', $form_values['rid']);
-    // Update the users who have this role set:
-    db_query('DELETE FROM {users_roles} WHERE rid = %d', $form_values['rid']);
-
-    drupal_set_message(t('The role has been deleted.'));
-  }
-  else if ($form_values['op'] == t('Add role')) {
-    db_query("INSERT INTO {role} (name) VALUES ('%s')", $form_values['name']);
-    drupal_set_message(t('The role has been added.'));
-  }
-  return 'admin/user/roles';
-}
-
-function theme_user_admin_new_role($form) {
-  $header = array(t('Name'), array('data' => t('Operations'), 'colspan' => 2));
-  foreach (user_roles() as $rid => $name) {
-    $edit_permissions = l(t('edit permissions'), 'admin/user/access/'. $rid);
-    if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
-      $rows[] = array($name, l(t('edit role'), 'admin/user/roles/edit/'. $rid), $edit_permissions);
-    }
-    else {
-      $rows[] = array($name, t('locked'), $edit_permissions);
-    }
-  }
-  $rows[] = array(drupal_render($form['name']), array('data' => drupal_render($form['submit']), 'colspan' => 2));
-
-  $output = drupal_render($form);
-  $output .= theme('table', $header, $rows);
-
-  return $output;
-}
-
-function user_admin_account() {
-  $filter = user_build_filter_query();
-
-  $header = array(
-    array(),
-    array('data' => t('Username'), 'field' => 'u.name'),
-    array('data' => t('Status'), 'field' => 'u.status'),
-    t('Roles'),
-    array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'),
-    array('data' => t('Last access'), 'field' => 'u.access'),
-    t('Operations')
-  );
-
-  $sql = 'SELECT DISTINCT u.uid, u.name, u.status, u.created, u.access FROM {users} u LEFT JOIN {users_roles} ur ON u.uid = ur.uid '. $filter['join'] .' WHERE u.uid != 0 '. $filter['where'];
-  $sql .= tablesort_sql($header);
-  $result = pager_query($sql, 50, 0, NULL, $filter['args']);
-
-  $form['options'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Update options'),
-    '#prefix' => '<div class="container-inline">',
-    '#suffix' => '</div>',
-  );
-  $options = array();
-  foreach (module_invoke_all('user_operations') as $operation => $array) {
-    $options[$operation] = $array['label'];
-  }
-  $form['options']['operation'] = array(
-    '#type' => 'select',
-    '#options' => $options,
-    '#default_value' => 'unblock',
-  );
-  $form['options']['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Update'),
-  );
-
-  $destination = drupal_get_destination();
-
-  $status = array(t('blocked'), t('active'));
-  $roles = user_roles(1);
-  $accounts = array();
-  while ($account = db_fetch_object($result)) {
-    $accounts[$account->uid] = '';
-    $form['name'][$account->uid] = array('#value' => theme('username', $account));
-    $form['status'][$account->uid] =  array('#value' => $status[$account->status]);
-    $users_roles = array();
-    $roles_result = db_query('SELECT rid FROM {users_roles} WHERE uid = %d', $account->uid);
-    while ($user_role = db_fetch_object($roles_result)) {
-      $users_roles[] = $roles[$user_role->rid];
-    }
-    asort($users_roles);
-    $form['roles'][$account->uid][0] = array('#value' => theme('item_list', $users_roles));
-    $form['member_for'][$account->uid] = array('#value' => format_interval(time() - $account->created));
-    $form['last_access'][$account->uid] =  array('#value' => $account->access ? t('@time ago', array('@time' => format_interval(time() - $account->access))) : t('never'));
-    $form['operations'][$account->uid] = array('#value' => l(t('edit'), "user/$account->uid/edit", array('query' => $destination)));
-  }
-  $form['accounts'] = array(
-    '#type' => 'checkboxes',
-    '#options' => $accounts
-  );
-  $form['pager'] = array('#value' => theme('pager', NULL, 50, 0));
-
-  return $form;
-}
-
-/**
- * Theme user administration overview.
- */
-function theme_user_admin_account($form) {
-  // Overview table:
-  $header = array(
-    theme('table_select_header_cell'),
-    array('data' => t('Username'), 'field' => 'u.name'),
-    array('data' => t('Status'), 'field' => 'u.status'),
-    t('Roles'),
-    array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'),
-    array('data' => t('Last access'), 'field' => 'u.access'),
-    t('Operations')
-  );
-
-  $output = drupal_render($form['options']);
-  if (isset($form['name']) && is_array($form['name'])) {
-    foreach (element_children($form['name']) as $key) {
-      $rows[] = array(
-        drupal_render($form['accounts'][$key]),
-        drupal_render($form['name'][$key]),
-        drupal_render($form['status'][$key]),
-        drupal_render($form['roles'][$key]),
-        drupal_render($form['member_for'][$key]),
-        drupal_render($form['last_access'][$key]),
-        drupal_render($form['operations'][$key]),
-      );
-    }
-  }
-  else  {
-    $rows[] = array(array('data' => t('No users available.'), 'colspan' => '7'));
-  }
-
-  $output .= theme('table', $header, $rows);
-  if ($form['pager']['#value']) {
-    $output .= drupal_render($form['pager']);
-  }
-
-  $output .= drupal_render($form);
-
-  return $output;
-}
-
-/**
- * Submit the user administration update form.
- */
-function user_admin_account_submit($form_id, $form_values) {
-  $operations = module_invoke_all('user_operations');
-  $operation = $operations[$form_values['operation']];
-  // Filter out unchecked accounts.
-  $accounts = array_filter($form_values['accounts']);
-  if ($function = $operation['callback']) {
-    // Add in callback arguments if present.
-    if (isset($operation['callback arguments'])) {
-      $args = array_merge(array($accounts), $operation['callback arguments']);
-    }
-    else {
-      $args = array($accounts);
-    }
-    call_user_func_array($function, $args);
-
-    drupal_set_message(t('The update has been performed.'));
-  }
-}
-
-function user_admin_account_validate($form_id, $form_values) {
-  $form_values['accounts'] = array_filter($form_values['accounts']);
-  if (count($form_values['accounts']) == 0) {
-    form_set_error('', t('No users selected.'));
-  }
-}
-
-/**
- * Implementation of hook_user_operations().
- */
-function user_user_operations() {
-  global $form_values;
-
-  $operations = array(
-    'unblock' => array(
-      'label' => t('Unblock the selected users'),
-      'callback' => 'user_user_operations_unblock',
-    ),
-    'block' => array(
-      'label' => t('Block the selected users'),
-      'callback' => 'user_user_operations_block',
-    ),
-    'delete' => array(
-      'label' => t('Delete the selected users'),
-    ),
-  );
-
-  if (user_access('administer access control')) {
-    $roles = user_roles(1);
-    unset($roles[DRUPAL_AUTHENTICATED_RID]);  // Can't edit authenticated role.
-
-    $add_roles = array();
-    foreach ($roles as $key => $value) {
-      $add_roles['add_role-'. $key] = $value;
-    }
-
-    $remove_roles = array();
-    foreach ($roles as $key => $value) {
-      $remove_roles['remove_role-'. $key] = $value;
-    }
-
-    if (count($roles)) {
-      $role_operations = array(
-        t('Add a role to the selected users') => array(
-          'label' => $add_roles,
-        ),
-        t('Remove a role from the selected users') => array(
-          'label' => $remove_roles,
-        ),
-      );
-
-      $operations += $role_operations;
-    }
-  }
-
-  // If the form has been posted, we need to insert the proper data for role editing if necessary.
-  if ($form_values) {
-    $operation_rid = explode('-', $form_values['operation']);
-    $operation = $operation_rid[0];
-    $rid = $operation_rid[1];
-    if ($operation == 'add_role' || $operation == 'remove_role') {
-      if (user_access('administer access control')) {
-        $operations[$form_values['operation']] = array(
-          'callback' => 'user_multiple_role_edit',
-          'callback arguments' => array($operation, $rid),
-        );
-      }
-      else {
-        watchdog('security', 'Detected malicious attempt to alter protected user fields.', array(), WATCHDOG_WARNING);
-        return;
-      }
-    }
-  }
-
-  return $operations;
-}
-
-/**
- * Callback function for admin mass unblocking users.
- */
-function user_user_operations_unblock($accounts) {
-  foreach ($accounts as $uid) {
-    $account = user_load(array('uid' => (int)$uid));
-    // Skip unblocking user if they are already unblocked.
-    if ($account !== FALSE && $account->status == 0) {
-      user_save($account, array('status' => 1));
-    }
-  }
-}
-
-/**
- * Callback function for admin mass blocking users.
- */
-function user_user_operations_block($accounts) {
-  foreach ($accounts as $uid) {
-    $account = user_load(array('uid' => (int)$uid));
-    // Skip blocking user if they are already blocked.
-    if ($account !== FALSE && $account->status == 1) {
-      user_save($account, array('status' => 0));
-    }
-  }
-}
-
-/**
- * Callback function for admin mass adding/deleting a user role.
- */
-function user_multiple_role_edit($accounts, $operation, $rid) {
-  // The role name is not necessary as user_save() will reload the user
-  // object, but some modules' hook_user() may look at this first.
-  $role_name = db_result(db_query('SELECT name FROM {role} WHERE rid = %d', $rid));
-
-  switch ($operation) {
-    case 'add_role':
-      foreach ($accounts as $uid) {
-        $account = user_load(array('uid' => (int)$uid));
-        // Skip adding the role to the user if they already have it.
-        if ($account !== FALSE && !isset($account->roles[$rid])) {
-          $roles = $account->roles + array($rid => $role_name);
-          user_save($account, array('roles' => $roles));
-        }
-      }
-      break;
-    case 'remove_role':
-      foreach ($accounts as $uid) {
-        $account = user_load(array('uid' => (int)$uid));
-        // Skip removing the role from the user if they already don't have it.
-        if ($account !== FALSE && isset($account->roles[$rid])) {
-          $roles = array_diff($account->roles, array($rid => $role_name));
-          user_save($account, array('roles' => $roles));
-        }
-      }
-      break;
-  }
-}
-
-function user_multiple_delete_confirm() {
-  $edit = $_POST;
-
-  $form['accounts'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
-  // array_filter returns only elements with TRUE values
-  foreach (array_filter($edit['accounts']) as $uid => $value) {
-    $user = db_result(db_query('SELECT name FROM {users} WHERE uid = %d', $uid));
-    $form['accounts'][$uid] = array('#type' => 'hidden', '#value' => $uid, '#prefix' => '<li>', '#suffix' => check_plain($user) ."</li>\n");
-  }
-  $form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
-
-  return confirm_form($form,
-                      t('Are you sure you want to delete these users?'),
-                      'admin/user/user', t('This action cannot be undone.'),
-                      t('Delete all'), t('Cancel'));
-}
-
-function user_multiple_delete_confirm_submit($form_id, $form_values) {
-  if ($form_values['confirm']) {
-    foreach ($form_values['accounts'] as $uid => $value) {
-      user_delete($form_values, $uid);
-    }
-    drupal_set_message(t('The users have been deleted.'));
-  }
-  return 'admin/user/user';
-}
-
-function user_admin_settings() {
-  // User registration settings.
-  $form['registration'] = array('#type' => 'fieldset', '#title' => t('User registration settings'));
-  $form['registration']['user_register'] = array('#type' => 'radios', '#title' => t('Public registrations'), '#default_value' => variable_get('user_register', 1), '#options' => array(t('Only site administrators can create new user accounts.'), t('Visitors can create accounts and no administrator approval is required.'), t('Visitors can create accounts but administrator approval is required.')));
-  $form['registration']['user_email_verification'] = array('#type' => 'checkbox', '#title' => t('Require e-mail verification when a visitor creates an account'), '#default_value' => variable_get('user_email_verification', TRUE), '#description' => t('If this box is checked, new users will be required to validate their e-mail address prior to logging into to the site, and will be assigned a system-generated password. With it unchecked, users will be logged in immediately upon registering, and may select their own passwords during registration.'));
-  $form['registration']['user_registration_help'] = array('#type' => 'textarea', '#title' => t('User registration guidelines'), '#default_value' => variable_get('user_registration_help', ''), '#description' => t("This text is displayed at the top of the user registration form. It's useful for helping or instructing your users."));
-
-  // User e-mail settings.
-  $form['email'] = array('#type' => 'fieldset', '#title' => t('User e-mail settings'));
-  $form['email']['user_mail_welcome_subject'] = array('#type' => 'textfield', '#title' => t('Subject of welcome e-mail'), '#default_value' => _user_mail_text('welcome_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri, !login_url.');
-  $form['email']['user_mail_welcome_body'] = array('#type' => 'textarea', '#title' => t('Body of welcome e-mail'), '#default_value' => _user_mail_text('welcome_body'), '#rows' => 15, '#description' => t('Customize the body of the welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !login_uri, !edit_uri, !login_url.');
-  $form['email']['user_mail_admin_subject'] = array('#type' => 'textfield', '#title' => t('Subject of welcome e-mail (user created by administrator)'), '#default_value' => _user_mail_text('admin_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your welcome e-mail, which is sent to new member accounts created by an administrator.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri, !login_url.');
-  $form['email']['user_mail_admin_body'] = array('#type' => 'textarea', '#title' => t('Body of welcome e-mail (user created by administrator)'), '#default_value' => _user_mail_text('admin_body'), '#rows' => 15, '#description' => t('Customize the body of the welcome e-mail, which is sent to new member accounts created by an administrator.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !login_uri, !edit_uri, !login_url.');
-  $form['email']['user_mail_approval_subject'] = array('#type' => 'textfield', '#title' => t('Subject of welcome e-mail (awaiting admin approval)'), '#default_value' => _user_mail_text('approval_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your awaiting approval welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri, !login_url.');
-  $form['email']['user_mail_approval_body'] = array('#type' => 'textarea', '#title' => t('Body of welcome e-mail (awaiting admin approval)'), '#default_value' => _user_mail_text('approval_body'), '#rows' => 15, '#description' => t('Customize the body of the awaiting approval welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !login_uri, !edit_uri, !login_url.');
-  $form['email']['user_mail_pass_subject'] = array('#type' => 'textfield', '#title' => t('Subject of password recovery e-mail'), '#default_value' => _user_mail_text('pass_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your forgotten password e-mail.') .' '. t('Available variables are:') .' !username, !site, !login_url, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri.');
-  $form['email']['user_mail_pass_body'] = array('#type' => 'textarea', '#title' => t('Body of password recovery e-mail'), '#default_value' => _user_mail_text('pass_body'), '#rows' => 15, '#description' => t('Customize the body of the forgotten password e-mail.') .' '. t('Available variables are:') .' !username, !site, !login_url, !uri, !uri_brief, !mailto, !login_uri, !edit_uri.');
-
-  // User signatures.
-  $form['signatures'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Signatures'),
-  );
-  $form['signatures']['user_signatures'] = array(
-    '#type' => 'radios',
-    '#title' => t('Signature support'),
-    '#default_value' => variable_get('user_signatures', 0),
-    '#options' => array(t('Disabled'), t('Enabled')),
-    '#description' => t('Enable signature support.'),
-  );
-
-  // If picture support is enabled, check whether the picture directory exists:
-  if (variable_get('user_pictures', 0)) {
-    $picture_path = file_create_path(variable_get('user_picture_path', 'pictures'));
-    file_check_directory($picture_path, 1, 'user_picture_path');
-  }
-
-  $form['pictures'] = array('#type' => 'fieldset', '#title' => t('Pictures'));
-  $form['pictures']['user_pictures'] = array('#type' => 'radios', '#title' => t('Picture support'), '#default_value' => variable_get('user_pictures', 0), '#options' => array(t('Disabled'), t('Enabled')), '#description' => t('Enable picture support.'));
-  $form['pictures']['user_picture_path'] = array('#type' => 'textfield', '#title' => t('Picture image path'), '#default_value' => variable_get('user_picture_path', 'pictures'), '#size' => 30, '#maxlength' => 255, '#description' => t('Subdirectory in the directory %dir where pictures will be stored.', array('%dir' => file_directory_path() .'/')));
-  $form['pictures']['user_picture_default'] = array('#type' => 'textfield', '#title' => t('Default picture'), '#default_value' => variable_get('user_picture_default', ''), '#size' => 30, '#maxlength' => 255, '#description' => t('URL of picture to display for users with no custom picture selected. Leave blank for none.'));
-  $form['pictures']['user_picture_dimensions'] = array('#type' => 'textfield', '#title' => t('Picture maximum dimensions'), '#default_value' => variable_get('user_picture_dimensions', '85x85'), '#size' => 15, '#maxlength' => 10, '#description' => t('Maximum dimensions for pictures, in pixels.'));
-  $form['pictures']['user_picture_file_size'] = array('#type' => 'textfield', '#title' => t('Picture maximum file size'), '#default_value' => variable_get('user_picture_file_size', '30'), '#size' => 15, '#maxlength' => 10, '#description' => t('Maximum file size for pictures, in kB.'));
-  $form['pictures']['user_picture_guidelines'] = array('#type' => 'textarea', '#title' => t('Picture guidelines'), '#default_value' => variable_get('user_picture_guidelines', ''), '#description' => t("This text is displayed at the picture upload form in addition to the default guidelines. It's useful for helping or instructing your users."));
-
-  return system_settings_form($form);
-}
-
-function user_admin($callback_arg = '') {
-  $op = isset($_POST['op']) ? $_POST['op'] : $callback_arg;
-
-  switch ($op) {
-    case 'search':
-    case t('Search'):
-      $keys = isset($_POST['keys']) ? $_POST['keys'] : NULL;
-      $output = drupal_get_form('search_form', url('admin/user/search'), $keys, 'user') . search_data($keys, 'user');
-      break;
-    case t('Create new account'):
-    case 'create':
-      $output = drupal_get_form('user_register');
-      break;
-    default:
-      if (!empty($_POST['accounts']) && isset($_POST['operation']) && ($_POST['operation'] == 'delete')) {
-        $output = drupal_get_form('user_multiple_delete_confirm');
-      }
-      else {
-        $output = drupal_get_form('user_filter_form');
-        $output .= drupal_get_form('user_admin_account');
-      }
-  }
-  return $output;
-}
-
-/**
- * Implementation of hook_help().
- */
-function user_help($section) {
-  global $user;
-
-  switch ($section) {
-    case 'admin/help#user':
-      $output = '<p>'. t('The user module allows users to register, login, and log out. Users benefit from being able to sign on because it associates content they create with their account and allows various permissions to be set for their roles. The user module supports user roles which can setup fine grained permissions allowing each role to do only what the administrator wants them to. Each user is assigned to one or more roles. By default there are two roles <em>anonymous</em> - a user who has not logged in, and <em>authenticated</em> a user who has signed up and who has been authorized.') .'</p>';
-      $output .= '<p>'. t('Users can use their own name or handle and can fine tune some personal configuration settings through their individual my account page. Registered users need to authenticate by supplying either a local username and password, or a remote username and password such as DelphiForums ID, or one from a Drupal powered website. A visitor accessing your website is assigned an unique ID, the so-called session ID, which is stored in a cookie. For security\'s sake, the cookie does not contain personal information but acts as a key to retrieve the information stored on your server.') .'</p>';
-      $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="@user">User page</a>.', array('@user' => 'http://drupal.org/handbook/modules/user/')) .'</p>';
-      return $output;
-    case 'admin/user/user':
-      return '<p>'. t('Drupal allows users to register, login, log out, maintain user profiles, etc. Users of the site may not use their own names to post content until they have signed up for a user account.') .'</p>';
-    case 'admin/user/user/create':
-    case 'admin/user/user/account/create':
-      return '<p>'. t('This web page allows the administrators to register a new users by hand. Note that you cannot have a user where either the e-mail address or the username match another user in the system.') .'</p>';
-    case 'admin/user/rules':
-      return '<p>'. t('Set up username and e-mail address access rules for new <em>and</em> existing accounts (currently logged in accounts will not be logged out). If a username or e-mail address for an account matches any deny rule, but not an allow rule, then the account will not be allowed to be created or to log in. A host rule is effective for every page view, not just registrations.') .'</p>';
-    case 'admin/user/access':
-      return '<p>'. t('Permissions let you control what users can do on your site. Each user role (defined on the <a href="@role">user roles page</a>) has its own set of permissions. For example, you could give users classified as "Administrators" permission to "administer nodes" but deny this power to ordinary, "authenticated" users. You can use permissions to reveal new features to privileged users (those with subscriptions, for example). Permissions also allow trusted users to share the administrative burden of running a busy site.', array('@role' => url('admin/user/roles'))) .'</p>';
-    case 'admin/user/roles':
-      return t('<p>Roles allow you to fine tune the security and administration of Drupal. A role defines a group of users that have certain privileges as defined in <a href="@permissions">user permissions</a>. Examples of roles include: anonymous user, authenticated user, moderator, administrator and so on. In this area you will define the <em>role names</em> of the various roles. To delete a role choose "edit".</p><p>By default, Drupal comes with two user roles:</p>
-      <ul>
-      <li>Anonymous user: this role is used for users that don\'t have a user account or that are not authenticated.</li>
-      <li>Authenticated user: this role is automatically granted to all logged in users.</li>
-      </ul>', array('@permissions' => url('admin/user/access')));
-    case 'admin/user/search':
-      return '<p>'. t('Enter a simple pattern ("*" may be used as a wildcard match) to search for a username. For example, one may search for "br" and Drupal might return "brian", "brad", and "brenda".') .'</p>';
-    case 'user/help#user':
-      $site = variable_get('site_name', 'Drupal');
-
-      $affiliates = user_auth_help_links();
-      if (count($affiliates)) {
-        $affiliate_info = implode(', ', user_auth_help_links());
-      }
-      else {
-        $affiliate_info = t('one of our affiliates');
-      }
-
-      $output = t('
-      <h3>Distributed authentication<a id="da"></a></h3>
-      <p>One of the more tedious moments in visiting a new website is filling out the registration form. Here at @site, you do not have to fill out a registration form if you are already a member of !affiliate-info. This capability is called <em>distributed authentication</em>, and <a href="@drupal">Drupal</a>, the software which powers @site, fully supports it.</p>
-      <p>Distributed authentication enables a new user to input a username and password into the login box, and immediately be recognized, even if that user never registered at @site. This works because Drupal knows how to communicate with external registration databases. For example, lets say that new user \'Joe\' is already a registered member of <a href="@delphi-forums">Delphi Forums</a>. Drupal informs Joe on registration and login screens that he may login with his Delphi ID instead of registering with @site. Joe likes that idea, and logs in with a username of joe@remote.delphiforums.com and his usual Delphi password. Drupal then contacts the <em>remote.delphiforums.com</em> server behind the scenes (usually using <a href="@xml">XML-RPC</a>, <a href="@http-post">HTTP POST</a>, or <a href="@soap">SOAP</a>) and asks: "Is the password for user Joe correct?". If Delphi replies yes, then we create a new @site account for Joe and log him into it. Joe may keep on logging into @site in the same manner, and he will always be logged into the same account.</p>', array('!affiliate-info' => $affiliate_info, '@site' => $site, '@drupal' => 'http://drupal.org', '@delphi-forums' => 'http://www.delphiforums.com', '@xml' => 'http://www.xmlrpc.com', '@http-post' => 'http://www.w3.org/Protocols/', '@soap' => 'http://www.soapware.org'));
-
-        foreach (module_list() as $module) {
-          if (module_hook($module, 'auth')) {
-            $output .= "<h4><a id=\"$module\"></a>". module_invoke($module, 'info', 'name') .'</h4>';
-            $output .= module_invoke($module, 'help', "user/help#$module");
-          }
-        }
-
-        return $output;
-  }
-
-}
-
-/**
- * Menu callback; Prints user-specific help information.
- */
-function user_help_page() {
-  return user_help('user/help#user');
-}
-
-/**
- * Retrieve a list of all user setting/information categories and sort them by weight.
- */
-function _user_categories($account) {
-  $categories = array();
-
-  foreach (module_list() as $module) {
-    if ($data = module_invoke($module, 'user', 'categories', NULL, $account, '')) {
-      $categories = array_merge($data, $categories);
-    }
-  }
-
-  usort($categories, '_user_sort');
-
-  return $categories;
-}
-
-function _user_sort($a, $b) {
-  $a = (array)$a + array('weight' => 0, 'title' => '');
-  $b = (array)$b + array('weight' => 0, 'title' => '');
-  return $a['weight'] < $b['weight'] ? -1 : ($a['weight'] > $b['weight'] ? 1 : ($a['title'] < $b['title'] ? -1 : 1));
-}
-
-/**
- * Retrieve a list of all form elements for the specified category.
- */
-function _user_forms(&$edit, $account, $category, $hook = 'form') {
-  $groups = array();
-  foreach (module_list() as $module) {
-    if ($data = module_invoke($module, 'user', $hook, $edit, $account, $category)) {
-      $groups = array_merge_recursive($data, $groups);
-    }
-  }
-  uasort($groups, '_user_sort');
-
-  return empty($groups) ? FALSE : $groups;
-}
-
-/**
- * Retrieve a pipe delimited string of autocomplete suggestions for existing users
- */
-function user_autocomplete($string = '') {
-  $matches = array();
-  if ($string) {
-    $result = db_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER('%s%%')", $string, 0, 10);
-    while ($user = db_fetch_object($result)) {
-      $matches[$user->name] = check_plain($user->name);
-   }
-  }
-  print drupal_to_js($matches);
-  exit();
-}
-
-/**
- * List user administration filters that can be applied.
- */
-function user_filters() {
-  // Regular filters
-  $filters = array();
-  $roles = user_roles(1);
-  unset($roles[DRUPAL_AUTHENTICATED_RID]); // Don't list authorized role.
-  if (count($roles)) {
-    $filters['role'] = array(
-      'title' => t('role'),
-      'where' => "ur.rid = %d",
-      'options' => $roles,
-      'join' => '',
-    );
-  }
-
-  $options = array();
-  $t_module = t('module');
-  foreach (module_list() as $module) {
-    if ($permissions = module_invoke($module, 'perm')) {
-      asort($permissions);
-      foreach ($permissions as $permission) {
-        $options["$module $t_module"][$permission] = t($permission);
-      }
-    }
-  }
-  ksort($options);
-  $filters['permission'] = array(
-    'title' => t('permission'),
-    'join' => 'LEFT JOIN {permission} p ON ur.rid = p.rid',
-    'where' => " ((p.perm IS NOT NULL AND p.perm LIKE '%%%s%%') OR u.uid = 1) ",
-    'options' => $options,
-  );
-
-  $filters['status'] = array(
-    'title' => t('status'),
-    'where' => 'u.status = %d',
-    'join' => '',
-    'options' => array(1 => t('active'), 0 => t('blocked')),
-  );
-  return $filters;
-}
-
-/**
- * Build query for user administration filters based on session.
- */
-function user_build_filter_query() {
-  $filters = user_filters();
-
-  // Build query
-  $where = $args = $join = array();
-  foreach ($_SESSION['user_overview_filter'] as $filter) {
-    list($key, $value) = $filter;
-    // This checks to see if this permission filter is an enabled permission for the authenticated role.
-    // If so, then all users would be listed, and we can skip adding it to the filter query.
-    if ($key == 'permission') {
-      $account = new stdClass();
-      $account->uid = 'user_filter';
-      $account->roles = array(DRUPAL_AUTHENTICATED_RID => 1);
-      if (user_access($value, $account)) {
-        continue;
-      }
-    }
-    $where[] = $filters[$key]['where'];
-    $args[] = $value;
-    $join[] = $filters[$key]['join'];
-  }
-  $where = !empty($where) ? 'AND '. implode(' AND ', $where) : '';
-  $join = !empty($join) ? ' '. implode(' ', array_unique($join)) : '';
-
-  return array('where' => $where,
-           'join' => $join,
-           'args' => $args,
-         );
-}
-
-/**
- * Return form for user administration filters.
- */
-function user_filter_form() {
-  $session = &$_SESSION['user_overview_filter'];
-  $session = is_array($session) ? $session : array();
-  $filters = user_filters();
-
-  $i = 0;
-  $form['filters'] = array('#type' => 'fieldset',
-                       '#title' => t('Show only users where'),
-                       '#theme' => 'user_filters',
-                     );
-  foreach ($session as $filter) {
-    list($type, $value) = $filter;
-    $string = ($i++ ? '<em>and</em> where <strong>%a</strong> is <strong>%b</strong>' : '<strong>%a</strong> is <strong>%b</strong>');
-    // Merge an array of arrays into one if necessary.
-    $options = $type == 'permission' ? call_user_func_array('array_merge', $filters[$type]['options']) : $filters[$type]['options'];
-    $form['filters']['current'][] = array('#value' => t($string, array('%a' => $filters[$type]['title'] , '%b' => $options[$value])));
-  }
-
-  foreach ($filters as $key => $filter) {
-    $names[$key] = $filter['title'];
-    $form['filters']['status'][$key] = array('#type' => 'select',
-                                         '#options' => $filter['options'],
-                                       );
-  }
-
-  $form['filters']['filter'] = array('#type' => 'radios',
-                                 '#options' => $names,
-                               );
-  $form['filters']['buttons']['submit'] = array('#type' => 'submit',
-                                            '#value' => (count($session) ? t('Refine') : t('Filter'))
-                                          );
-  if (count($session)) {
-    $form['filters']['buttons']['undo'] = array('#type' => 'submit',
-                                            '#value' => t('Undo')
-                                          );
-    $form['filters']['buttons']['reset'] = array('#type' => 'submit',
-                                             '#value' => t('Reset')
-                                           );
-  }
-
-  return $form;
-}
-
-/**
- * Theme user administration filter form.
- */
-function theme_user_filter_form($form) {
-  $output = '<div id="user-admin-filter">';
-  $output .= drupal_render($form['filters']);
-  $output .= '</div>';
-  $output .= drupal_render($form);
-  return $output;
-}
-
-/**
- * Theme user administration filter selector.
- */
-function theme_user_filters($form) {
-  $output = '<ul class="clear-block">';
-  if (!empty($form['current'])) {
-    foreach (element_children($form['current']) as $key) {
-      $output .= '<li>'. drupal_render($form['current'][$key]) .'</li>';
-    }
-  }
-
-  $output .= '<li><dl class="multiselect">'. (!empty($form['current']) ? '<dt><em>'. t('and') .'</em> '. t('where') .'</dt>' : '') .'<dd class="a">';
-  foreach (element_children($form['filter']) as $key) {
-    $output .= drupal_render($form['filter'][$key]);
-  }
-  $output .= '</dd>';
-
-  $output .= '<dt>'. t('is') .'</dt><dd class="b">';
-
-  foreach (element_children($form['status']) as $key) {
-    $output .= drupal_render($form['status'][$key]);
-  }
-  $output .= '</dd>';
-
-  $output .= '</dl>';
-  $output .= '<div class="container-inline" id="user-admin-buttons">'. drupal_render($form['buttons']) .'</div>';
-  $output .= '</li></ul>';
-
-  return $output;
-}
-
-/**
- * Process result from user administration filter form.
- */
-function user_filter_form_submit($form_id, $form_values) {
-  $op = $form_values['op'];
-  $filters = user_filters();
-  switch ($op) {
-    case t('Filter'): case t('Refine'):
-      if (isset($form_values['filter'])) {
-        $filter = $form_values['filter'];
-        // Merge an array of arrays into one if necessary.
-        $options = $filter == 'permission' ? call_user_func_array('array_merge', $filters[$filter]['options']) : $filters[$filter]['options'];
-        if (isset($options[$form_values[$filter]])) {
-          $_SESSION['user_overview_filter'][] = array($filter, $form_values[$filter]);
-        }
-      }
-      break;
-    case t('Undo'):
-      array_pop($_SESSION['user_overview_filter']);
-      break;
-    case t('Reset'):
-      $_SESSION['user_overview_filter'] = array();
-      break;
-    case t('Update'):
-      return;
-  }
-
-  return 'admin/user/user';
-}
-
-
-function user_forms() {
-  $forms['user_admin_access_add_form']['callback'] = 'user_admin_access_form';
-  $forms['user_admin_access_edit_form']['callback'] = 'user_admin_access_form';
-  $forms['user_admin_new_role']['callback'] = 'user_admin_role';
-  return $forms;
-}
-
-/**
- * Implementation of hook_comments().
- */
-function user_comment($comment, $op) {
-  // Validate signature.
-  if ($op == 'view') {
-    if (variable_get('user_signatures', 0) && !empty($comment->signature)) {
-      $comment->signature = check_markup($comment->signature, $comment->format);
-    }
-    else {
-      $comment->signature = '';
-    }
-  }
-}
-
-/**
- * Theme output of user signature.
- *
- * @ingroup themeable
- */
-function theme_user_signature($signature) {
-  $output = '';
-  if ($signature) {
-    $output .= '<div class="clear">';
-    $output .= '<div>'. '—' .'</div>';
-    $output .= $signature;
-    $output .= '</div>';
-  }
-
-  return $output;
-}
-
Index: modules/user/user.pages.inc
===================================================================
RCS file: modules/user/user.pages.inc
diff -N modules/user/user.pages.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/user/user.pages.inc	30 Apr 2007 07:06:45 -0000
@@ -0,0 +1,2014 @@
+<?php
+// $Id: $
+
+/**
+ * @file
+ * Enables the user registration and login system.
+ */
+
+
+/**
+ * Verify the syntax of the given name.
+ */
+function user_validate_name($name) {
+  if (!strlen($name)) return t('You must enter a username.');
+  if (substr($name, 0, 1) == ' ') return t('The username cannot begin with a space.');
+  if (substr($name, -1) == ' ') return t('The username cannot end with a space.');
+  if (strpos($name, '  ') !== FALSE) return t('The username cannot contain multiple spaces in a row.');
+  if (ereg("[^\x80-\xF7 [:alnum:]@_.-]", $name)) return t('The username contains an illegal character.');
+  if (preg_match('/[\x{80}-\x{A0}'.          // Non-printable ISO-8859-1 + NBSP
+                   '\x{AD}'.                 // Soft-hyphen
+                   '\x{2000}-\x{200F}'.      // Various space characters
+                   '\x{2028}-\x{202F}'.      // Bidirectional text overrides
+                   '\x{205F}-\x{206F}'.      // Various text hinting characters
+                   '\x{FEFF}'.               // Byte order mark
+                   '\x{FF01}-\x{FF60}'.      // Full-width latin
+                   '\x{FFF9}-\x{FFFD}'.      // Replacement characters
+                   '\x{0}]/u',               // NULL byte
+                   $name)) {
+    return t('The username contains an illegal character.');
+  }
+  if (strpos($name, '@') !== FALSE && !eregi('@([0-9a-z](-?[0-9a-z])*.)+[a-z]{2}([zmuvtg]|fo|me)?$', $name)) return t('The username is not a valid authentication ID.');
+  if (strlen($name) > USERNAME_MAX_LENGTH) return t('The username %name is too long: it must be %max characters or less.', array('%name' => $name, '%max' => USERNAME_MAX_LENGTH));
+}
+
+function user_validate_mail($mail) {
+  if (!$mail) return t('You must enter an e-mail address.');
+  if (!valid_email_address($mail)) {
+    return t('The e-mail address %mail is not valid.', array('%mail' => $mail));
+  }
+}
+
+function user_validate_picture($file, &$edit, $user) {
+  global $form_values;
+  // Initialize the picture:
+  $form_values['picture'] = $user->picture;
+
+  // Check that uploaded file is an image, with a maximum file size
+  // and maximum height/width.
+  $info = image_get_info($file->filepath);
+  list($maxwidth, $maxheight) = explode('x', variable_get('user_picture_dimensions', '85x85'));
+
+  if (!$info || !$info['extension']) {
+    form_set_error('picture_upload', t('The uploaded file was not an image.'));
+  }
+  else if (image_get_toolkit()) {
+    image_scale($file->filepath, $file->filepath, $maxwidth, $maxheight);
+  }
+  else if (filesize($file->filepath) > (variable_get('user_picture_file_size', '30') * 1000)) {
+    form_set_error('picture_upload', t('The uploaded image is too large; the maximum file size is %size kB.', array('%size' => variable_get('user_picture_file_size', '30'))));
+  }
+  else if ($info['width'] > $maxwidth || $info['height'] > $maxheight) {
+    form_set_error('picture_upload', t('The uploaded image is too large; the maximum dimensions are %dimensions pixels.', array('%dimensions' => variable_get('user_picture_dimensions', '85x85'))));
+  }
+
+  if (!form_get_errors()) {
+    if ($file = file_save_upload('picture_upload', variable_get('user_picture_path', 'pictures') .'/picture-'. $user->uid .'.'. $info['extension'], 1)) {
+      $form_values['picture'] = $file->filepath;
+    }
+    else {
+      form_set_error('picture_upload', t("Failed to upload the picture image; the %directory directory doesn't exist or is not writable.", array('%directory' => variable_get('user_picture_path', 'pictures'))));
+    }
+  }
+}
+
+function user_fields() {
+  static $fields;
+
+  if (!$fields) {
+    $result = db_query('SELECT * FROM {users} WHERE uid = 1');
+    if (db_num_rows($result)) {
+      $fields = array_keys(db_fetch_array($result));
+    }
+    else {
+      // Make sure we return the default fields at least
+      $fields = array('uid', 'name', 'pass', 'mail', 'picture', 'mode', 'sort', 'threshold', 'theme', 'signature', 'created', 'access', 'login', 'status', 'timezone', 'language', 'init', 'data');
+    }
+  }
+
+  return $fields;
+}
+
+function theme_user_picture($account) {
+  if (variable_get('user_pictures', 0)) {
+    if ($account->picture && file_exists($account->picture)) {
+      $picture = file_create_url($account->picture);
+    }
+    else if (variable_get('user_picture_default', '')) {
+      $picture = variable_get('user_picture_default', '');
+    }
+
+    if (isset($picture)) {
+      $alt = t("@user's picture", array('@user' => $account->name ? $account->name : variable_get('anonymous', t('Anonymous'))));
+      $picture = theme('image', $picture, $alt, $alt, '', FALSE);
+      if (!empty($account->uid) && user_access('access user profiles')) {
+        $picture = l($picture, "user/$account->uid", array('attributes' => array('title' => t('View user profile.')), 'html' => TRUE));
+      }
+
+      return "<div class=\"picture\">$picture</div>";
+    }
+  }
+}
+
+/**
+ * Theme a user page
+ * @param $account the user object
+ * @param $fields a multidimensional array for the fields, in the form of array (
+ *   'category1' => array(item_array1, item_array2), 'category2' => array(item_array3,
+ *    .. etc.). Item arrays are formatted as array(array('title' => 'item title',
+ * 'value' => 'item value', 'class' => 'class-name'), ... etc.). Module names are incorporated
+ * into the CSS class.
+ *
+ * @ingroup themeable
+ */
+function theme_user_profile($account, $fields) {
+  $output = '<div class="profile">';
+  $output .= theme('user_picture', $account);
+  foreach ($fields as $category => $items) {
+    if (strlen($category) > 0) {
+      $output .= '<h2 class="title">'. $category .'</h2>';
+    }
+    $output .= '<dl>';
+    foreach ($items as $item) {
+      if (isset($item['title'])) {
+        $output .= '<dt class="'. $item['class'] .'">'. $item['title'] .'</dt>';
+      }
+      $output .= '<dd class="'. $item['class'] .'">'. $item['value'] .'</dd>';
+    }
+    $output .= '</dl>';
+  }
+  $output .= '</div>';
+
+  return $output;
+}
+
+/**
+ * Make a list of users.
+ * @param $items an array with user objects. Should contain at least the name and uid
+ *
+ * @ingroup themeable
+ */
+function theme_user_list($users, $title = NULL) {
+  if (!empty($users)) {
+    foreach ($users as $user) {
+      $items[] = theme('username', $user);
+    }
+  }
+  return theme('item_list', $items, $title);
+}
+
+
+/**
+ * Accepts an user object, $account, or a DA name and returns an associative
+ * array of modules and DA names. Called at external login.
+ */
+function user_get_authmaps($authname = NULL) {
+  $result = db_query("SELECT authname, module FROM {authmap} WHERE authname = '%s'", $authname);
+  if (db_num_rows($result) > 0) {
+    while ($authmap = db_fetch_object($result)) {
+      $authmaps[$authmap->module] = $authmap->authname;
+    }
+    return $authmaps;
+  }
+  else {
+    return 0;
+  }
+}
+
+function user_set_authmaps($account, $authmaps) {
+  foreach ($authmaps as $key => $value) {
+    $module = explode('_', $key, 2);
+    if ($value) {
+      db_query("UPDATE {authmap} SET authname = '%s' WHERE uid = %d AND module = '%s'", $value, $account->uid, $module[1]);
+      if (!db_affected_rows()) {
+        db_query("INSERT INTO {authmap} (authname, uid, module) VALUES ('%s', %d, '%s')", $value, $account->uid, $module[1]);
+      }
+    }
+    else {
+      db_query("DELETE FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module[1]);
+    }
+  }
+}
+
+function user_auth_help_links() {
+  $links = array();
+  foreach (module_list() as $module) {
+    if (module_hook($module, 'auth')) {
+      $links[] = l(module_invoke($module, 'info', 'name'), 'user/help', array('fragment' => $module));
+    }
+  }
+  return $links;
+}
+
+/*** User features *********************************************************/
+
+
+
+function user_login($msg = '') {
+  global $user;
+
+  // If we are already logged on, go to the user page instead.
+  if ($user->uid) {
+    drupal_goto('user/'. $user->uid);
+  }
+
+  // Display login form:
+  if ($msg) {
+    $form['message'] = array('#value' => '<p>'. check_plain($msg) .'</p>');
+  }
+  $form['name'] = array('#type' => 'textfield',
+    '#title' => t('Username'),
+    '#size' => 60,
+    '#maxlength' => USERNAME_MAX_LENGTH,
+    '#required' => TRUE,
+    '#attributes' => array('tabindex' => '1'),
+  );
+  if (variable_get('drupal_authentication_service', FALSE) && count(user_auth_help_links()) > 0) {
+    $form['name']['#description'] = t('Enter your @s username, or an ID from one of our affiliates: !a.', array('@s' => variable_get('site_name', 'Drupal'), '!a' => implode(', ', user_auth_help_links())));
+  }
+  else {
+    $form['name']['#description'] = t('Enter your @s username.', array('@s' => variable_get('site_name', 'Drupal')));
+  }
+  $form['pass'] = array('#type' => 'password',
+    '#title' => t('Password'),
+    '#description' => t('Enter the password that accompanies your username.'),
+    '#required' => TRUE,
+    '#attributes' => array('tabindex' => '2'),
+  );
+  $form['submit'] = array('#type' => 'submit', '#value' => t('Log in'), '#weight' => 2, '#attributes' => array('tabindex' => '3'));
+
+  return $form;
+}
+
+function user_login_validate($form_id, $form_values) {
+  if ($form_values['name']) {
+    if (user_is_blocked($form_values['name'])) {
+      // blocked in user administration
+      form_set_error('name', t('The username %name has not been activated or is blocked.', array('%name' => $form_values['name'])));
+    }
+    else if (drupal_is_denied('user', $form_values['name'])) {
+      // denied by access controls
+      form_set_error('name', t('The name %name is a reserved username.', array('%name' => $form_values['name'])));
+    }
+    else if ($form_values['pass']) {
+      $user = user_authenticate($form_values['name'], trim($form_values['pass']));
+
+      if (!$user->uid) {
+        form_set_error('name', t('Sorry, unrecognized username or password. <a href="@password">Have you forgotten your password?</a>', array('@password' => url('user/password'))));
+        watchdog('user', 'Login attempt failed for %user.', array('%user' => $form_values['name']));
+      }
+    }
+  }
+}
+
+function user_login_submit($form_id, $form_values) {
+  global $user;
+  if ($user->uid) {
+    watchdog('user', 'Session opened for %name.', array('%name' => $user->name));
+
+    // Update the user table timestamp noting user has logged in.
+    db_query("UPDATE {users} SET login = %d WHERE uid = %d", time(), $user->uid);
+
+    user_module_invoke('login', $form_values, $user);
+
+    sess_regenerate();
+    return 'user/'. $user->uid;
+  }
+}
+
+function user_authenticate($name, $pass) {
+  global $user;
+
+  // Try to log in the user locally. Don't set $user unless successful.
+  if ($account = user_load(array('name' => $name, 'pass' => $pass, 'status' => 1))) {
+    $user = $account;
+    return $user;
+  }
+
+  // Strip name and server from ID:
+  if ($server = strrchr($name, '@')) {
+    $name = substr($name, 0, strlen($name) - strlen($server));
+    $server = substr($server, 1);
+  }
+
+  // When possible, determine corresponding external auth source. Invoke
+  // source, and log in user if successful:
+  if ($server && ($result = user_get_authmaps("$name@$server"))) {
+    if (module_invoke(key($result), 'auth', $name, $pass, $server)) {
+      $user = user_external_load("$name@$server");
+      watchdog('user', 'External load by %user using module %module.', array('%user' => $name .'@'. $server, '%module' => key($result)));
+    }
+  }
+
+  // Try each external authentication source in series. Register user if
+  // successful.
+  else {
+    foreach (module_implements('auth') as $module) {
+      if (module_invoke($module, 'auth', $name, $pass, $server)) {
+        if ($server) {
+          $name .= '@'. $server;
+        }
+        $user = user_load(array('name' => $name));
+        if (!$user->uid) { // Register this new user.
+          $userinfo = array('name' => $name, 'pass' => user_password(), 'init' => $name, 'status' => 1);
+          if ($server) {
+            $userinfo["authname_$module"] = $name;
+          }
+          $user = user_save('', $userinfo);
+          watchdog('user', 'New external user: %user using module %module.', array('%user' => $name, '%module' => $module), WATCHDOG_NOTICE, l(t('edit'), 'user/'. $user->uid .'/edit'));
+          break;
+        }
+      }
+    }
+  }
+  return $user;
+}
+
+/**
+ * Menu callback; logs the current user out, and redirects to the home page.
+ */
+function user_logout() {
+  global $user;
+
+  watchdog('user', 'Session closed for %name.', array('%name' => $user->name));
+
+  // Destroy the current session:
+  session_destroy();
+  module_invoke_all('user', 'logout', NULL, $user);
+
+  // Load the anonymous user
+  $user = drupal_anonymous_user();
+
+  drupal_goto();
+}
+
+function user_pass() {
+  $form['name'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Username or e-mail address'),
+    '#size' => 60,
+    '#maxlength' => max(USERNAME_MAX_LENGTH, EMAIL_MAX_LENGTH),
+    '#required' => TRUE,
+  );
+  $form['submit'] = array('#type' => 'submit', '#value' => t('E-mail new password'));
+
+  return $form;
+}
+
+function user_pass_validate($form_id, $form_values) {
+  $name = trim($form_values['name']);
+  if (valid_email_address($name)) {
+    $account = user_load(array('mail' => $name, 'status' => 1));
+  }
+  else {
+    $account = user_load(array('name' => $name, 'status' => 1));
+  }
+  if (isset($account->uid)) {
+    form_set_value(array('#parents' => array('account')), $account);
+  }
+  else {
+    form_set_error('name', t('Sorry, %name is not recognized as a user name or an e-mail address.', array('%name' => $name)));
+  }
+}
+
+function user_pass_submit($form_id, $form_values) {
+  global $base_url;
+
+  $account = $form_values['account'];
+  $from = variable_get('site_mail', ini_get('sendmail_from'));
+
+  // Mail one time login URL and instructions.
+  $variables = array('!username' => $account->name, '!site' => variable_get('site_name', 'Drupal'), '!login_url' => user_pass_reset_url($account), '!uri' => $base_url, '!uri_brief' => substr($base_url, strlen('http://')), '!mailto' => $account->mail, '!date' => format_date(time()), '!login_uri' => url('user', array('absolute' => TRUE)), '!edit_uri' => url('user/'. $account->uid .'/edit', array('absolute' => TRUE)));
+  $subject = _user_mail_text('pass_subject', $variables);
+  $body = _user_mail_text('pass_body', $variables);
+  $mail_success = drupal_mail('user-pass', $account->mail, $subject, $body, $from);
+
+  if ($mail_success) {
+    watchdog('user', 'Password reset instructions mailed to %name at %email.', array('%name' => $account->name, '%email' => $account->mail));
+    drupal_set_message(t('Further instructions have been sent to your e-mail address.'));
+  }
+  else {
+    watchdog('user', 'Error mailing password reset instructions to %name at %email.', array('%name' => $account->name, '%email' => $account->mail), WATCHDOG_ERROR);
+    drupal_set_message(t('Unable to send mail. Please contact the site admin.'));
+  }
+  return 'user';
+}
+
+/**
+ * Menu callback; process one time login link and redirects to the user page on success.
+ */
+function user_pass_reset($uid, $timestamp, $hashed_pass, $action = NULL) {
+  global $user;
+
+  // Check if the user is already logged in. The back button is often the culprit here.
+  if ($user->uid) {
+    drupal_set_message(t('You have already used this one-time login link. It is not necessary to use this link to login anymore. You are already logged in.'));
+    drupal_goto();
+  }
+  else {
+    // Time out, in seconds, until login URL expires. 24 hours = 86400 seconds.
+    $timeout = 86400;
+    $current = time();
+    // Some redundant checks for extra security ?
+    if ($timestamp < $current && $account = user_load(array('uid' => $uid, 'status' => 1)) ) {
+      // 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.'));
+        drupal_goto('user/password');
+      }
+      else if ($account->uid && $timestamp > $account->login && $timestamp < $current && $hashed_pass == user_pass_rehash($account->pass, $timestamp, $account->login)) {
+        // First stage is a confirmation form, then login
+        if ($action == 'login') {
+          watchdog('user', 'User %name used one-time login link at time %timestamp.', array('%name' => $account->name, '%timestamp' => $timestamp));
+          // Update the user table noting user has logged in.
+          // And this also makes this hashed password a one-time-only login.
+          db_query("UPDATE {users} SET login = %d WHERE uid = %d", time(), $account->uid);
+          // Now we can set the new user.
+          $user = $account;
+          // And proceed with normal login, going to user page.
+          $edit = array();
+          user_module_invoke('login', $edit, $user);
+          drupal_set_message(t('You have just used your one-time login link. It is no longer necessary to use this link to login. Please change your password.'));
+          drupal_goto('user/'. $user->uid .'/edit');
+        }
+        else {
+          $form['message'] = array('#value' => t('<p>This is a one-time login for %user_name and will expire on %expiration_date</p><p>Click on this button to login to the site and change your password.</p>', array('%user_name' => $account->name, '%expiration_date' => format_date($timestamp + $timeout))));
+          $form['help'] = array('#value' => '<p>'. t('This login can be used only once.') .'</p>');
+          $form['submit'] = array('#type' => 'submit', '#value' => t('Log in'));
+          $form['#action'] = url("user/reset/$uid/$timestamp/$hashed_pass/login");
+          return $form;
+        }
+      }
+      else {
+        drupal_set_message(t('You have tried to use a one-time login link which has either been used or is no longer valid. Please request a new one using the form below.'));
+        drupal_goto('user/password');
+      }
+    }
+    else {
+      // Deny access, no more clues.
+      // Everything will be in the watchdog's URL for the administrator to check.
+      drupal_access_denied();
+    }
+  }
+}
+
+function user_pass_reset_url($account) {
+  $timestamp = time();
+  return url("user/reset/$account->uid/$timestamp/". user_pass_rehash($account->pass, $timestamp, $account->login), array('absolute' => TRUE));
+}
+
+function user_pass_rehash($password, $timestamp, $login) {
+  return md5($timestamp . $password . $login);
+}
+
+function user_register() {
+  global $user;
+
+  $admin = user_access('administer users');
+
+  // If we aren't admin but already logged on, go to the user page instead.
+  if (!$admin && $user->uid) {
+    drupal_goto('user/'. $user->uid);
+  }
+
+  $form = array();
+
+  // Display the registration form.
+  if (!$admin) {
+    $form['user_registration_help'] = array('#value' => filter_xss_admin(variable_get('user_registration_help', '')));
+  }
+  $affiliates = user_auth_help_links();
+  if (!$admin && count($affiliates) > 0) {
+    $affiliates = implode(', ', $affiliates);
+    $form['affiliates'] = array('#value' => '<p>'. t('Note: if you have an account with one of our affiliates (!s), you may <a href="@login_uri">login now</a> instead of registering.', array('!s' => $affiliates, '@login_uri' => url('user'))) .'</p>');
+  }
+  // Merge in the default user edit fields.
+  $form = array_merge($form, user_edit_form(NULL, NULL, TRUE));
+  if ($admin) {
+    $form['account']['notify'] = array(
+     '#type' => 'checkbox',
+     '#title' => t('Notify user of new account')
+    );
+    // Redirect back to page which initiated the create request; usually admin/user/user/create
+    $form['destination'] = array('#type' => 'hidden', '#value' => $_GET['q']);
+  }
+
+  // Create a dummy variable for pass-by-reference parameters.
+  $null = NULL;
+  $extra = _user_forms($null, NULL, NULL, 'register');
+
+  // Remove form_group around default fields if there are no other groups.
+  if (!$extra) {
+    foreach (array('name', 'mail', 'pass', 'status', 'roles', 'notify') as $key) {
+      if (isset($form['account'][$key])) {
+        $form[$key] = $form['account'][$key];
+      }
+    }
+    unset($form['account']);
+  }
+  else {
+    $form = array_merge($form, $extra);
+  }
+  $form['submit'] = array('#type' => 'submit', '#value' => t('Create new account'), '#weight' => 30);
+
+  return $form;
+}
+
+function user_register_validate($form_id, $form_values) {
+  user_module_invoke('validate', $form_values, $form_values, 'account');
+}
+
+function user_register_submit($form_id, $form_values) {
+  global $base_url;
+  $admin = user_access('administer users');
+
+  $mail = $form_values['mail'];
+  $name = $form_values['name'];
+  if (!variable_get('user_email_verification', TRUE) || $admin) {
+    $pass = $form_values['pass'];
+  }
+  else {
+    $pass = user_password();
+  };
+  $notify = isset($form_values['notify']) ? $form_values['notify'] : NULL;
+  $from = variable_get('site_mail', ini_get('sendmail_from'));
+  if (isset($form_values['roles'])) {
+    $roles = array_filter($form_values['roles']);     // Remove unset roles
+  }
+  else {
+    $roles = array();
+  }
+
+  if (!$admin && array_intersect(array_keys($form_values), array('uid', 'roles', 'init', 'session', 'status'))) {
+    watchdog('security', 'Detected malicious attempt to alter protected user fields.', array(), WATCHDOG_WARNING);
+    return 'user/register';
+  }
+  //the unset below is needed to prevent these form values from being saved as user data
+  unset($form_values['form_token'], $form_values['submit'], $form_values['op'], $form_values['notify'], $form_values['form_id'], $form_values['affiliates'], $form_values['destination']);
+
+  $merge_data = array('pass' => $pass, 'init' => $mail, 'roles' => $roles);
+  if (!$admin) {
+    // Set the user's status because it was not displayed in the form.
+    $merge_data['status'] = variable_get('user_register', 1) == 1;
+  }
+  $account = user_save('', array_merge($form_values, $merge_data));
+  watchdog('user', 'New user: %name %email.', array('%name' => $name, '%email' => '<'. $mail .'>'), WATCHDOG_NOTICE, l(t('edit'), 'user/'. $account->uid .'/edit'));
+
+  $variables = array('!username' => $name, '!site' => variable_get('site_name', 'Drupal'), '!password' => $pass, '!uri' => $base_url, '!uri_brief' => substr($base_url, strlen('http://')), '!mailto' => $mail, '!date' => format_date(time()), '!login_uri' => url('user', array('absolute' => TRUE)), '!edit_uri' => url('user/'. $account->uid .'/edit', array('absolute' => TRUE)), '!login_url' => user_pass_reset_url($account));
+
+  // The first user may login immediately, and receives a customized welcome e-mail.
+  if ($account->uid == 1) {
+    drupal_mail('user-register-admin', $mail, t('Drupal user account details for !s', array('!s' => $name)), strtr(t("!username,\n\nYou may now login to !uri using the following username and password:\n\n  username: !username\n  password: !password\n\n!edit_uri\n\n--drupal"), $variables), $from);
+    drupal_set_message(t('<p>Welcome to Drupal. You are user #1, which gives you full and immediate access. All future registrants will receive their passwords via e-mail, so please make sure your website e-mail address is set properly under the general settings on the <a href="@settings">site information settings page</a>.</p><p> Your password is <strong>%pass</strong>. You may change your password below.</p>', array('%pass' => $pass, '@settings' => url('admin/settings/site-information'))));
+    user_authenticate($account->name, trim($pass));
+
+    return 'user/1/edit';
+  }
+  else {
+    if ($admin && !$notify) {
+      drupal_set_message(t('Created a new user account. No e-mail has been sent.'));
+    }
+    else if (!variable_get('user_email_verification', TRUE) && $account->status && !$admin) {
+      // No e-mail verification is required, create new user account, and login user immediately.
+      $subject = _user_mail_text('welcome_subject', $variables);
+      $body = _user_mail_text('welcome_body', $variables);
+      drupal_mail('user-register-welcome', $mail, $subject, $body, $from);
+      user_authenticate($account->name, trim($pass));
+      return '';
+    }
+    else if ($account->status || $notify) {
+      // Create new user account, no administrator approval required.
+      $subject = $notify ? _user_mail_text('admin_subject', $variables) : _user_mail_text('welcome_subject', $variables);
+      $body = $notify ? _user_mail_text('admin_body', $variables) : _user_mail_text('welcome_body', $variables);
+
+      drupal_mail(($notify ? 'user-register-notify' : 'user-register-welcome'), $mail, $subject, $body, $from);
+
+      if ($notify) {
+        drupal_set_message(t('Password and further instructions have been e-mailed to the new user %user.', array('%user' => $name)));
+      }
+      else {
+        drupal_set_message(t('Your password and further instructions have been sent to your e-mail address.'));
+        return '';
+      }
+    }
+    else {
+      // Create new user account, administrator approval required.
+      $subject = _user_mail_text('approval_subject', $variables);
+      $body = _user_mail_text('approval_body', $variables);
+
+      drupal_mail('user-register-approval-user', $mail, $subject, $body, $from);
+      drupal_mail('user-register-approval-admin', $from, $subject, t("!username has applied for an account.\n\n!edit_uri", $variables), $from);
+      drupal_set_message(t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.<br />In the meantime, your password and further instructions have been sent to your e-mail address.'));
+
+    }
+  }
+}
+
+function user_edit_form($uid, $edit, $register = FALSE) {
+  $admin = user_access('administer users');
+
+  // Account information:
+  $form['account'] = array('#type' => 'fieldset',
+    '#title' => t('Account information'),
+  );
+  if (user_access('change own username') || $admin || $register) {
+    $form['account']['name'] = array('#type' => 'textfield',
+      '#title' => t('Username'),
+      '#default_value' => $edit['name'],
+      '#maxlength' => USERNAME_MAX_LENGTH,
+      '#description' => t('Your preferred username; punctuation is not allowed except for periods, hyphens, and underscores.'),
+      '#required' => TRUE,
+    );
+  }
+  $form['account']['mail'] = array('#type' => 'textfield',
+    '#title' => t('E-mail address'),
+    '#default_value' => $edit['mail'],
+    '#maxlength' => EMAIL_MAX_LENGTH,
+    '#description' => t('A valid e-mail address. All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'),
+    '#required' => TRUE,
+  );
+  if (!$register) {
+    $form['account']['pass'] = array('#type' => 'password_confirm',
+      '#description' => t('To change the current user password, enter the new password in both fields.'),
+      '#size' => 25,
+    );
+  }
+  elseif (!variable_get('user_email_verification', TRUE) || $admin) {
+    $form['account']['pass'] = array(
+      '#type' => 'password_confirm',
+      '#description' => t('Provide a password for the new account in both fields.'),
+      '#required' => TRUE,
+      '#size' => 25,
+    );
+  }
+  if ($admin) {
+    $form['account']['status'] = array('#type' => 'radios', '#title' => t('Status'), '#default_value' => isset($edit['status']) ? $edit['status'] : 1, '#options' => array(t('Blocked'), t('Active')));
+  }
+  if (user_access('administer access control')) {
+    $roles = user_roles(1);
+    unset($roles[DRUPAL_AUTHENTICATED_RID]);
+    if ($roles) {
+      $default = empty($edit['roles']) ? array() : array_keys($edit['roles']);
+      $form['account']['roles'] = array('#type' => 'checkboxes', '#title' => t('Roles'), '#default_value' => $default, '#options' => $roles, '#description' => t('The user receives the combined permissions of the %au role, and all roles selected here.', array('%au' => t('authenticated user'))));
+    }
+  }
+
+  // Signature:
+  if (variable_get('user_signatures', 0) && module_exists('comment') && !$register) {
+    $form['signature_settings'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Signature settings'),
+      '#weight' => 1,
+    );
+    $form['signature_settings']['signature'] = array(
+      '#type' => 'textarea',
+      '#title' => t('Signature'),
+      '#default_value' => $edit['signature'],
+      '#description' => t('Your signature will be publicly displayed at the end of your comments.'),
+    );
+  }
+
+  // Picture/avatar:
+  if (variable_get('user_pictures', 0) && !$register) {
+    $form['picture'] = array('#type' => 'fieldset', '#title' => t('Picture'), '#weight' => 1);
+    $picture = theme('user_picture', (object)$edit);
+    if ($picture) {
+      $form['picture']['current_picture'] = array('#value' => $picture);
+      $form['picture']['picture_delete'] = array('#type' => 'checkbox', '#title' => t('Delete picture'), '#description' => t('Check this box to delete your current picture.'));
+    }
+    else {
+      $form['picture']['picture_delete'] = array('#type' => 'hidden');
+    }
+    $form['picture']['picture_upload'] = array('#type' => 'file', '#title' => t('Upload picture'), '#size' => 48, '#description' => t('Your virtual face or picture. Maximum dimensions are %dimensions and the maximum size is %size kB.', array('%dimensions' => variable_get('user_picture_dimensions', '85x85'), '%size' => variable_get('user_picture_file_size', '30'))) .' '. variable_get('user_picture_guidelines', ''));
+  }
+
+  return $form;
+}
+
+function _user_edit_validate($uid, &$edit) {
+  $user = user_load(array('uid' => $uid));
+  // Validate the username:
+  if (user_access('change own username') || user_access('administer users') || arg(1) == 'register') {
+    if ($error = user_validate_name($edit['name'])) {
+      form_set_error('name', $error);
+    }
+    else if (db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != %d AND LOWER(name) = LOWER('%s')", $uid, $edit['name'])) > 0) {
+      form_set_error('name', t('The name %name is already taken.', array('%name' => $edit['name'])));
+    }
+    else if (drupal_is_denied('user', $edit['name'])) {
+      form_set_error('name', t('The name %name has been denied access.', array('%name' => $edit['name'])));
+    }
+  }
+
+  // Validate the e-mail address:
+  if ($error = user_validate_mail($edit['mail'])) {
+    form_set_error('mail', $error);
+  }
+  else if (db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != %d AND LOWER(mail) = LOWER('%s')", $uid, $edit['mail'])) > 0) {
+    form_set_error('mail', t('The e-mail address %email is already registered. <a href="@password">Have you forgotten your password?</a>', array('%email' => $edit['mail'], '@password' => url('user/password'))));
+  }
+  else if (drupal_is_denied('mail', $edit['mail'])) {
+    form_set_error('mail', t('The e-mail address %email has been denied access.', array('%email' => $edit['mail'])));
+  }
+
+  // If required, validate the uploaded picture.
+  if ($file = file_check_upload('picture_upload')) {
+    user_validate_picture($file, $edit, $user);
+  }
+}
+
+function _user_edit_submit($uid, &$edit) {
+  $user = user_load(array('uid' => $uid));
+  // Delete picture if requested, and if no replacement picture was given.
+  if (!empty($edit['picture_delete'])) {
+    if ($user->picture && file_exists($user->picture)) {
+      file_delete($user->picture);
+    }
+    $edit['picture'] = '';
+  }
+  if (isset($edit['roles'])) {
+    $edit['roles'] = array_filter($edit['roles']);
+  }
+}
+
+function user_edit($category = 'account') {
+  global $user;
+
+  $account = user_load(array('uid' => arg(1)));
+  if ($account === FALSE) {
+    drupal_set_message(t('The account does not exist or has already been deleted.'));
+    drupal_goto('admin/user/user');
+  }
+  $op = !empty($_POST['op']) ? $_POST['op'] : '';
+  $edit = $op ? $_POST : (array)$account;
+
+  if (arg(2) == 'delete') {
+    if ($edit['confirm']) {
+      user_delete($edit, $account->uid);
+      drupal_goto('admin/user/user');
+    }
+    else {
+      return drupal_get_form('user_confirm_delete', $account->name, $account->uid);
+    }
+  }
+  else if ($op == t('Delete')) {
+    if ($_REQUEST['destination']) {
+      $destination = drupal_get_destination();
+      unset($_REQUEST['destination']);
+    }
+    // Note: we redirect from user/uid/edit to user/uid/delete to make the tabs disappear.
+    drupal_goto("user/$account->uid/delete", $destination);
+  }
+
+  $form = _user_forms($edit, $account, $category);
+  $form['_category'] = array('#type' => 'value', '#value' => $category);
+  $form['_account'] = array('#type' => 'value', '#value' => $account);
+  $form['submit'] = array('#type' => 'submit', '#value' => t('Submit'), '#weight' => 30);
+  if (user_access('administer users')) {
+    $form['delete'] = array('#type' => 'submit', '#value' => t('Delete'), '#weight' => 31);
+  }
+  $form['#attributes']['enctype'] = 'multipart/form-data';
+
+  drupal_set_title(check_plain($account->name));
+  return $form;
+}
+
+function user_confirm_delete($name, $uid) {
+  return confirm_form(array(),
+    t('Are you sure you want to delete the account %name?', array('%name' => $name)),
+    'user/'. $uid,
+    t('All submissions made by this user will be attributed to the anonymous account. This action cannot be undone.'),
+    t('Delete'), t('Cancel'));
+}
+
+/**
+ * Delete a user.
+ *
+ * @param $edit An array of submitted form values.
+ * @param $uid The user ID of the user to delete.
+ */
+function user_delete($edit, $uid) {
+  $account = user_load(array('uid' => $uid));
+  sess_destroy_uid($uid);
+  db_query('DELETE FROM {users} WHERE uid = %d', $uid);
+  db_query('DELETE FROM {users_roles} WHERE uid = %d', $uid);
+  db_query('DELETE FROM {authmap} WHERE uid = %d', $uid);
+  $variables = array('%name' => $account->name, '%email' => '<'. $account->mail .'>');
+  watchdog('user', 'Deleted user: %name %email.', $variables, WATCHDOG_NOTICE);
+  drupal_set_message(t('%name has been deleted.', $variables));
+  module_invoke_all('user', 'delete', $edit, $account);
+}
+
+function user_edit_validate($form_id, $form_values) {
+  user_module_invoke('validate', $form_values, $form_values['_account'], $form_values['_category']);
+  // Validate input to ensure that non-privileged users can't alter protected data.
+  if ((!user_access('administer users') && array_intersect(array_keys($form_values), array('uid', 'init', 'session'))) || (!user_access('administer access control') && isset($form_values['roles']))) {
+    watchdog('security', 'Detected malicious attempt to alter protected user fields.', array(), WATCHDOG_WARNING);
+    // set this to a value type field
+    form_set_error('category', t('Detected malicious attempt to alter protected user fields.'));
+  }
+}
+
+function user_edit_submit($form_id, $form_values) {
+  $account = $form_values['_account'];
+  $category = $form_values['_category'];
+  unset($form_values['_account'], $form_values['op'], $form_values['submit'], $form_values['delete'], $form_values['form_token'], $form_values['form_id'], $form_values['_category']);
+  user_module_invoke('submit', $form_values, $account, $category);
+  user_save($account, $form_values, $category);
+
+  // Clear the page cache because pages can contain usernames and/or profile information:
+  cache_clear_all();
+
+  drupal_set_message(t('The changes have been saved.'));
+  return 'user/'. $account->uid;
+}
+
+function user_view($account) {
+  global $user;
+
+  drupal_set_title(check_plain($account->name));
+  // Retrieve and merge all profile fields:
+  $fields = array();
+  foreach (module_list() as $module) {
+    if ($data = module_invoke($module, 'user', 'view', '', $account)) {
+      foreach ($data as $category => $items) {
+        foreach ($items as $key => $item) {
+          $item['class'] = "$module-". $item['class'];
+          $fields[$category][$key] = $item;
+        }
+      }
+    }
+  }
+
+  drupal_alter('profile', $fields, $account);
+
+  drupal_set_title(check_plain($account->name));
+  return theme('user_profile', $account, $fields);
+}
+
+/*** Administrative features ***********************************************/
+
+function _user_mail_text($messageid, $variables = array()) {
+
+  // Check if an admin setting overrides the default string.
+  if ($admin_setting = variable_get('user_mail_'. $messageid, FALSE)) {
+    return strtr($admin_setting, $variables);
+  }
+  // No override, return with default strings.
+  else {
+    switch ($messageid) {
+      case 'welcome_subject':
+        return t('Account details for !username at !site', $variables);
+      case 'welcome_body':
+        return t("!username,\n\nThank you for registering at !site. 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);
+      case 'admin_subject':
+        return t('An administrator created an account for you at !site', $variables);
+      case 'admin_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);
+      case 'approval_subject':
+        return t('Account details for !username at !site (pending admin approval)', $variables);
+      case '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 granted, you may 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 may wish to change your password at !edit_uri\n\n\n--  !site team", $variables);
+      case 'pass_subject':
+        return t('Replacement login information for !username at !site', $variables);
+      case 'pass_body':
+        return t("!username,\n\nA request to reset the password for your account has been made at !site.\n\nYou may now log in to !uri_brief 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. It expires after one day and nothing will happen if it's not used.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.", $variables);
+    }
+  }
+}
+
+function user_admin_check_user() {
+  $form['user'] = array('#type' => 'fieldset', '#title' => t('Username'));
+  $form['user']['test'] = array('#type' => 'textfield', '#title' => '', '#description' => t('Enter a username to check if it will be denied or allowed.'), '#size' => 30, '#maxlength' => USERNAME_MAX_LENGTH);
+  $form['user']['type'] = array('#type' => 'hidden', '#value' => 'user');
+  $form['user']['submit'] = array('#type' => 'submit', '#value' => t('Check username'));
+  $form['#submit']['user_admin_access_check_submit'] = array();
+  $form['#validate']['user_admin_access_check_validate'] = array();
+  $form['#theme'] = 'user_admin_access_check';
+  return $form;
+}
+
+function user_admin_check_mail() {
+  $form['mail'] = array('#type' => 'fieldset', '#title' => t('E-mail'));
+  $form['mail']['test'] = array('#type' => 'textfield', '#title' => '', '#description' => t('Enter an e-mail address to check if it will be denied or allowed.'), '#size' => 30, '#maxlength' => EMAIL_MAX_LENGTH);
+  $form['mail']['type'] = array('#type' => 'hidden', '#value' => 'mail');
+  $form['mail']['submit'] = array('#type' => 'submit', '#value' => t('Check e-mail'));
+  $form['#submit']['user_admin_access_check_submit'] = array();
+  $form['#validate']['user_admin_access_check_validate'] = array();
+  $form['#theme'] = 'user_admin_access_check';
+  return $form;
+}
+
+function user_admin_check_host() {
+  $form['host'] = array('#type' => 'fieldset', '#title' => t('Hostname'));
+  $form['host']['test'] = array('#type' => 'textfield', '#title' => '', '#description' => t('Enter a hostname or IP address to check if it will be denied or allowed.'), '#size' => 30, '#maxlength' => 64);
+  $form['host']['type'] = array('#type' => 'hidden', '#value' => 'host');
+  $form['host']['submit'] = array('#type' => 'submit', '#value' => t('Check hostname'));
+  $form['#submit']['user_admin_access_check_submit'] = array();
+  $form['#validate']['user_admin_access_check_validate'] = array();
+  $form['#theme'] = 'user_admin_access_check';
+  return $form;
+}
+
+/**
+ * Menu callback: check an access rule
+ */
+function user_admin_access_check() {
+  $output = drupal_get_form('user_admin_check_user');
+  $output .= drupal_get_form('user_admin_check_mail');
+  $output .= drupal_get_form('user_admin_check_host');
+  return $output;
+}
+
+function user_admin_access_check_validate($form_id, $form_values) {
+  if (empty($form_values['test'])) {
+    form_set_error($form_values['type'], t('No value entered. Please enter a test string and try again.'));
+  }
+}
+
+function user_admin_access_check_submit($form_id, $form_values) {
+  switch ($form_values['type']) {
+    case 'user':
+      if (drupal_is_denied('user', $form_values['test'])) {
+        drupal_set_message(t('The username %name is not allowed.', array('%name' => $form_values['test'])));
+      }
+      else {
+        drupal_set_message(t('The username %name is allowed.', array('%name' => $form_values['test'])));
+      }
+      break;
+    case 'mail':
+      if (drupal_is_denied('mail', $form_values['test'])) {
+        drupal_set_message(t('The e-mail address %mail is not allowed.', array('%mail' => $form_values['test'])));
+      }
+      else {
+        drupal_set_message(t('The e-mail address %mail is allowed.', array('%mail' => $form_values['test'])));
+      }
+      break;
+    case 'host':
+      if (drupal_is_denied('host', $form_values['test'])) {
+        drupal_set_message(t('The hostname %host is not allowed.', array('%host' => $form_values['test'])));
+      }
+      else {
+        drupal_set_message(t('The hostname %host is allowed.', array('%host' => $form_values['test'])));
+      }
+      break;
+    default:
+      break;
+  }
+}
+
+/**
+ * Menu callback: add an access rule
+ */
+function user_admin_access_add($mask = NULL, $type = NULL) {
+  if ($edit = $_POST) {
+    if (!$edit['mask']) {
+      form_set_error('mask', t('You must enter a mask.'));
+    }
+    else {
+      $aid = db_next_id('{access}_aid');
+      db_query("INSERT INTO {access} (aid, mask, type, status) VALUES ('%s', '%s', '%s', %d)", $aid, $edit['mask'], $edit['type'], $edit['status']);
+      drupal_set_message(t('The access rule has been added.'));
+      drupal_goto('admin/user/rules');
+    }
+  }
+  else {
+    $edit['mask'] = $mask;
+    $edit['type'] = $type;
+  }
+  return drupal_get_form('user_admin_access_add_form', $edit, t('Add rule'));
+}
+
+/**
+ * Menu callback: delete an access rule
+ */
+function user_admin_access_delete_confirm($aid = 0) {
+  $access_types = array('user' => t('username'), 'mail' => t('e-mail'), 'host' => t('host'));
+  $edit = db_fetch_object(db_query('SELECT aid, type, status, mask FROM {access} WHERE aid = %d', $aid));
+
+  $form = array();
+  $form['aid'] = array('#type' => 'hidden', '#value' => $aid);
+  $output = confirm_form($form,
+                  t('Are you sure you want to delete the @type rule for %rule?', array('@type' => $access_types[$edit->type], '%rule' => $edit->mask)),
+                  'admin/user/rules',
+                  t('This action cannot be undone.'),
+                  t('Delete'),
+                  t('Cancel'));
+  return $output;
+}
+
+function user_admin_access_delete_confirm_submit($form_id, $form_values) {
+  db_query('DELETE FROM {access} WHERE aid = %d', $form_values['aid']);
+  drupal_set_message(t('The access rule has been deleted.'));
+  return 'admin/user/rules';
+}
+
+/**
+ * Menu callback: edit an access rule
+ */
+function user_admin_access_edit($aid = 0) {
+  if ($edit = $_POST) {
+    if (!$edit['mask']) {
+      form_set_error('mask', t('You must enter a mask.'));
+    }
+    else {
+      db_query("UPDATE {access} SET mask = '%s', type = '%s', status = '%s' WHERE aid = %d", $edit['mask'], $edit['type'], $edit['status'], $aid);
+      drupal_set_message(t('The access rule has been saved.'));
+      drupal_goto('admin/user/rules');
+    }
+  }
+  else {
+    $edit = db_fetch_array(db_query('SELECT aid, type, status, mask FROM {access} WHERE aid = %d', $aid));
+  }
+  return drupal_get_form('user_admin_access_edit_form', $edit, t('Save rule'));
+}
+
+function user_admin_access_form($edit, $submit) {
+  $form['status'] = array(
+    '#type' => 'radios',
+    '#title' => t('Access type'),
+    '#default_value' => isset($edit['status']) ? $edit['status'] : array(),
+    '#options' => array('1' => t('Allow'), '0' => t('Deny')),
+  );
+  $type_options = array('user' => t('Username'), 'mail' => t('E-mail'), 'host' => t('Host'));
+  $form['type'] = array(
+    '#type' => 'radios',
+    '#title' => t('Rule type'),
+    '#default_value' => (isset($type_options[$edit['type']]) ? $edit['type'] : 'user'),
+    '#options' => $type_options,
+  );
+  $form['mask'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Mask'),
+    '#size' => 30,
+    '#maxlength' => 64,
+    '#default_value' => $edit['mask'],
+    '#description' => '%: '. t('Matches any number of characters, even zero characters') .'.<br />_: '. t('Matches exactly one character.'),
+    '#required' => TRUE,
+  );
+  $form['submit'] = array('#type' => 'submit', '#value' => $submit);
+
+  return $form;
+}
+
+/**
+ * Menu callback: list all access rules
+ */
+function user_admin_access() {
+  $header = array(array('data' => t('Access type'), 'field' => 'status'), array('data' => t('Rule type'), 'field' => 'type'), array('data' => t('Mask'), 'field' => 'mask'), array('data' => t('Operations'), 'colspan' => 2));
+  $result = db_query("SELECT aid, type, status, mask FROM {access}". tablesort_sql($header));
+  $access_types = array('user' => t('username'), 'mail' => t('e-mail'), 'host' => t('host'));
+  $rows = array();
+  while ($rule = db_fetch_object($result)) {
+    $rows[] = array($rule->status ? t('allow') : t('deny'), $access_types[$rule->type], $rule->mask, l(t('edit'), 'admin/user/rules/edit/'. $rule->aid), l(t('delete'), 'admin/user/rules/delete/'. $rule->aid));
+  }
+  if (empty($rows)) {
+    $rows[] = array(array('data' => '<em>'. t('There are currently no access rules.') .'</em>', 'colspan' => 5));
+  }
+  return theme('table', $header, $rows);
+}
+
+/**
+ * Retrieve an array of roles matching specified conditions.
+ *
+ * @param $membersonly
+ *   Set this to TRUE to exclude the 'anonymous' role.
+ * @param $permission
+ *   A string containing a permission. If set, only roles containing that permission are returned.
+ *
+ * @return
+ *   An associative array with the role id as the key and the role name as value.
+ */
+function user_roles($membersonly = 0, $permission = 0) {
+  $roles = array();
+
+  if ($permission) {
+    $result = db_query("SELECT r.* FROM {role} r INNER JOIN {permission} p ON r.rid = p.rid WHERE p.perm LIKE '%%%s%%' ORDER BY r.name", $permission);
+  }
+  else {
+    $result = db_query('SELECT * FROM {role} ORDER BY name');
+  }
+  while ($role = db_fetch_object($result)) {
+    if (!$membersonly || ($membersonly && $role->rid != DRUPAL_ANONYMOUS_RID)) {
+      $roles[$role->rid] = $role->name;
+    }
+  }
+  return $roles;
+}
+
+/**
+ * Menu callback: administer permissions.
+ */
+function user_admin_perm($rid = NULL) {
+  if (is_numeric($rid)) {
+    $result = db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid WHERE r.rid = %d', $rid);
+  }
+  else {
+    $result = db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid ORDER BY name');
+  }
+
+  // Compile role array:
+  // Add a comma at the end so when searching for a permission, we can
+  // always search for "$perm," to make sure we do not confuse
+  // permissions that are substrings of each other.
+  while ($role = db_fetch_object($result)) {
+    $role_permissions[$role->rid] = $role->perm .',';
+  }
+
+  if (is_numeric($rid)) {
+    $result = db_query('SELECT rid, name FROM {role} r WHERE r.rid = %d ORDER BY name', $rid);
+  }
+  else {
+    $result = db_query('SELECT rid, name FROM {role} ORDER BY name');
+  }
+
+  $role_names = array();
+  while ($role = db_fetch_object($result)) {
+    $role_names[$role->rid] = $role->name;
+  }
+
+  // Render role/permission overview:
+  $options = array();
+  foreach (module_list(FALSE, FALSE, TRUE) as $module) {
+    if ($permissions = module_invoke($module, 'perm')) {
+      $form['permission'][] = array(
+        '#value' => $module,
+      );
+      asort($permissions);
+      foreach ($permissions as $perm) {
+        $options[$perm] = '';
+        $form['permission'][$perm] = array('#value' => t($perm));
+        foreach ($role_names as $rid => $name) {
+          // Builds arrays for checked boxes for each role
+          if (strpos($role_permissions[$rid], $perm .',') !== FALSE) {
+            $status[$rid][] = $perm;
+          }
+        }
+      }
+    }
+  }
+
+  // Have to build checkboxes here after checkbox arrays are built
+  foreach ($role_names as $rid => $name) {
+    $form['checkboxes'][$rid] = array('#type' => 'checkboxes', '#options' => $options, '#default_value' => isset($status[$rid]) ? $status[$rid] : array());
+    $form['role_names'][$rid] = array('#value' => $name, '#tree' => TRUE);
+  }
+  $form['submit'] = array('#type' => 'submit', '#value' => t('Save permissions'));
+
+  return $form;
+}
+
+function theme_user_admin_perm($form) {
+  foreach (element_children($form['permission']) as $key) {
+    // Don't take form control structures
+    if (is_array($form['permission'][$key])) {
+      $row = array();
+      // Module name
+      if (is_numeric($key)) {
+        $row[] = array('data' => t('@module module', array('@module' => drupal_render($form['permission'][$key]))), 'class' => 'module', 'id' => 'module-'. $form['permission'][$key]['#value'], 'colspan' => count($form['role_names']) + 1);
+      }
+      else {
+        $row[] = array('data' => drupal_render($form['permission'][$key]), 'class' => 'permission');
+        foreach (element_children($form['checkboxes']) as $rid) {
+          if (is_array($form['checkboxes'][$rid])) {
+            $row[] = array('data' => drupal_render($form['checkboxes'][$rid][$key]), 'align' => 'center', 'title' => t($key));
+          }
+        }
+      }
+      $rows[] = $row;
+    }
+  }
+  $header[] = (t('Permission'));
+  foreach (element_children($form['role_names']) as $rid) {
+    if (is_array($form['role_names'][$rid])) {
+      $header[] = drupal_render($form['role_names'][$rid]);
+    }
+  }
+  $output = theme('table', $header, $rows, array('id' => 'permissions'));
+  $output .= drupal_render($form);
+  return $output;
+}
+
+function user_admin_perm_submit($form_id, $form_values) {
+  // Save permissions:
+  $result = db_query('SELECT * FROM {role}');
+  while ($role = db_fetch_object($result)) {
+    if (isset($form_values[$role->rid])) {
+      // Delete, so if we clear every checkbox we reset that role;
+      // otherwise permissions are active and denied everywhere.
+      db_query('DELETE FROM {permission} WHERE rid = %d', $role->rid);
+      $form_values[$role->rid] = array_filter($form_values[$role->rid]);
+      if (count($form_values[$role->rid])) {
+        db_query("INSERT INTO {permission} (rid, perm) VALUES (%d, '%s')", $role->rid, implode(', ', array_keys($form_values[$role->rid])));
+      }
+    }
+  }
+
+  drupal_set_message(t('The changes have been saved.'));
+
+  // Clear the cached pages and menus:
+  menu_rebuild();
+
+}
+
+/**
+ * Menu callback: administer roles.
+ */
+function user_admin_role() {
+  $id = arg(4);
+  if ($id) {
+    if (DRUPAL_ANONYMOUS_RID == $id || DRUPAL_AUTHENTICATED_RID == $id) {
+      drupal_goto('admin/user/roles');
+    }
+    // Display the edit role form.
+    $role = db_fetch_object(db_query('SELECT * FROM {role} WHERE rid = %d', $id));
+    $form['name'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Role name'),
+      '#default_value' => $role->name,
+      '#size' => 30,
+      '#required' => TRUE,
+      '#maxlength' => 64,
+      '#description' => t('The name for this role. Example: "moderator", "editorial board", "site architect".'),
+    );
+    $form['rid'] = array(
+      '#type' => 'value',
+      '#value' => $id,
+    );
+    $form['submit'] = array(
+      '#type' => 'submit',
+      '#value' => t('Save role'),
+    );
+    $form['delete'] = array(
+      '#type' => 'submit',
+      '#value' => t('Delete role'),
+    );
+  }
+  else {
+    $form['name'] = array(
+      '#type' => 'textfield',
+      '#size' => 32,
+      '#maxlength' => 64,
+    );
+    $form['submit'] = array(
+      '#type' => 'submit',
+      '#value' => t('Add role'),
+    );
+    $form['#submit']['user_admin_role_submit'] = array();
+    $form['#validate']['user_admin_role_validate'] = array();
+  }
+  return $form;
+}
+
+function user_admin_role_validate($form_id, $form_values) {
+  if ($form_values['name']) {
+    if ($form_values['op'] == t('Save role')) {
+      if (db_result(db_query("SELECT COUNT(*) FROM {role} WHERE name = '%s' AND rid != %d", $form_values['name'], $form_values['rid']))) {
+        form_set_error('name', t('The role name %name already exists. Please choose another role name.', array('%name' => $form_values['name'])));
+      }
+    }
+    else if ($form_values['op'] == t('Add role')) {
+      if (db_result(db_query("SELECT COUNT(*) FROM {role} WHERE name = '%s'", $form_values['name']))) {
+        form_set_error('name', t('The role name %name already exists. Please choose another role name.', array('%name' => $form_values['name'])));
+      }
+    }
+  }
+  else {
+    form_set_error('name', t('You must specify a valid role name.'));
+  }
+}
+
+function user_admin_role_submit($form_id, $form_values) {
+  if ($form_values['op'] == t('Save role')) {
+    db_query("UPDATE {role} SET name = '%s' WHERE rid = %d", $form_values['name'], $form_values['rid']);
+    drupal_set_message(t('The role has been renamed.'));
+  }
+  else if ($form_values['op'] == t('Delete role')) {
+    db_query('DELETE FROM {role} WHERE rid = %d', $form_values['rid']);
+    db_query('DELETE FROM {permission} WHERE rid = %d', $form_values['rid']);
+    // Update the users who have this role set:
+    db_query('DELETE FROM {users_roles} WHERE rid = %d', $form_values['rid']);
+
+    drupal_set_message(t('The role has been deleted.'));
+  }
+  else if ($form_values['op'] == t('Add role')) {
+    db_query("INSERT INTO {role} (name) VALUES ('%s')", $form_values['name']);
+    drupal_set_message(t('The role has been added.'));
+  }
+  return 'admin/user/roles';
+}
+
+function theme_user_admin_new_role($form) {
+  $header = array(t('Name'), array('data' => t('Operations'), 'colspan' => 2));
+  foreach (user_roles() as $rid => $name) {
+    $edit_permissions = l(t('edit permissions'), 'admin/user/access/'. $rid);
+    if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
+      $rows[] = array($name, l(t('edit role'), 'admin/user/roles/edit/'. $rid), $edit_permissions);
+    }
+    else {
+      $rows[] = array($name, t('locked'), $edit_permissions);
+    }
+  }
+  $rows[] = array(drupal_render($form['name']), array('data' => drupal_render($form['submit']), 'colspan' => 2));
+
+  $output = drupal_render($form);
+  $output .= theme('table', $header, $rows);
+
+  return $output;
+}
+
+function user_admin_account() {
+  $filter = user_build_filter_query();
+
+  $header = array(
+    array(),
+    array('data' => t('Username'), 'field' => 'u.name'),
+    array('data' => t('Status'), 'field' => 'u.status'),
+    t('Roles'),
+    array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'),
+    array('data' => t('Last access'), 'field' => 'u.access'),
+    t('Operations')
+  );
+
+  $sql = 'SELECT DISTINCT u.uid, u.name, u.status, u.created, u.access FROM {users} u LEFT JOIN {users_roles} ur ON u.uid = ur.uid '. $filter['join'] .' WHERE u.uid != 0 '. $filter['where'];
+  $sql .= tablesort_sql($header);
+  $result = pager_query($sql, 50, 0, NULL, $filter['args']);
+
+  $form['options'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Update options'),
+    '#prefix' => '<div class="container-inline">',
+    '#suffix' => '</div>',
+  );
+  $options = array();
+  foreach (module_invoke_all('user_operations') as $operation => $array) {
+    $options[$operation] = $array['label'];
+  }
+  $form['options']['operation'] = array(
+    '#type' => 'select',
+    '#options' => $options,
+    '#default_value' => 'unblock',
+  );
+  $form['options']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Update'),
+  );
+
+  $destination = drupal_get_destination();
+
+  $status = array(t('blocked'), t('active'));
+  $roles = user_roles(1);
+  $accounts = array();
+  while ($account = db_fetch_object($result)) {
+    $accounts[$account->uid] = '';
+    $form['name'][$account->uid] = array('#value' => theme('username', $account));
+    $form['status'][$account->uid] =  array('#value' => $status[$account->status]);
+    $users_roles = array();
+    $roles_result = db_query('SELECT rid FROM {users_roles} WHERE uid = %d', $account->uid);
+    while ($user_role = db_fetch_object($roles_result)) {
+      $users_roles[] = $roles[$user_role->rid];
+    }
+    asort($users_roles);
+    $form['roles'][$account->uid][0] = array('#value' => theme('item_list', $users_roles));
+    $form['member_for'][$account->uid] = array('#value' => format_interval(time() - $account->created));
+    $form['last_access'][$account->uid] =  array('#value' => $account->access ? t('@time ago', array('@time' => format_interval(time() - $account->access))) : t('never'));
+    $form['operations'][$account->uid] = array('#value' => l(t('edit'), "user/$account->uid/edit", array('query' => $destination)));
+  }
+  $form['accounts'] = array(
+    '#type' => 'checkboxes',
+    '#options' => $accounts
+  );
+  $form['pager'] = array('#value' => theme('pager', NULL, 50, 0));
+
+  return $form;
+}
+
+/**
+ * Theme user administration overview.
+ */
+function theme_user_admin_account($form) {
+  // Overview table:
+  $header = array(
+    theme('table_select_header_cell'),
+    array('data' => t('Username'), 'field' => 'u.name'),
+    array('data' => t('Status'), 'field' => 'u.status'),
+    t('Roles'),
+    array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'),
+    array('data' => t('Last access'), 'field' => 'u.access'),
+    t('Operations')
+  );
+
+  $output = drupal_render($form['options']);
+  if (isset($form['name']) && is_array($form['name'])) {
+    foreach (element_children($form['name']) as $key) {
+      $rows[] = array(
+        drupal_render($form['accounts'][$key]),
+        drupal_render($form['name'][$key]),
+        drupal_render($form['status'][$key]),
+        drupal_render($form['roles'][$key]),
+        drupal_render($form['member_for'][$key]),
+        drupal_render($form['last_access'][$key]),
+        drupal_render($form['operations'][$key]),
+      );
+    }
+  }
+  else  {
+    $rows[] = array(array('data' => t('No users available.'), 'colspan' => '7'));
+  }
+
+  $output .= theme('table', $header, $rows);
+  if ($form['pager']['#value']) {
+    $output .= drupal_render($form['pager']);
+  }
+
+  $output .= drupal_render($form);
+
+  return $output;
+}
+
+/**
+ * Submit the user administration update form.
+ */
+function user_admin_account_submit($form_id, $form_values) {
+  $operations = module_invoke_all('user_operations');
+  $operation = $operations[$form_values['operation']];
+  // Filter out unchecked accounts.
+  $accounts = array_filter($form_values['accounts']);
+  if ($function = $operation['callback']) {
+    // Add in callback arguments if present.
+    if (isset($operation['callback arguments'])) {
+      $args = array_merge(array($accounts), $operation['callback arguments']);
+    }
+    else {
+      $args = array($accounts);
+    }
+    call_user_func_array($function, $args);
+
+    drupal_set_message(t('The update has been performed.'));
+  }
+}
+
+function user_admin_account_validate($form_id, $form_values) {
+  $form_values['accounts'] = array_filter($form_values['accounts']);
+  if (count($form_values['accounts']) == 0) {
+    form_set_error('', t('No users selected.'));
+  }
+}
+
+/**
+ * Implementation of hook_user_operations().
+ */
+function user_user_operations() {
+  global $form_values;
+
+  $operations = array(
+    'unblock' => array(
+      'label' => t('Unblock the selected users'),
+      'callback' => 'user_user_operations_unblock',
+    ),
+    'block' => array(
+      'label' => t('Block the selected users'),
+      'callback' => 'user_user_operations_block',
+    ),
+    'delete' => array(
+      'label' => t('Delete the selected users'),
+    ),
+  );
+
+  if (user_access('administer access control')) {
+    $roles = user_roles(1);
+    unset($roles[DRUPAL_AUTHENTICATED_RID]);  // Can't edit authenticated role.
+
+    $add_roles = array();
+    foreach ($roles as $key => $value) {
+      $add_roles['add_role-'. $key] = $value;
+    }
+
+    $remove_roles = array();
+    foreach ($roles as $key => $value) {
+      $remove_roles['remove_role-'. $key] = $value;
+    }
+
+    if (count($roles)) {
+      $role_operations = array(
+        t('Add a role to the selected users') => array(
+          'label' => $add_roles,
+        ),
+        t('Remove a role from the selected users') => array(
+          'label' => $remove_roles,
+        ),
+      );
+
+      $operations += $role_operations;
+    }
+  }
+
+  // If the form has been posted, we need to insert the proper data for role editing if necessary.
+  if ($form_values) {
+    $operation_rid = explode('-', $form_values['operation']);
+    $operation = $operation_rid[0];
+    $rid = $operation_rid[1];
+    if ($operation == 'add_role' || $operation == 'remove_role') {
+      if (user_access('administer access control')) {
+        $operations[$form_values['operation']] = array(
+          'callback' => 'user_multiple_role_edit',
+          'callback arguments' => array($operation, $rid),
+        );
+      }
+      else {
+        watchdog('security', 'Detected malicious attempt to alter protected user fields.', array(), WATCHDOG_WARNING);
+        return;
+      }
+    }
+  }
+
+  return $operations;
+}
+
+/**
+ * Callback function for admin mass unblocking users.
+ */
+function user_user_operations_unblock($accounts) {
+  foreach ($accounts as $uid) {
+    $account = user_load(array('uid' => (int)$uid));
+    // Skip unblocking user if they are already unblocked.
+    if ($account !== FALSE && $account->status == 0) {
+      user_save($account, array('status' => 1));
+    }
+  }
+}
+
+/**
+ * Callback function for admin mass blocking users.
+ */
+function user_user_operations_block($accounts) {
+  foreach ($accounts as $uid) {
+    $account = user_load(array('uid' => (int)$uid));
+    // Skip blocking user if they are already blocked.
+    if ($account !== FALSE && $account->status == 1) {
+      user_save($account, array('status' => 0));
+    }
+  }
+}
+
+/**
+ * Callback function for admin mass adding/deleting a user role.
+ */
+function user_multiple_role_edit($accounts, $operation, $rid) {
+  // The role name is not necessary as user_save() will reload the user
+  // object, but some modules' hook_user() may look at this first.
+  $role_name = db_result(db_query('SELECT name FROM {role} WHERE rid = %d', $rid));
+
+  switch ($operation) {
+    case 'add_role':
+      foreach ($accounts as $uid) {
+        $account = user_load(array('uid' => (int)$uid));
+        // Skip adding the role to the user if they already have it.
+        if ($account !== FALSE && !isset($account->roles[$rid])) {
+          $roles = $account->roles + array($rid => $role_name);
+          user_save($account, array('roles' => $roles));
+        }
+      }
+      break;
+    case 'remove_role':
+      foreach ($accounts as $uid) {
+        $account = user_load(array('uid' => (int)$uid));
+        // Skip removing the role from the user if they already don't have it.
+        if ($account !== FALSE && isset($account->roles[$rid])) {
+          $roles = array_diff($account->roles, array($rid => $role_name));
+          user_save($account, array('roles' => $roles));
+        }
+      }
+      break;
+  }
+}
+
+function user_multiple_delete_confirm() {
+  $edit = $_POST;
+
+  $form['accounts'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
+  // array_filter returns only elements with TRUE values
+  foreach (array_filter($edit['accounts']) as $uid => $value) {
+    $user = db_result(db_query('SELECT name FROM {users} WHERE uid = %d', $uid));
+    $form['accounts'][$uid] = array('#type' => 'hidden', '#value' => $uid, '#prefix' => '<li>', '#suffix' => check_plain($user) ."</li>\n");
+  }
+  $form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
+
+  return confirm_form($form,
+                      t('Are you sure you want to delete these users?'),
+                      'admin/user/user', t('This action cannot be undone.'),
+                      t('Delete all'), t('Cancel'));
+}
+
+function user_multiple_delete_confirm_submit($form_id, $form_values) {
+  if ($form_values['confirm']) {
+    foreach ($form_values['accounts'] as $uid => $value) {
+      user_delete($form_values, $uid);
+    }
+    drupal_set_message(t('The users have been deleted.'));
+  }
+  return 'admin/user/user';
+}
+
+function user_admin_settings() {
+  // User registration settings.
+  $form['registration'] = array('#type' => 'fieldset', '#title' => t('User registration settings'));
+  $form['registration']['user_register'] = array('#type' => 'radios', '#title' => t('Public registrations'), '#default_value' => variable_get('user_register', 1), '#options' => array(t('Only site administrators can create new user accounts.'), t('Visitors can create accounts and no administrator approval is required.'), t('Visitors can create accounts but administrator approval is required.')));
+  $form['registration']['user_email_verification'] = array('#type' => 'checkbox', '#title' => t('Require e-mail verification when a visitor creates an account'), '#default_value' => variable_get('user_email_verification', TRUE), '#description' => t('If this box is checked, new users will be required to validate their e-mail address prior to logging into to the site, and will be assigned a system-generated password. With it unchecked, users will be logged in immediately upon registering, and may select their own passwords during registration.'));
+  $form['registration']['user_registration_help'] = array('#type' => 'textarea', '#title' => t('User registration guidelines'), '#default_value' => variable_get('user_registration_help', ''), '#description' => t("This text is displayed at the top of the user registration form. It's useful for helping or instructing your users."));
+
+  // User e-mail settings.
+  $form['email'] = array('#type' => 'fieldset', '#title' => t('User e-mail settings'));
+  $form['email']['user_mail_welcome_subject'] = array('#type' => 'textfield', '#title' => t('Subject of welcome e-mail'), '#default_value' => _user_mail_text('welcome_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri, !login_url.');
+  $form['email']['user_mail_welcome_body'] = array('#type' => 'textarea', '#title' => t('Body of welcome e-mail'), '#default_value' => _user_mail_text('welcome_body'), '#rows' => 15, '#description' => t('Customize the body of the welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !login_uri, !edit_uri, !login_url.');
+  $form['email']['user_mail_admin_subject'] = array('#type' => 'textfield', '#title' => t('Subject of welcome e-mail (user created by administrator)'), '#default_value' => _user_mail_text('admin_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your welcome e-mail, which is sent to new member accounts created by an administrator.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri, !login_url.');
+  $form['email']['user_mail_admin_body'] = array('#type' => 'textarea', '#title' => t('Body of welcome e-mail (user created by administrator)'), '#default_value' => _user_mail_text('admin_body'), '#rows' => 15, '#description' => t('Customize the body of the welcome e-mail, which is sent to new member accounts created by an administrator.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !login_uri, !edit_uri, !login_url.');
+  $form['email']['user_mail_approval_subject'] = array('#type' => 'textfield', '#title' => t('Subject of welcome e-mail (awaiting admin approval)'), '#default_value' => _user_mail_text('approval_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your awaiting approval welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri, !login_url.');
+  $form['email']['user_mail_approval_body'] = array('#type' => 'textarea', '#title' => t('Body of welcome e-mail (awaiting admin approval)'), '#default_value' => _user_mail_text('approval_body'), '#rows' => 15, '#description' => t('Customize the body of the awaiting approval welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !login_uri, !edit_uri, !login_url.');
+  $form['email']['user_mail_pass_subject'] = array('#type' => 'textfield', '#title' => t('Subject of password recovery e-mail'), '#default_value' => _user_mail_text('pass_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your forgotten password e-mail.') .' '. t('Available variables are:') .' !username, !site, !login_url, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri.');
+  $form['email']['user_mail_pass_body'] = array('#type' => 'textarea', '#title' => t('Body of password recovery e-mail'), '#default_value' => _user_mail_text('pass_body'), '#rows' => 15, '#description' => t('Customize the body of the forgotten password e-mail.') .' '. t('Available variables are:') .' !username, !site, !login_url, !uri, !uri_brief, !mailto, !login_uri, !edit_uri.');
+
+  // User signatures.
+  $form['signatures'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Signatures'),
+  );
+  $form['signatures']['user_signatures'] = array(
+    '#type' => 'radios',
+    '#title' => t('Signature support'),
+    '#default_value' => variable_get('user_signatures', 0),
+    '#options' => array(t('Disabled'), t('Enabled')),
+    '#description' => t('Enable signature support.'),
+  );
+
+  // If picture support is enabled, check whether the picture directory exists:
+  if (variable_get('user_pictures', 0)) {
+    $picture_path = file_create_path(variable_get('user_picture_path', 'pictures'));
+    file_check_directory($picture_path, 1, 'user_picture_path');
+  }
+
+  $form['pictures'] = array('#type' => 'fieldset', '#title' => t('Pictures'));
+  $form['pictures']['user_pictures'] = array('#type' => 'radios', '#title' => t('Picture support'), '#default_value' => variable_get('user_pictures', 0), '#options' => array(t('Disabled'), t('Enabled')), '#description' => t('Enable picture support.'));
+  $form['pictures']['user_picture_path'] = array('#type' => 'textfield', '#title' => t('Picture image path'), '#default_value' => variable_get('user_picture_path', 'pictures'), '#size' => 30, '#maxlength' => 255, '#description' => t('Subdirectory in the directory %dir where pictures will be stored.', array('%dir' => file_directory_path() .'/')));
+  $form['pictures']['user_picture_default'] = array('#type' => 'textfield', '#title' => t('Default picture'), '#default_value' => variable_get('user_picture_default', ''), '#size' => 30, '#maxlength' => 255, '#description' => t('URL of picture to display for users with no custom picture selected. Leave blank for none.'));
+  $form['pictures']['user_picture_dimensions'] = array('#type' => 'textfield', '#title' => t('Picture maximum dimensions'), '#default_value' => variable_get('user_picture_dimensions', '85x85'), '#size' => 15, '#maxlength' => 10, '#description' => t('Maximum dimensions for pictures, in pixels.'));
+  $form['pictures']['user_picture_file_size'] = array('#type' => 'textfield', '#title' => t('Picture maximum file size'), '#default_value' => variable_get('user_picture_file_size', '30'), '#size' => 15, '#maxlength' => 10, '#description' => t('Maximum file size for pictures, in kB.'));
+  $form['pictures']['user_picture_guidelines'] = array('#type' => 'textarea', '#title' => t('Picture guidelines'), '#default_value' => variable_get('user_picture_guidelines', ''), '#description' => t("This text is displayed at the picture upload form in addition to the default guidelines. It's useful for helping or instructing your users."));
+
+  return system_settings_form($form);
+}
+
+function user_admin($callback_arg = '') {
+  $op = isset($_POST['op']) ? $_POST['op'] : $callback_arg;
+
+  switch ($op) {
+    case 'search':
+    case t('Search'):
+      $keys = isset($_POST['keys']) ? $_POST['keys'] : NULL;
+      $output = drupal_get_form('search_form', url('admin/user/search'), $keys, 'user') . search_data($keys, 'user');
+      break;
+    case t('Create new account'):
+    case 'create':
+      $output = drupal_get_form('user_register');
+      break;
+    default:
+      if (!empty($_POST['accounts']) && isset($_POST['operation']) && ($_POST['operation'] == 'delete')) {
+        $output = drupal_get_form('user_multiple_delete_confirm');
+      }
+      else {
+        $output = drupal_get_form('user_filter_form');
+        $output .= drupal_get_form('user_admin_account');
+      }
+  }
+  return $output;
+}
+
+/**
+ * Implementation of hook_help().
+ */
+function user_help($section) {
+  global $user;
+
+  switch ($section) {
+    case 'admin/help#user':
+      $output = '<p>'. t('The user module allows users to register, login, and log out. Users benefit from being able to sign on because it associates content they create with their account and allows various permissions to be set for their roles. The user module supports user roles which can setup fine grained permissions allowing each role to do only what the administrator wants them to. Each user is assigned to one or more roles. By default there are two roles <em>anonymous</em> - a user who has not logged in, and <em>authenticated</em> a user who has signed up and who has been authorized.') .'</p>';
+      $output .= '<p>'. t('Users can use their own name or handle and can fine tune some personal configuration settings through their individual my account page. Registered users need to authenticate by supplying either a local username and password, or a remote username and password such as DelphiForums ID, or one from a Drupal powered website. A visitor accessing your website is assigned an unique ID, the so-called session ID, which is stored in a cookie. For security\'s sake, the cookie does not contain personal information but acts as a key to retrieve the information stored on your server.') .'</p>';
+      $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="@user">User page</a>.', array('@user' => 'http://drupal.org/handbook/modules/user/')) .'</p>';
+      return $output;
+    case 'admin/user/user':
+      return '<p>'. t('Drupal allows users to register, login, log out, maintain user profiles, etc. Users of the site may not use their own names to post content until they have signed up for a user account.') .'</p>';
+    case 'admin/user/user/create':
+    case 'admin/user/user/account/create':
+      return '<p>'. t('This web page allows the administrators to register a new users by hand. Note that you cannot have a user where either the e-mail address or the username match another user in the system.') .'</p>';
+    case 'admin/user/rules':
+      return '<p>'. t('Set up username and e-mail address access rules for new <em>and</em> existing accounts (currently logged in accounts will not be logged out). If a username or e-mail address for an account matches any deny rule, but not an allow rule, then the account will not be allowed to be created or to log in. A host rule is effective for every page view, not just registrations.') .'</p>';
+    case 'admin/user/access':
+      return '<p>'. t('Permissions let you control what users can do on your site. Each user role (defined on the <a href="@role">user roles page</a>) has its own set of permissions. For example, you could give users classified as "Administrators" permission to "administer nodes" but deny this power to ordinary, "authenticated" users. You can use permissions to reveal new features to privileged users (those with subscriptions, for example). Permissions also allow trusted users to share the administrative burden of running a busy site.', array('@role' => url('admin/user/roles'))) .'</p>';
+    case 'admin/user/roles':
+      return t('<p>Roles allow you to fine tune the security and administration of Drupal. A role defines a group of users that have certain privileges as defined in <a href="@permissions">user permissions</a>. Examples of roles include: anonymous user, authenticated user, moderator, administrator and so on. In this area you will define the <em>role names</em> of the various roles. To delete a role choose "edit".</p><p>By default, Drupal comes with two user roles:</p>
+      <ul>
+      <li>Anonymous user: this role is used for users that don\'t have a user account or that are not authenticated.</li>
+      <li>Authenticated user: this role is automatically granted to all logged in users.</li>
+      </ul>', array('@permissions' => url('admin/user/access')));
+    case 'admin/user/search':
+      return '<p>'. t('Enter a simple pattern ("*" may be used as a wildcard match) to search for a username. For example, one may search for "br" and Drupal might return "brian", "brad", and "brenda".') .'</p>';
+    case 'user/help#user':
+      $site = variable_get('site_name', 'Drupal');
+
+      $affiliates = user_auth_help_links();
+      if (count($affiliates)) {
+        $affiliate_info = implode(', ', user_auth_help_links());
+      }
+      else {
+        $affiliate_info = t('one of our affiliates');
+      }
+
+      $output = t('
+      <h3>Distributed authentication<a id="da"></a></h3>
+      <p>One of the more tedious moments in visiting a new website is filling out the registration form. Here at @site, you do not have to fill out a registration form if you are already a member of !affiliate-info. This capability is called <em>distributed authentication</em>, and <a href="@drupal">Drupal</a>, the software which powers @site, fully supports it.</p>
+      <p>Distributed authentication enables a new user to input a username and password into the login box, and immediately be recognized, even if that user never registered at @site. This works because Drupal knows how to communicate with external registration databases. For example, lets say that new user \'Joe\' is already a registered member of <a href="@delphi-forums">Delphi Forums</a>. Drupal informs Joe on registration and login screens that he may login with his Delphi ID instead of registering with @site. Joe likes that idea, and logs in with a username of joe@remote.delphiforums.com and his usual Delphi password. Drupal then contacts the <em>remote.delphiforums.com</em> server behind the scenes (usually using <a href="@xml">XML-RPC</a>, <a href="@http-post">HTTP POST</a>, or <a href="@soap">SOAP</a>) and asks: "Is the password for user Joe correct?". If Delphi replies yes, then we create a new @site account for Joe and log him into it. Joe may keep on logging into @site in the same manner, and he will always be logged into the same account.</p>', array('!affiliate-info' => $affiliate_info, '@site' => $site, '@drupal' => 'http://drupal.org', '@delphi-forums' => 'http://www.delphiforums.com', '@xml' => 'http://www.xmlrpc.com', '@http-post' => 'http://www.w3.org/Protocols/', '@soap' => 'http://www.soapware.org'));
+
+        foreach (module_list() as $module) {
+          if (module_hook($module, 'auth')) {
+            $output .= "<h4><a id=\"$module\"></a>". module_invoke($module, 'info', 'name') .'</h4>';
+            $output .= module_invoke($module, 'help', "user/help#$module");
+          }
+        }
+
+        return $output;
+  }
+
+}
+
+/**
+ * Menu callback; Prints user-specific help information.
+ */
+function user_help_page() {
+  return user_help('user/help#user');
+}
+
+/**
+ * Retrieve a list of all form elements for the specified category.
+ */
+function _user_forms(&$edit, $account, $category, $hook = 'form') {
+  $groups = array();
+  foreach (module_list() as $module) {
+    if ($data = module_invoke($module, 'user', $hook, $edit, $account, $category)) {
+      $groups = array_merge_recursive($data, $groups);
+    }
+  }
+  uasort($groups, '_user_sort');
+
+  return empty($groups) ? FALSE : $groups;
+}
+
+/**
+ * Retrieve a pipe delimited string of autocomplete suggestions for existing users
+ */
+function user_autocomplete($string = '') {
+  $matches = array();
+  if ($string) {
+    $result = db_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER('%s%%')", $string, 0, 10);
+    while ($user = db_fetch_object($result)) {
+      $matches[$user->name] = check_plain($user->name);
+   }
+  }
+  print drupal_to_js($matches);
+  exit();
+}
+
+/**
+ * List user administration filters that can be applied.
+ */
+function user_filters() {
+  // Regular filters
+  $filters = array();
+  $roles = user_roles(1);
+  unset($roles[DRUPAL_AUTHENTICATED_RID]); // Don't list authorized role.
+  if (count($roles)) {
+    $filters['role'] = array(
+      'title' => t('role'),
+      'where' => "ur.rid = %d",
+      'options' => $roles,
+      'join' => '',
+    );
+  }
+
+  $options = array();
+  $t_module = t('module');
+  foreach (module_list() as $module) {
+    if ($permissions = module_invoke($module, 'perm')) {
+      asort($permissions);
+      foreach ($permissions as $permission) {
+        $options["$module $t_module"][$permission] = t($permission);
+      }
+    }
+  }
+  ksort($options);
+  $filters['permission'] = array(
+    'title' => t('permission'),
+    'join' => 'LEFT JOIN {permission} p ON ur.rid = p.rid',
+    'where' => " ((p.perm IS NOT NULL AND p.perm LIKE '%%%s%%') OR u.uid = 1) ",
+    'options' => $options,
+  );
+
+  $filters['status'] = array(
+    'title' => t('status'),
+    'where' => 'u.status = %d',
+    'join' => '',
+    'options' => array(1 => t('active'), 0 => t('blocked')),
+  );
+  return $filters;
+}
+
+/**
+ * Build query for user administration filters based on session.
+ */
+function user_build_filter_query() {
+  $filters = user_filters();
+
+  // Build query
+  $where = $args = $join = array();
+  foreach ($_SESSION['user_overview_filter'] as $filter) {
+    list($key, $value) = $filter;
+    // This checks to see if this permission filter is an enabled permission for the authenticated role.
+    // If so, then all users would be listed, and we can skip adding it to the filter query.
+    if ($key == 'permission') {
+      $account = new stdClass();
+      $account->uid = 'user_filter';
+      $account->roles = array(DRUPAL_AUTHENTICATED_RID => 1);
+      if (user_access($value, $account)) {
+        continue;
+      }
+    }
+    $where[] = $filters[$key]['where'];
+    $args[] = $value;
+    $join[] = $filters[$key]['join'];
+  }
+  $where = !empty($where) ? 'AND '. implode(' AND ', $where) : '';
+  $join = !empty($join) ? ' '. implode(' ', array_unique($join)) : '';
+
+  return array('where' => $where,
+           'join' => $join,
+           'args' => $args,
+         );
+}
+
+/**
+ * Return form for user administration filters.
+ */
+function user_filter_form() {
+  $session = &$_SESSION['user_overview_filter'];
+  $session = is_array($session) ? $session : array();
+  $filters = user_filters();
+
+  $i = 0;
+  $form['filters'] = array('#type' => 'fieldset',
+                       '#title' => t('Show only users where'),
+                       '#theme' => 'user_filters',
+                     );
+  foreach ($session as $filter) {
+    list($type, $value) = $filter;
+    $string = ($i++ ? '<em>and</em> where <strong>%a</strong> is <strong>%b</strong>' : '<strong>%a</strong> is <strong>%b</strong>');
+    // Merge an array of arrays into one if necessary.
+    $options = $type == 'permission' ? call_user_func_array('array_merge', $filters[$type]['options']) : $filters[$type]['options'];
+    $form['filters']['current'][] = array('#value' => t($string, array('%a' => $filters[$type]['title'] , '%b' => $options[$value])));
+  }
+
+  foreach ($filters as $key => $filter) {
+    $names[$key] = $filter['title'];
+    $form['filters']['status'][$key] = array('#type' => 'select',
+                                         '#options' => $filter['options'],
+                                       );
+  }
+
+  $form['filters']['filter'] = array('#type' => 'radios',
+                                 '#options' => $names,
+                               );
+  $form['filters']['buttons']['submit'] = array('#type' => 'submit',
+                                            '#value' => (count($session) ? t('Refine') : t('Filter'))
+                                          );
+  if (count($session)) {
+    $form['filters']['buttons']['undo'] = array('#type' => 'submit',
+                                            '#value' => t('Undo')
+                                          );
+    $form['filters']['buttons']['reset'] = array('#type' => 'submit',
+                                             '#value' => t('Reset')
+                                           );
+  }
+
+  return $form;
+}
+
+/**
+ * Theme user administration filter form.
+ */
+function theme_user_filter_form($form) {
+  $output = '<div id="user-admin-filter">';
+  $output .= drupal_render($form['filters']);
+  $output .= '</div>';
+  $output .= drupal_render($form);
+  return $output;
+}
+
+/**
+ * Theme user administration filter selector.
+ */
+function theme_user_filters($form) {
+  $output = '<ul class="clear-block">';
+  if (!empty($form['current'])) {
+    foreach (element_children($form['current']) as $key) {
+      $output .= '<li>'. drupal_render($form['current'][$key]) .'</li>';
+    }
+  }
+
+  $output .= '<li><dl class="multiselect">'. (!empty($form['current']) ? '<dt><em>'. t('and') .'</em> '. t('where') .'</dt>' : '') .'<dd class="a">';
+  foreach (element_children($form['filter']) as $key) {
+    $output .= drupal_render($form['filter'][$key]);
+  }
+  $output .= '</dd>';
+
+  $output .= '<dt>'. t('is') .'</dt><dd class="b">';
+
+  foreach (element_children($form['status']) as $key) {
+    $output .= drupal_render($form['status'][$key]);
+  }
+  $output .= '</dd>';
+
+  $output .= '</dl>';
+  $output .= '<div class="container-inline" id="user-admin-buttons">'. drupal_render($form['buttons']) .'</div>';
+  $output .= '</li></ul>';
+
+  return $output;
+}
+
+/**
+ * Process result from user administration filter form.
+ */
+function user_filter_form_submit($form_id, $form_values) {
+  $op = $form_values['op'];
+  $filters = user_filters();
+  switch ($op) {
+    case t('Filter'): case t('Refine'):
+      if (isset($form_values['filter'])) {
+        $filter = $form_values['filter'];
+        // Merge an array of arrays into one if necessary.
+        $options = $filter == 'permission' ? call_user_func_array('array_merge', $filters[$filter]['options']) : $filters[$filter]['options'];
+        if (isset($options[$form_values[$filter]])) {
+          $_SESSION['user_overview_filter'][] = array($filter, $form_values[$filter]);
+        }
+      }
+      break;
+    case t('Undo'):
+      array_pop($_SESSION['user_overview_filter']);
+      break;
+    case t('Reset'):
+      $_SESSION['user_overview_filter'] = array();
+      break;
+    case t('Update'):
+      return;
+  }
+
+  return 'admin/user/user';
+}
+
+
+function user_forms() {
+  $forms['user_admin_access_add_form']['callback'] = 'user_admin_access_form';
+  $forms['user_admin_access_edit_form']['callback'] = 'user_admin_access_form';
+  $forms['user_admin_new_role']['callback'] = 'user_admin_role';
+  return $forms;
+}
+
+/**
+ * Implementation of hook_comments().
+ */
+function user_comment($comment, $op) {
+  // Validate signature.
+  if ($op == 'view') {
+    if (variable_get('user_signatures', 0) && !empty($comment->signature)) {
+      $comment->signature = check_markup($comment->signature, $comment->format);
+    }
+    else {
+      $comment->signature = '';
+    }
+  }
+}
+
+/**
+ * Theme output of user signature.
+ *
+ * @ingroup themeable
+ */
+function theme_user_signature($signature) {
+  $output = '';
+  if ($signature) {
+    $output .= '<div class="clear">';
+    $output .= '<div>'. '—' .'</div>';
+    $output .= $signature;
+    $output .= '</div>';
+  }
+
+  return $output;
+}
+

