=== modified file 'includes/database.inc'
--- includes/database.inc	2007-08-30 19:54:21 +0000
+++ includes/database.inc	2007-09-02 18:01:55 +0000
@@ -164,35 +164,6 @@ function db_set_active($name = 'default'
 }
 
 /**
- * Helper function for db_query().
- */
-function _db_query_callback($match, $init = FALSE) {
-  static $args = NULL;
-  if ($init) {
-    $args = $match;
-    return;
-  }
-
-  switch ($match[1]) {
-    case '%d': // We must use type casting to int to convert FALSE/NULL/(TRUE?)
-      return (int) array_shift($args); // We don't need db_escape_string as numbers are db-safe
-    case '%s':
-      return db_escape_string(array_shift($args));
-    case '%%':
-      return '%';
-    case '%f':
-      return (float) array_shift($args);
-    case '%b': // binary data
-      return db_encode_blob(array_shift($args));
-  }
-}
-
-/**
- * Indicates the place holders that should be replaced in _db_query_callback().
- */
-define('DB_QUERY_REGEXP', '/(%d|%s|%%|%f|%b)/');
-
-/**
  * Helper function for db_rewrite_sql.
  *
  * Collects JOIN and WHERE statements via hook_db_rewrite_sql()
@@ -428,6 +399,26 @@ function db_create_table(&$ret, $name, $
 }
 
 /**
+ * Creates a unique named table with the same structure as an existing table.
+ *
+ * @param $module
+ *   The name of the module that defines the existing table.
+ * @param $table
+ *   The name  of the table to copy. Prefixing is handled by this function,
+ *   so just use the table name.
+ * @return
+ *   Name of the freshly created table.
+ */
+function db_create_table_like($module, $table) {
+  $new_table_name = uniqid('temp_', FALSE);
+  $schema[$new_table_name] = drupal_get_schema_unprocessed($module, $table);
+  _drupal_initialize_schema($module, $schema);
+  $ret = array();
+  db_create_table($ret, $new_table_name, $schema[$new_table_name]);
+  return $new_table_name;
+}
+
+/**
  * Return an array of field names from an array of key/index column
  * specifiers.  This is usually an identity function but if a
  * key/index uses a column prefix specification, this function

=== modified file 'includes/database.mysql-common.inc'
--- includes/database.mysql-common.inc	2007-08-26 08:27:08 +0000
+++ includes/database.mysql-common.inc	2007-09-02 18:01:55 +0000
@@ -37,13 +37,110 @@
  */
 function db_query($query) {
   $args = func_get_args();
-  array_shift($args);
-  $query = db_prefix_tables($query);
-  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
-    $args = $args[0];
+  $query = db_prefix_tables(str_replace('%b', "'%s'", $query));
+  if (count($args) > 1) {
+    if (is_array($args[1])) {
+      $args = array_merge(array($query), $args[1]);
+    }
+    $args = array_map('db_escape_string', $args);
+    $args[0] = $query;
+    $query = call_user_func_array('sprintf', $args);
+  }
+  return _db_query($query);
+}
+
+/**
+ * Runs a limited-range query in the active database.
+ *
+ * Use this as a substitute for db_query() when a subset of the query is to be
+ * returned.
+ * User-supplied arguments to the query should be passed in as separate parameters
+ * so that they can be properly escaped to avoid SQL injection attacks.
+ *
+ * @param $query
+ *   A string containing an SQL query.
+ * @param ...
+ *   A variable number of arguments which are substituted into the query
+ *   using printf() syntax. The query arguments can be enclosed in one
+ *   array instead.
+ *   Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
+ *   in '') and %%.
+ *
+ *   NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
+ *   and TRUE values to decimal 1.
+ *
+ * @param $from
+ *   The first result row to return.
+ * @param $count
+ *   The maximum number of result rows to return.
+ * @return
+ *   A database query result resource, or FALSE if the query was not executed
+ *   correctly.
+ */
+function db_query_range($query) {
+  $args = func_get_args();
+  $count = array_pop($args);
+  $from = array_pop($args);
+
+  $query = db_prefix_tables(str_replace('%b', "'%s'", $query));
+  if (count(func_get_args()) > 3) {
+    // Check for array (alternative syntax).
+    if (is_array($args[1])) {
+      $args = array_merge(array($query), $args[1]);
+    }
+    $args = array_map('db_escape_string', $args);
+    $args[0] = $query;
+    $query = call_user_func_array('sprintf', $args);
+  }
+  $query .= ' LIMIT '. (int)$from .', '. (int)$count;
+  return _db_query($query);
+}
+
+/**
+ * Runs a SELECT query and stores its results in a temporary table.
+ *
+ * Use this as a substitute for db_query() when the results need to stored
+ * in a temporary table. Temporary tables exist for the duration of the page
+ * request.
+ * User-supplied arguments to the query should be passed in as separate parameters
+ * so that they can be properly escaped to avoid SQL injection attacks.
+ *
+ * Note that if you need to know how many results were returned, you should do
+ * a SELECT COUNT(*) on the temporary table afterwards. db_affected_rows() does
+ * not give consistent result across different database types in this case.
+ *
+ * @param $query
+ *   A string containing a normal SELECT SQL query.
+ * @param ...
+ *   A variable number of arguments which are substituted into the query
+ *   using printf() syntax. The query arguments can be enclosed in one
+ *   array instead.
+ *   Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
+ *   in '') and %%.
+ *
+ *   NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
+ *   and TRUE values to decimal 1.
+ *
+ * @param $table
+ *   The name of the temporary table to select into. This name will not be
+ *   prefixed as there is no risk of collision.
+ * @return
+ *   A database query result resource, or FALSE if the query was not executed
+ *   correctly.
+ */
+function db_query_temporary($query) {
+  $args = func_get_args();
+  $tablename = array_pop($args);
+  $query = db_prefix_tables(str_replace('%b', "'%s'", $query));
+  $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE '. $tablename .' Engine=HEAP SELECT', $query);
+  if (count($args) > 1) {
+    if (is_array($args[1])) {
+      $args = array_merge(array($query), $args[1]);
+    }
+    $args = array_map('db_escape_string', $args);
+    $args[0] = $query;
+    $query = call_user_func_array('sprintf', $args);
   }
-  _db_query_callback($args, TRUE);
-  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
   return _db_query($query);
 }
 
@@ -481,5 +578,26 @@ function db_last_insert_id($table, $fiel
 }
 
 /**
+ * Renames a table to another, replacing the latter.
+ *
+ * This function uses db specific ways to guarantee that no data loss can
+ * occur. In case of a failure, the replace simply does not happen.
+ *
+ * @param $src
+ *  Name of the source table, usally from db_create_table_like().
+ * @param $target
+ *  Name of the target table.
+ */
+function db_replace_table($src, $target) {
+  if (!db_error()) {
+    $swap_table = uniqid('temp_', FALSE);
+    db_query('RENAME TABLE {'. $target .'} TO '. $swap_table .', {'. $src .'} TO {'. $target .'}');
+    if (!db_error()) {
+      db_query("DROP TABLE $swap_table");
+    }
+  }
+}
+
+/**
  * @} End of "ingroup schemaapi".
- */
\ No newline at end of file
+ */

=== modified file 'includes/database.mysql.inc'
--- includes/database.mysql.inc	2007-08-29 18:38:55 +0000
+++ includes/database.mysql.inc	2007-09-02 16:39:58 +0000
@@ -230,96 +230,6 @@ function db_affected_rows() {
 }
 
 /**
- * Runs a limited-range query in the active database.
- *
- * Use this as a substitute for db_query() when a subset of the query is to be
- * returned.
- * User-supplied arguments to the query should be passed in as separate parameters
- * so that they can be properly escaped to avoid SQL injection attacks.
- *
- * @param $query
- *   A string containing an SQL query.
- * @param ...
- *   A variable number of arguments which are substituted into the query
- *   using printf() syntax. The query arguments can be enclosed in one
- *   array instead.
- *   Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
- *   in '') and %%.
- *
- *   NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
- *   and TRUE values to decimal 1.
- *
- * @param $from
- *   The first result row to return.
- * @param $count
- *   The maximum number of result rows to return.
- * @return
- *   A database query result resource, or FALSE if the query was not executed
- *   correctly.
- */
-function db_query_range($query) {
-  $args = func_get_args();
-  $count = array_pop($args);
-  $from = array_pop($args);
-  array_shift($args);
-
-  $query = db_prefix_tables($query);
-  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
-    $args = $args[0];
-  }
-  _db_query_callback($args, TRUE);
-  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
-  $query .= ' LIMIT '. (int)$from .', '. (int)$count;
-  return _db_query($query);
-}
-
-/**
- * Runs a SELECT query and stores its results in a temporary table.
- *
- * Use this as a substitute for db_query() when the results need to stored
- * in a temporary table. Temporary tables exist for the duration of the page
- * request.
- * User-supplied arguments to the query should be passed in as separate parameters
- * so that they can be properly escaped to avoid SQL injection attacks.
- *
- * Note that if you need to know how many results were returned, you should do
- * a SELECT COUNT(*) on the temporary table afterwards. db_affected_rows() does
- * not give consistent result across different database types in this case.
- *
- * @param $query
- *   A string containing a normal SELECT SQL query.
- * @param ...
- *   A variable number of arguments which are substituted into the query
- *   using printf() syntax. The query arguments can be enclosed in one
- *   array instead.
- *   Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
- *   in '') and %%.
- *
- *   NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
- *   and TRUE values to decimal 1.
- *
- * @param $table
- *   The name of the temporary table to select into. This name will not be
- *   prefixed as there is no risk of collision.
- * @return
- *   A database query result resource, or FALSE if the query was not executed
- *   correctly.
- */
-function db_query_temporary($query) {
-  $args = func_get_args();
-  $tablename = array_pop($args);
-  array_shift($args);
-
-  $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE '. $tablename .' Engine=HEAP SELECT', db_prefix_tables($query));
-  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
-    $args = $args[0];
-  }
-  _db_query_callback($args, TRUE);
-  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
-  return _db_query($query);
-}
-
-/**
  * Returns a properly formatted Binary Large OBject value.
  *
  * @param $data

=== modified file 'includes/database.mysqli.inc'
--- includes/database.mysqli.inc	2007-08-29 18:38:55 +0000
+++ includes/database.mysqli.inc	2007-09-02 16:39:58 +0000
@@ -229,96 +229,6 @@ function db_affected_rows() {
 }
 
 /**
- * Runs a limited-range query in the active database.
- *
- * Use this as a substitute for db_query() when a subset of the query is to be
- * returned.
- * User-supplied arguments to the query should be passed in as separate parameters
- * so that they can be properly escaped to avoid SQL injection attacks.
- *
- * @param $query
- *   A string containing an SQL query.
- * @param ...
- *   A variable number of arguments which are substituted into the query
- *   using printf() syntax. The query arguments can be enclosed in one
- *   array instead.
- *   Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
- *   in '') and %%.
- *
- *   NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
- *   and TRUE values to decimal 1.
- *
- * @param $from
- *   The first result row to return.
- * @param $count
- *   The maximum number of result rows to return.
- * @return
- *   A database query result resource, or FALSE if the query was not executed
- *   correctly.
- */
-function db_query_range($query) {
-  $args = func_get_args();
-  $count = array_pop($args);
-  $from = array_pop($args);
-  array_shift($args);
-
-  $query = db_prefix_tables($query);
-  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
-    $args = $args[0];
-  }
-  _db_query_callback($args, TRUE);
-  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
-  $query .= ' LIMIT '. (int)$from .', '. (int)$count;
-  return _db_query($query);
-}
-
-/**
- * Runs a SELECT query and stores its results in a temporary table.
- *
- * Use this as a substitute for db_query() when the results need to stored
- * in a temporary table. Temporary tables exist for the duration of the page
- * request.
- * User-supplied arguments to the query should be passed in as separate parameters
- * so that they can be properly escaped to avoid SQL injection attacks.
- *
- * Note that if you need to know how many results were returned, you should do
- * a SELECT COUNT(*) on the temporary table afterwards. db_affected_rows() does
- * not give consistent result across different database types in this case.
- *
- * @param $query
- *   A string containing a normal SELECT SQL query.
- * @param ...
- *   A variable number of arguments which are substituted into the query
- *   using printf() syntax. The query arguments can be enclosed in one
- *   array instead.
- *   Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
- *   in '') and %%.
- *
- *   NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
- *   and TRUE values to decimal 1.
- *
- * @param $table
- *   The name of the temporary table to select into. This name will not be
- *   prefixed as there is no risk of collision.
- * @return
- *   A database query result resource, or FALSE if the query was not executed
- *   correctly.
- */
-function db_query_temporary($query) {
-  $args = func_get_args();
-  $tablename = array_pop($args);
-  array_shift($args);
-
-  $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE '. $tablename .' Engine=HEAP SELECT', db_prefix_tables($query));
-  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
-    $args = $args[0];
-  }
-  _db_query_callback($args, TRUE);
-  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
-  return _db_query($query);
-}
-
-/**
  * Returns a properly formatted Binary Large Object value.
  *
  * @param $data

=== modified file 'includes/database.pgsql.inc'
--- includes/database.pgsql.inc	2007-08-29 18:38:55 +0000
+++ includes/database.pgsql.inc	2007-09-02 18:01:55 +0000
@@ -144,6 +144,35 @@ function db_query($query) {
 /**
  * Helper function for db_query().
  */
+function _db_query_callback($match, $init = FALSE) {
+  static $args = NULL;
+  if ($init) {
+    $args = $match;
+    return;
+  }
+
+  switch ($match[1]) {
+    case '%d': // We must use type casting to int to convert FALSE/NULL/(TRUE?)
+      return (int) array_shift($args); // We don't need db_escape_string as numbers are db-safe
+    case '%s':
+      return db_escape_string(array_shift($args));
+    case '%%':
+      return '%';
+    case '%f':
+      return (float) array_shift($args);
+    case '%b': // binary data
+      return db_encode_blob(array_shift($args));
+  }
+}
+
+/**
+ * Indicates the place holders that should be replaced in _db_query_callback().
+ */
+define('DB_QUERY_REGEXP', '/(%d|%s|%%|%f|%b)/');
+
+/**
+ * Helper function for db_query().
+ */
 function _db_query($query, $debug = 0) {
   global $active_db, $last_result, $queries;
 
@@ -443,6 +472,26 @@ function db_distinct_field($table, $fiel
 }
 
 /**
+ * Renames a table to an existing one.
+ *
+ * This function uses db specific ways to guarantee that no data loss can
+ * occur. In case of a failure, the rename simply does not happen.
+ *
+ * @param $new_table_name
+ *  Name of the source table, usally from db_create_table_like().
+ * @param $table
+ *  Name of the target table.
+ */
+function db_replace_table($src, $target) {
+  if (!db_error()) {
+    db_query('BEGIN');
+    db_query('DROP TABLE {'. $target .'}');
+    db_query('ALTER TABLE {'. $src .'} RENAME TO {'. $target .'}');
+    db_query('COMMIT');
+  }
+}
+
+/**
  * @} End of "ingroup database".
  */
 

=== modified file 'index.php'
--- index.php	2007-04-06 13:27:20 +0000
+++ index.php	2007-09-02 18:00:37 +0000
@@ -12,6 +12,7 @@
 require_once './includes/bootstrap.inc';
 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 
+menu_rebuild();
 $return = menu_execute_active_handler();
 
 // Menu status constants are integers; page content is a string.

=== modified file 'modules/aggregator/aggregator.module'
--- modules/aggregator/aggregator.module	2007-08-30 20:20:38 +0000
+++ modules/aggregator/aggregator.module	2007-09-02 18:00:28 +0000
@@ -111,10 +111,12 @@ function aggregator_menu() {
     'title' => 'Sources',
     'page callback' => 'aggregator_page_sources',
     'access arguments' => array('access news feeds'));
-  $items['aggregator/categories'] = array(
+  $items['aggregator/categories/%aggregator_category'] = array(
     'title' => 'Categories',
     'page callback' => 'aggregator_page_categories',
+    'page arguments' => array(1),
     'access callback' => '_aggregator_has_categories',
+    'access arguments' => array(1),
   );
   $items['aggregator/rss'] = array(
     'title' => 'RSS feed',
@@ -583,7 +585,7 @@ function aggregator_save_feed($edit) {
   }
   if ($edit['title']) {
     // The feed is being saved, save the categories as well.
-    if ($edit['category']) {
+    if (!empty($edit['category'])) {
       foreach ($edit['category'] as $cid => $value) {
         if ($value) {
           db_query('INSERT INTO {aggregator_category_feed} (fid, cid) VALUES (%d, %d)', $edit['fid'], $cid);
@@ -679,28 +681,31 @@ function aggregator_element_data($parser
   global $channel, $element, $items, $item, $image, $tag;
   switch ($element) {
     case 'ITEM':
-      if(empty($items[$item][$tag])) {
-        $items[$item][$tag] = '';
-      }
+      $items[$item] += array($tag => '');
       $items[$item][$tag] .= $data;
       break;
     case 'IMAGE':
     case 'LOGO':
+      $image += array($tag => '');
       $image[$tag] .= $data;
       break;
     case 'LINK':
       if ($data) {
+        $items[$item] += array($tag => '');
         $items[$item][$tag] .= $data;
       }
       break;
     case 'CONTENT':
+      $items[$item] += array('CONTENT' => '');
       $items[$item]['CONTENT'] .= $data;
       break;
     case 'SUMMARY':
+      $items[$item] += array('SUMMARY' => '');
       $items[$item]['SUMMARY'] .= $data;
       break;
     case 'TAGLINE':
     case 'SUBTITLE':
+      $channel += array('DESCRIPTION' => '');
       $channel['DESCRIPTION'] .= $data;
       break;
     case 'INFO':
@@ -892,15 +897,13 @@ function aggregator_parse_feed(&$data, $
     ** Resolve the items link.
     */
 
-    if ($item['LINK']) {
+    if (!empty($item['LINK'])) {
       $link = $item['LINK'];
     }
     else {
       $link = $feed['link'];
     }
-    if ($item['GUID']) {
-      $guid = $item['GUID'];
-    }
+    $guid = isset($item['GUID']) ? $item['GUID'] : '';
 
     /**
      * Atom feeds have a CONTENT and/or SUMMARY tag instead of a DESCRIPTION tag
@@ -946,7 +949,7 @@ function aggregator_parse_feed(&$data, $
     ** pass along it's ID such that we can update it if needed.
     */
 
-    if ($guid) {
+    if (!empty($guid)) {
       $entry = db_fetch_object(db_query("SELECT iid FROM {aggregator_item} WHERE fid = %d AND guid = '%s'", $feed['fid'], $guid));
     }
     else if ($link && $link != $feed['link'] && $link != $feed['url']) {
@@ -955,7 +958,7 @@ function aggregator_parse_feed(&$data, $
     else {
       $entry = db_fetch_object(db_query("SELECT iid FROM {aggregator_item} WHERE fid = %d AND title = '%s'", $feed['fid'], $title));
     }
-    aggregator_save_item(array('iid' => (isset($entry->iid)?$entry->iid:''), 'fid' => $feed['fid'], 'timestamp' => $timestamp, 'title' => $title, 'link' => $link, 'author' => (empty($item['AUTHOR'])?'':$item['AUTHOR']), 'description' => $item['DESCRIPTION'], 'guid' => $guid));
+    aggregator_save_item(array('iid' => (isset($entry->iid) ? $entry->iid:''), 'fid' => $feed['fid'], 'timestamp' => $timestamp, 'title' => $title, 'link' => $link, 'author' => (empty($item['AUTHOR'])?'':$item['AUTHOR']), 'description' => $item['DESCRIPTION'], 'guid' => $guid));
   }
 
   /*

=== modified file 'modules/block/block.module'
--- modules/block/block.module	2007-09-01 05:31:09 +0000
+++ modules/block/block.module	2007-09-02 18:06:17 +0000
@@ -256,19 +256,18 @@ function _block_rehash() {
     }
   }
 
-  db_lock_table('blocks');
-  // Remove all blocks from table.
-  db_query("DELETE FROM {blocks} WHERE theme = '%s'", $theme_key);
 
-  // Reinsert new set of blocks into table.
+  // Reinsert new set of blocks into a temporary table.
+  $temporary_table_name = db_create_table_like('block', 'blocks');
+  db_query('INSERT INTO {'. $temporary_table_name ."} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle, title, cache) SELECT module, delta, theme, status, weight, region, visibility, pages, custom, throttle, title, cache FROM blocks WHERE theme != '%s'", $theme_key);
   foreach ($blocks as $block) {
     $block += array(
       'visibility' => NULL,
       'throttle' => NULL,
     );
-    db_query("INSERT INTO {blocks} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle, title, cache) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d, '%s', %d)", $block['module'], $block['delta'], $theme_key, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle'], $block['title'], $block['cache']);
+    db_query('INSERT INTO {'. $temporary_table_name ."} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle, title, cache) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d, '%s', %d)", $block['module'], $block['delta'], $theme_key, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle'], $block['title'], $block['cache']);
   }
-  db_unlock_tables();
+  db_replace_table($temporary_table_name, 'blocks');
 
   return $blocks;
 }

=== modified file 'modules/user/user.module'
--- modules/user/user.module	2007-09-02 12:46:21 +0000
+++ modules/user/user.module	2007-09-02 18:00:48 +0000
@@ -434,6 +434,7 @@ function user_access($string, $account =
     $account = $user;
   }
 
+if (!is_object($account)) var_dump(debug_backtrace());
   // User #1 has all privileges:
   if ($account->uid == 1) {
     return TRUE;

