From 8d103a08984ac2de72d756eb5c5c8d23061ab028 Mon Sep 17 00:00:00 2001
From: Dries Buytaert <dries@buytaert.net>
Date: Sat, 26 Oct 2002 15:17:26 +0000
Subject: [PATCH] - Committed Marco's block rewrite:

   + Blocks are not longer called if not rendered: major performance
     improvement.
   + Fixed some bugs (preview option was broken, path option was broken).
   + Removed "ascii"-type blocks.
   + Added permission to for "PHP blocks"
   + ...

  NOTES:

   + You'll want to run "update.php":

       ALTER TABLE blocks DROP remove;
       ALTER TABLE blocks DROP name;

   + You'll want to update your custom modules as well as the modules in
     the contrib repository.  Block function should now read:

       function *_block($op = "list", $delta = 0) {
         if ($op == "list") {
           return array of block infos
         }
         else {
           return subject and content of $delta block
         }
       }
---
 includes/common.inc                  |   8 ++
 includes/module.inc                  |  21 ----
 includes/theme.inc                   |  12 +-
 modules/aggregator.module            |  91 +++++++++------
 modules/aggregator/aggregator.module |  91 +++++++++------
 modules/archive.module               |  25 ++--
 modules/archive/archive.module       |  25 ++--
 modules/block.module                 | 164 +++++++++++++++++----------
 modules/block/block.module           | 164 +++++++++++++++++----------
 modules/blog.module                  |  33 +++---
 modules/blog/blog.module             |  33 +++---
 modules/cloud.module                 |  17 ++-
 modules/import.module                |  91 +++++++++------
 modules/node.module                  |  16 ++-
 modules/node/node.module             |  16 ++-
 modules/poll.module                  |  27 +++--
 modules/poll/poll.module             |  27 +++--
 modules/rating.module                |  17 ++-
 modules/user.module                  |  95 +++++++++-------
 modules/user/user.module             |  95 +++++++++-------
 update.php                           |   8 +-
 21 files changed, 647 insertions(+), 429 deletions(-)

diff --git a/includes/common.inc b/includes/common.inc
index 3e3460597b3c..dc1e5027a345 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -619,6 +619,14 @@ function form_submit($value) {
   return "<input type=\"submit\" name=\"op\" value=\"". check_form($value) ."\" />\n";
 }
 
+function form_weight($title = NULL, $name = "weight", $value = 0, $delta = 10, $description = 0, $extra = 0) {
+  for ($n = (-1*$delta); $n <= $delta; $n++) {
+    $weights[$n] = $n;
+  }
+
+  return form_select($title, $name, $value, $weights, $description, $extra);
+}
+
 /**
  * Build an URL; use this functions when you must write an URL
  * for example in a form or a redirect.
diff --git a/includes/module.inc b/includes/module.inc
index d908ceb25005..7a248d2361d5 100644
--- a/includes/module.inc
+++ b/includes/module.inc
@@ -69,25 +69,4 @@ function module_hook($name, $hook) {
   return function_exists($name ."_". $hook);
 }
 
-// rehash module-exported blocks:
-function module_rehash_blocks($name) {
-  db_query("UPDATE blocks SET remove = '1' WHERE module = '$name'");
-
-  if ($blocks = module_invoke($name, "block")) {
-    foreach ($blocks as $delta => $block) {
-      foreach ($block as $item => $data) {
-        $block[$item] = addslashes($data);
-      }
-      if (!db_fetch_object(db_query("SELECT * FROM blocks WHERE module = '$name' AND name = '$block[info]'"))) {
-        db_query("INSERT INTO blocks (name, module, delta) VALUES ('$block[info]', '$name', '$delta')");
-      }
-      else {
-        db_query("UPDATE blocks SET delta = '$delta', remove = '0' WHERE module = '$name' AND name = '$block[info]'");
-      }
-    }
-  }
-
-  db_query("DELETE FROM blocks WHERE module = '$name' AND remove = '1'");
-}
-
 ?>
\ No newline at end of file
diff --git a/includes/theme.inc b/includes/theme.inc
index 62239da128cb..da4d3ca06d6e 100644
--- a/includes/theme.inc
+++ b/includes/theme.inc
@@ -123,15 +123,15 @@ function theme_init() {
 }
 
 function theme_blocks($region, &$theme) {
-  global $id, $PHP_SELF, $user;
+  global $user, $PHP_SELF;
 
-  $result = db_query("SELECT * FROM blocks WHERE (status = '1' OR custom = '1') ". ($region != "all" ? "AND region = '%s' " : "") ."ORDER BY weight, name", $region == "left" ? 0 : 1);
+  $result = db_query("SELECT * FROM blocks WHERE (status = '1' OR custom = '1') ". ($region != "all" ? "AND region = '%s' " : "") ."ORDER BY weight, module", $region == "left" ? 0 : 1);
 
   while ($result && ($block = db_fetch_object($result))) {
-    if (($block->status && (!$user->uid || !$block->custom)) || ($block->custom && $user->block[$block->name])) {
-      $blocks = module_invoke($block->module, "block");
-      if ($blocks[$block->delta]["content"]) {
-        $theme->box($blocks[$block->delta]["subject"], $blocks[$block->delta]["content"], $region);
+    if ((($block->status && (!$user->uid || !$block->custom)) || ($block->custom && $user->block[$block->module][$block->delta])) && (!$block->path || preg_match("|$block->path|", $PHP_SELF))) {
+      $block_data = module_invoke($block->module, "block", "view", $block->delta);
+      if ($block_data["content"]) {
+        $theme->box($block_data["subject"], $block_data["content"], $region);
       }
     }
   }
diff --git a/modules/aggregator.module b/modules/aggregator.module
index 364d6ccc2adb..2c640cc4f469 100644
--- a/modules/aggregator.module
+++ b/modules/aggregator.module
@@ -93,20 +93,44 @@ function import_feed_block($feed) {
   return $output;
 }
 
-function import_block() {
-  return array_merge(import_get_bundles(), import_get_feeds());
+function import_block($op, $delta) {
+  if ($op == "list") {
+    $result = db_query("SELECT * FROM bundle ORDER BY title");
+    while ($bundle = db_fetch_object($result)) {
+      $block[$bundle->bid]["info"] = "$bundle->title bundle";
+    }
+
+    $result = db_query("SELECT * FROM feed ORDER BY fid");
+    while ($feed = db_fetch_object($result)) {
+      $block[$feed->fid]["info"] = "$feed->title feed";
+    }
+
+    return $block;
+  }
+  else {
+    $feed = db_fetch_object(db_query("SELECT * FROM feed WHERE fid = '%d'", $delta));
+    if ($feed) {
+      $block["subject"] = $feed->title;
+      $block["content"] = import_feed_block($feed) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "feed", "id" => $feed->fid), "", array("title" => t("View this feed's recent news."))) ."</div></p>";
+    }
+    else {
+      // it was a bundle. this is NOT elegant
+      $bundle = db_fetch_object(db_query("SELECT * FROM bundle WHERE bid = '%d'", $delta));
+      $block["subject"] = $bundle->title;
+      $block["content"] = import_bundle_block($bundle->attributes) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "bundle", "id" => $bundle->bid), "", array("title" => t("View this bundle's recent news."))) ."</div></p>";
+    }
+
+    return $block;
+  }
 }
 
 function import_get_bundles($attributes = 0) {
   $result = db_query("SELECT * FROM bundle ORDER BY title");
 
-  $i = 0;
   while ($bundle = db_fetch_object($result)) {
-    $block[$i]["subject"] = $bundle->title;
-    $block[$i]["content"] = import_bundle_block($bundle->attributes) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "bundle", "id" => $bundle->bid), "", array("title" => t("View this bundle's recent news."))) ."</div></p>";
-    $block[$i]["info"] = "$bundle->title bundle";
-
-    $i++;
+    $block[$bundle->bid]["subject"] = $bundle->title;
+    $block[$bundle->bid]["content"] = import_bundle_block($bundle->attributes) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "bundle", "id" => $bundle->bid), "", array("title" => t("View this bundle's recent news."))) ."</div></p>";
+    $block[$bundle->bid]["info"] = "$bundle->title bundle";
   }
 
   return $block;
@@ -115,13 +139,10 @@ function import_get_bundles($attributes = 0) {
 function import_get_feeds($attributes = 0) {
   $result = db_query("SELECT * FROM feed ORDER BY fid");
 
-  $i = 0;
   while ($feed = db_fetch_object($result)) {
-    $block[$i]["subject"] = $feed->title;
-    $block[$i]["content"] = import_feed_block($feed) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "feed", "id" => $feed->fid), "", array("title" => t("View this feed's recent news."))) ."</div></p>";
-    $block[$i]["info"] = "$feed->title feed";
-
-    $i++;
+    $block[$feed->fid]["subject"] = $feed->title;
+    $block[$feed->fid]["content"] = import_feed_block($feed) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "feed", "id" => $feed->fid), "", array("title" => t("View this feed's recent news."))) ."</div></p>";
+    $block[$feed->fid]["info"] = "$feed->title feed";
   }
 
   return $block;
@@ -289,10 +310,10 @@ function import_save_bundle($edit) {
     db_query("DELETE FROM bundle WHERE bid = '%s'", $edit["bid"]);
   }
   else if ($edit["title"]) {
-    db_query("INSERT INTO bundle (title, attributes) VALUES ('%s', '%s')", $edit["title"], $edit["attributes"]);
+    // a single unique id for bundles and feeds, to use in blocks
+    $next_id = db_next_id("import");
+    db_query("INSERT INTO bundle (bid, title, attributes) VALUES ('%d', '%s', '%s')", $next_id, $edit["title"], $edit["attributes"]);
   }
-
-  module_rehash_blocks("import");
 }
 
 function import_form_feed($edit = array()) {
@@ -328,7 +349,9 @@ function import_save_feed($edit) {
     db_query("DELETE FROM item WHERE fid = '%s'", $edit["fid"]);
   }
   else if ($edit["title"]) {
-    db_query("INSERT INTO feed (title, url, attributes, refresh) VALUES ('%s', '%s', '%s', '%s')", $edit["title"], $edit["url"], $edit["attributes"], $edit["refresh"]);
+    // a single unique id for bundles and feeds, to use in blocks
+    $next_id = db_next_id("import");
+    db_query("INSERT INTO feed (fid, title, url, attributes, refresh) VALUES ('%d', '%s', '%s', '%s', '%s')", $next_id, $edit["title"], $edit["url"], $edit["attributes"], $edit["refresh"]);
   }
 }
 
@@ -694,26 +717,24 @@ function import_page_feeds() {
 function import_page_blocks($blocks) {
   global $theme;
 
-  $count = count($blocks);
-  $items = ceil($count / 3);
-  $c1 = min($items, $count);
-  $c2 = min(2 * $items, $count);
-  $c3 = $count;
-  $i = 0;
-
   $theme->header();
   $theme->box(t("News feeds"), import_page_info());
   print "<table cellpadding=\"0\" cellspacing=\"5\" border=\"0\" width=\"100%\">\n";
   print " <tr>\n";
-  print "  <td width=\"33%\" valign=\"top\">\n";
-  for ($i; $i < $c1; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]);
-  print "  </td>\n";
-  print "  <td width=\"33%\" valign=\"top\">\n";
-  for ($i; $i < $c2; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]);
-  print "  </td>\n";
-  print "  <td width=\"33%\" valign=\"top\">\n";
-  for ($i; $i < $c3; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]);
-  print "  </td>\n";
+
+  for ($t = 0; $t < 3; $t++) {
+    $i = 1;
+    print "  <td width=\"33%\" valign=\"top\">\n";
+    while ($block = each($blocks)) {
+      $theme->box($block["value"]["subject"], $block["value"]["content"]);
+      if ($i == ceil(count($blocks) / 3)) {
+        break;
+      }
+      $i++;
+    }
+    print "  </td>\n";
+  }
+
   print " </tr>\n";
   print "</table>\n";
   $theme->footer();
@@ -748,4 +769,4 @@ function import_page() {
   }
 }
 
-?>
+?>
\ No newline at end of file
diff --git a/modules/aggregator/aggregator.module b/modules/aggregator/aggregator.module
index 364d6ccc2adb..2c640cc4f469 100644
--- a/modules/aggregator/aggregator.module
+++ b/modules/aggregator/aggregator.module
@@ -93,20 +93,44 @@ function import_feed_block($feed) {
   return $output;
 }
 
-function import_block() {
-  return array_merge(import_get_bundles(), import_get_feeds());
+function import_block($op, $delta) {
+  if ($op == "list") {
+    $result = db_query("SELECT * FROM bundle ORDER BY title");
+    while ($bundle = db_fetch_object($result)) {
+      $block[$bundle->bid]["info"] = "$bundle->title bundle";
+    }
+
+    $result = db_query("SELECT * FROM feed ORDER BY fid");
+    while ($feed = db_fetch_object($result)) {
+      $block[$feed->fid]["info"] = "$feed->title feed";
+    }
+
+    return $block;
+  }
+  else {
+    $feed = db_fetch_object(db_query("SELECT * FROM feed WHERE fid = '%d'", $delta));
+    if ($feed) {
+      $block["subject"] = $feed->title;
+      $block["content"] = import_feed_block($feed) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "feed", "id" => $feed->fid), "", array("title" => t("View this feed's recent news."))) ."</div></p>";
+    }
+    else {
+      // it was a bundle. this is NOT elegant
+      $bundle = db_fetch_object(db_query("SELECT * FROM bundle WHERE bid = '%d'", $delta));
+      $block["subject"] = $bundle->title;
+      $block["content"] = import_bundle_block($bundle->attributes) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "bundle", "id" => $bundle->bid), "", array("title" => t("View this bundle's recent news."))) ."</div></p>";
+    }
+
+    return $block;
+  }
 }
 
 function import_get_bundles($attributes = 0) {
   $result = db_query("SELECT * FROM bundle ORDER BY title");
 
-  $i = 0;
   while ($bundle = db_fetch_object($result)) {
-    $block[$i]["subject"] = $bundle->title;
-    $block[$i]["content"] = import_bundle_block($bundle->attributes) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "bundle", "id" => $bundle->bid), "", array("title" => t("View this bundle's recent news."))) ."</div></p>";
-    $block[$i]["info"] = "$bundle->title bundle";
-
-    $i++;
+    $block[$bundle->bid]["subject"] = $bundle->title;
+    $block[$bundle->bid]["content"] = import_bundle_block($bundle->attributes) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "bundle", "id" => $bundle->bid), "", array("title" => t("View this bundle's recent news."))) ."</div></p>";
+    $block[$bundle->bid]["info"] = "$bundle->title bundle";
   }
 
   return $block;
@@ -115,13 +139,10 @@ function import_get_bundles($attributes = 0) {
 function import_get_feeds($attributes = 0) {
   $result = db_query("SELECT * FROM feed ORDER BY fid");
 
-  $i = 0;
   while ($feed = db_fetch_object($result)) {
-    $block[$i]["subject"] = $feed->title;
-    $block[$i]["content"] = import_feed_block($feed) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "feed", "id" => $feed->fid), "", array("title" => t("View this feed's recent news."))) ."</div></p>";
-    $block[$i]["info"] = "$feed->title feed";
-
-    $i++;
+    $block[$feed->fid]["subject"] = $feed->title;
+    $block[$feed->fid]["content"] = import_feed_block($feed) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "feed", "id" => $feed->fid), "", array("title" => t("View this feed's recent news."))) ."</div></p>";
+    $block[$feed->fid]["info"] = "$feed->title feed";
   }
 
   return $block;
@@ -289,10 +310,10 @@ function import_save_bundle($edit) {
     db_query("DELETE FROM bundle WHERE bid = '%s'", $edit["bid"]);
   }
   else if ($edit["title"]) {
-    db_query("INSERT INTO bundle (title, attributes) VALUES ('%s', '%s')", $edit["title"], $edit["attributes"]);
+    // a single unique id for bundles and feeds, to use in blocks
+    $next_id = db_next_id("import");
+    db_query("INSERT INTO bundle (bid, title, attributes) VALUES ('%d', '%s', '%s')", $next_id, $edit["title"], $edit["attributes"]);
   }
-
-  module_rehash_blocks("import");
 }
 
 function import_form_feed($edit = array()) {
@@ -328,7 +349,9 @@ function import_save_feed($edit) {
     db_query("DELETE FROM item WHERE fid = '%s'", $edit["fid"]);
   }
   else if ($edit["title"]) {
-    db_query("INSERT INTO feed (title, url, attributes, refresh) VALUES ('%s', '%s', '%s', '%s')", $edit["title"], $edit["url"], $edit["attributes"], $edit["refresh"]);
+    // a single unique id for bundles and feeds, to use in blocks
+    $next_id = db_next_id("import");
+    db_query("INSERT INTO feed (fid, title, url, attributes, refresh) VALUES ('%d', '%s', '%s', '%s', '%s')", $next_id, $edit["title"], $edit["url"], $edit["attributes"], $edit["refresh"]);
   }
 }
 
@@ -694,26 +717,24 @@ function import_page_feeds() {
 function import_page_blocks($blocks) {
   global $theme;
 
-  $count = count($blocks);
-  $items = ceil($count / 3);
-  $c1 = min($items, $count);
-  $c2 = min(2 * $items, $count);
-  $c3 = $count;
-  $i = 0;
-
   $theme->header();
   $theme->box(t("News feeds"), import_page_info());
   print "<table cellpadding=\"0\" cellspacing=\"5\" border=\"0\" width=\"100%\">\n";
   print " <tr>\n";
-  print "  <td width=\"33%\" valign=\"top\">\n";
-  for ($i; $i < $c1; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]);
-  print "  </td>\n";
-  print "  <td width=\"33%\" valign=\"top\">\n";
-  for ($i; $i < $c2; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]);
-  print "  </td>\n";
-  print "  <td width=\"33%\" valign=\"top\">\n";
-  for ($i; $i < $c3; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]);
-  print "  </td>\n";
+
+  for ($t = 0; $t < 3; $t++) {
+    $i = 1;
+    print "  <td width=\"33%\" valign=\"top\">\n";
+    while ($block = each($blocks)) {
+      $theme->box($block["value"]["subject"], $block["value"]["content"]);
+      if ($i == ceil(count($blocks) / 3)) {
+        break;
+      }
+      $i++;
+    }
+    print "  </td>\n";
+  }
+
   print " </tr>\n";
   print "</table>\n";
   $theme->footer();
@@ -748,4 +769,4 @@ function import_page() {
   }
 }
 
-?>
+?>
\ No newline at end of file
diff --git a/modules/archive.module b/modules/archive.module
index 15d61e5b66fc..d2f33c0ab700 100644
--- a/modules/archive.module
+++ b/modules/archive.module
@@ -102,14 +102,20 @@ function archive_display($original = 0) {
   return $output;
 }
 
-function archive_block() {
+function archive_block($op = "list", $delta = 0) {
   global $date;
-
-  $block[0]["subject"] = "Browse archives";
-  $block[0]["content"] = archive_display($date);
-  $block[0]["info"] = "Calendar to browse archives";
-
-  return $block;
+  if ($op == "list") {
+    $blocks[0]["info"] = t("Calendar to browse archives");
+    return $blocks;
+  }
+  else {
+    switch ($delta) {
+      case 0:
+        $block["subject"] = t("Browse archives");
+        $block["content"] = archive_display($date);
+        return $block;
+    }
+  }
 }
 
 function archive_link($type) {
@@ -169,10 +175,11 @@ function archive_page() {
       }
   }
   else {
-    $theme->box(t("Access denied"), message_access());
+    #$theme->box(t("Access denied"), message_access());
+    message_access();
   }
 
   $theme->footer();
 }
 
-?>
+?>
\ No newline at end of file
diff --git a/modules/archive/archive.module b/modules/archive/archive.module
index 15d61e5b66fc..d2f33c0ab700 100644
--- a/modules/archive/archive.module
+++ b/modules/archive/archive.module
@@ -102,14 +102,20 @@ function archive_display($original = 0) {
   return $output;
 }
 
-function archive_block() {
+function archive_block($op = "list", $delta = 0) {
   global $date;
-
-  $block[0]["subject"] = "Browse archives";
-  $block[0]["content"] = archive_display($date);
-  $block[0]["info"] = "Calendar to browse archives";
-
-  return $block;
+  if ($op == "list") {
+    $blocks[0]["info"] = t("Calendar to browse archives");
+    return $blocks;
+  }
+  else {
+    switch ($delta) {
+      case 0:
+        $block["subject"] = t("Browse archives");
+        $block["content"] = archive_display($date);
+        return $block;
+    }
+  }
 }
 
 function archive_link($type) {
@@ -169,10 +175,11 @@ function archive_page() {
       }
   }
   else {
-    $theme->box(t("Access denied"), message_access());
+    #$theme->box(t("Access denied"), message_access());
+    message_access();
   }
 
   $theme->footer();
 }
 
-?>
+?>
\ No newline at end of file
diff --git a/modules/block.module b/modules/block.module
index 555861333a90..2359f3ffa7f1 100644
--- a/modules/block.module
+++ b/modules/block.module
@@ -13,9 +13,9 @@ function block_help() {
   <p>The content of the site can be almost entirely altered through <I>boxes</I>.  Simply put, boxes are small bits of text, HTML or PHP code which will get plugged into the site just like any other block.  Boxes are typically used to add custom blocks to the site.</p>
   <p>Each box consists of a title and an associated block of text, HTML or PHP code that can be as long as you wish and that will 'render' the content of the box.</p>
   <h3>PHP boxes</h3>
-  <p>If you know how to script in PHP, PHP boxes are easy to create.  Don't worry if you're no PHP-wizard: simply use ASCII or HTML boxes instead.</p>
+  <p>If you know how to script in PHP, PHP boxes are easy to create.  Don't worry if you're no PHP-wizard: simply use HTML boxes instead.</p>
   <p>You can use any piece of PHP code to make up the content of a PHP box: this implies that you can declare and use functions, consult the SQL database, access configuration settings and much more.  A PHP box's code is stored in the database and the engine will dynamically embed the PHP code just-in-time for execution.</p>
-  <p>There are however some factors to keep in mind when using and creating PHP boxes: PHP boxes can be extremely useful and flexible, yet they can be dangerous and insecure if not properly used.  If you are not familiar with PHP, SQL or with the site engine, avoid experimenting with PHP boxes because you can - and probably will - corrupt your database or render your site unusable!  If you don't plan to do fancy stuff with boxes then you're probably better off with ASCII or HTML boxes.</p>
+  <p>There are however some factors to keep in mind when using and creating PHP boxes: PHP boxes can be extremely useful and flexible, yet they can be dangerous and insecure if not properly used.  If you are not familiar with PHP, SQL or with the site engine, avoid experimenting with PHP boxes because you can - and probably will - corrupt your database or render your site unusable!  If you don't plan to do fancy stuff with boxes then you're probably better off with HTML boxes.</p>
   <p>Remember that the code within each PHP box must be valid PHP code -- including things like correctly terminating statements with a semicolon so that the parser won't die.  It is highly recommended that you develop your boxes separately using a simple test script on top of a test database before migrating to your production environment.</p>
   <p>Note that you can use global variables such as configuration parameters within the scope of a PHP box. Also keep in mind that variables which have been given values in a PHP box will retain these values in the engine or module afterwards.</p>
   <p>You can use the <code>return</code> statement to return the actual content for your block as well.</p>
@@ -55,44 +55,86 @@ function block_link($type) {
   return $links ? $links : array();
 }
 
-function block_block() {
-  $result = db_query("SELECT * FROM boxes ORDER BY title");
-  while ($block = db_fetch_object($result)) {
-    $blocks[$block->bid]["subject"] = check_output($block->title);
-    $blocks[$block->bid]["content"] = ($block->type == 2) ? eval($block->body) : $block->body;
-    $blocks[$block->bid]["info"] = check_output($block->info);
+function block_block($op = "list", $delta = 0) {
+  if ($op == "list") {
+    $result = db_query("SELECT bid, title, info FROM boxes ORDER BY title");
+    while ($block = db_fetch_object($result)) {
+      $blocks[$block->bid]["info"] = check_output($block->info);
+    }
+    return $blocks;
+  }
+  else {
+    $block = db_fetch_object(db_query("SELECT * FROM boxes WHERE bid = '%d'", $delta));
+    $data["subject"] = check_output($block->title);
+    $data["content"] = ($block->type == 1) ? eval($block->body) : $block->body;
+    return $data;
   }
-  return $blocks;
 }
 
 function block_admin_save($edit) {
-  foreach ($edit as $key => $value) {
-    db_query("UPDATE blocks SET region = '%s', status = '%d', custom = '%d', path = '%s', weight = '%d' WHERE name = '%s'", $value["region"], $value["status"], $value["custom"], $value["path"], $value["weight"], $key);
+  foreach ($edit as $module => $blocks) {
+    foreach ($blocks as $delta => $block) {
+      db_query("UPDATE blocks SET region = '%s', status = '%d', custom = '%d', path = '%s', weight = '%d' WHERE module = '%s' AND delta = '%d'", $block["region"], $block["status"], $block["custom"], $block["path"], $block["weight"], $module, $delta);
+    }
   }
 }
 
-function block_admin_display() {
+function block_rehash() {
   $result = db_query("SELECT * FROM blocks ORDER BY weight");
+  while ($old_block = db_fetch_object($result)) {
+    $old_blocks[$old_block->module][$old_block->delta] = $old_block;
+  }
+
+  db_query("DELETE FROM blocks");
+
+  foreach (module_list() as $module) {
+    $module_blocks = module_invoke($module, "block", "list");
+    if ($module_blocks) {
+      foreach ($module_blocks as $delta => $block) {
+        $block["module"] = $module;
+        $block["delta"]  = $delta;
+        if ($old_blocks[$module][$delta]) {
+          $block["status"] = $old_blocks[$module][$delta]->status;
+          $block["weight"] = $old_blocks[$module][$delta]->weight;
+          $block["region"] = $old_blocks[$module][$delta]->region;
+          $block["path"]   = $old_blocks[$module][$delta]->path;
+          $block["custom"] = $old_blocks[$module][$delta]->custom;
+        }
+        else {
+          $block["status"] = $block["weight"] = $block["region"] = $block["custom"] = 0;
+          $block["path"]   = "";
+        }
+
+        // reinsert blocks into table
+        db_query("INSERT INTO blocks (module, delta, status, weight, region, path, custom) VALUES ('%s', '%d', '%d', '%d', '%d', '%s', '%d')", $block["module"], $block["delta"], $block["status"], $block["weight"], $block["region"], $block["path"], $block["custom"]);
+
+        $blocks[] = $block;
+      }
+    }
+  }
+
+  return $blocks;
+}
 
+function block_admin_display() {
   // Generate output:
   $output = "<table border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n";
   $output .= "<tr><th>block</th><th>module</th><th>enabled</th><th>custom</th><th>weight</th><th>region</th><th>path</th><th colspan=\"2\">operations</th></tr>\n";
 
-  while ($block = db_fetch_object($result)) {
-    $weights = array(0 => 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
-
-    $output .= '<tr>';
-    //$output .= '<td>'. la($block->name, array("mod" => "block", "op" => "view", "id" => $block->delta), "", array("title" => t("View the block details"))) .'</td>';
-    $output .= "<td>$block->name</td>";
-    $output .= '<td>'. (module_hook($block->module, "admin") ? la($block->module, array("mod" => $block->module), "", array("title" => t("Administer module"))) : $block->module) .'</td>';
-    $output .= '<td align="center">'. form_checkbox(NULL, "$block->name][status", 1, $block->status) .'</td>';
-    $output .= '<td align="center">'. form_checkbox(NULL, "$block->name][custom", 1, $block->custom) .'</td>';
-    $output .= '<td>'. form_select(NULL, "$block->name][weight", $block->weight, $weights) .'</td>';
-    $output .= '<td>'. form_select(NULL, "$block->name][region", $block->region, array("left", "right")) .'</td>';
-    $output .= '<td>'. form_textfield(NULL, "$block->name][path", $block->path, 10, 255) .'</td>';
-    if ($block->module == 'block') {
-      $output .= '<td>'. la(t("edit"), array("mod" => "block", "op" => "edit", "id" => $block->delta)) .'</td>';
-      $output .= '<td>'. la(t("delete"), array("mod" => "block", "op" => "delete", "id" => $block->delta)) .'</td>';
+  $blocks = block_rehash();
+
+  foreach ($blocks as $block) {
+    $output .= "<tr>";
+    $output .= "<td>".$block["info"]."</td>";
+    $output .= "<td>". (module_hook($block["module"], "admin") ? la($block["module"], array("mod" => $module), "", array("title" => t("Administer module"))) : $block["module"]) ."</td>";
+    $output .= "<td align=\"center\">". form_checkbox(NULL, $block["module"]."][".$block["delta"]."][status", 1, $block["status"]) ."</td>";
+    $output .= "<td align=\"center\">". form_checkbox(NULL, $block["module"]."][".$block["delta"]."][custom", 1, $block["custom"]) ."</td>";
+    $output .= "<td>". form_weight(NULL, $block["module"]."][".$block["delta"]."][weight", $block["weight"]) ."</td>";
+    $output .= "<td>". form_select(NULL, $block["module"]."][".$block["delta"]."][region", $block["region"], array("left", "right")) ."</td>";
+    $output .= "<td>". form_textfield(NULL, $block["module"]."][".$block["delta"]."][path", $block["path"], 10, 255) ."</td>";
+    if ($block["module"] == 'block') {
+      $output .= "<td>". la(t("edit"), array("mod" => "block", "op" => "edit", "id" => $block["delta"])) ."</td>";
+      $output .= "<td>". la(t("delete"), array("mod" => "block", "op" => "delete", "id" => $block["delta"])) ."</td>";
     }
     $output .= "</tr>\n";
   }
@@ -107,12 +149,20 @@ function block_admin_preview() {
 
   $result = db_query("SELECT * FROM blocks WHERE status > 0 AND region = 0 ORDER BY weight");
   $lblocks .= "<table border=\"0\" cellpadding=\"2\" cellspacing=\"2\">\n";
-  while ($block = db_fetch_object($result)) $lblocks .= " <tr><td nowrap>". ($block->status == 2 ? "<b>$block->name</b>" : $block->name) ."</td><td>$block->weight</td></tr>\n";
+  while ($block = db_fetch_object($result)) {
+    $block_data = module_invoke($block->module, "block", "list");
+    $name = $block_data[$block->delta]["info"];
+    $lblocks .= " <tr><td nowrap=\"nowrap\">". ($block->status == 2 ? "<b>$name</b>" : $name) ."</td><td>$block->weight</td></tr>\n";
+  }
   $lblocks .= "</table>\n";
 
   $result = db_query("SELECT * FROM blocks WHERE status > 0 AND region = 1 ORDER BY weight");
   $rblocks .= "<table border=\"0\" cellpadding=\"2\" cellspacing=\"2\">\n";
-  while ($block = db_fetch_object($result)) $rblocks .= " <tr><td nowrap>". ($block->status == 2 ? "<b>$block->name</b>" : $block->name) ."</td><td>$block->weight</td></tr>\n";
+  while ($block = db_fetch_object($result)) {
+    $block_data = module_invoke($block->module, "block", "list");
+    $name = $block_data[$block->delta]["info"];
+    $rblocks .= " <tr><td nowrap=\"nowrap\">". ($block->status == 2 ? "<b>$name</b>" : $name) ."</td><td>$block->weight</td></tr>\n";
+  }
   $rblocks .= "</table>\n";
 
   $output .= "<h3>layout scheme #1:</h3>\n";
@@ -124,7 +174,11 @@ function block_admin_preview() {
 
   $result = db_query("SELECT * FROM blocks WHERE status > 0 ORDER BY weight");
   $blocks .= "<table border=\"0\" cellpadding=\"2\" cellspacing=\"2\">\n";
-  while ($block = db_fetch_object($result)) $blocks .= " <tr><td nowrap>". ($block->status == 2 ? "<b>$block->name</b>" : $block->name) ."</td><td>$block->weight</td></tr>\n";
+  while ($block = db_fetch_object($result)) {
+    $block_data = module_invoke($block->module, "block", "list");
+    $name = $block_data[$block->delta]["info"];
+    $blocks .= " <tr><td nowrap=\"nowrap\">". ($block->status == 2 ? "<b>$name</b>" : $name) ."</td><td>$block->weight</td></tr>\n";
+  }
   $blocks .= "</table>\n";
 
   $output .= "<h3>layout scheme #2:</h3>\n";
@@ -144,23 +198,19 @@ function block_admin_preview() {
   print $output;
 }
 
-function block_init() {
-  foreach (module_list() as $name) {
-    module_rehash_blocks($name);
-  }
-}
-
 function block_box_get($bid) {
   return db_fetch_array(db_query("SELECT * FROM boxes WHERE bid = '%s'", $bid));
 }
 
 function block_box_form($edit = array()) {
-  $type = array(0 => "ASCII", 1 => "HTML", 2 => "PHP");
+  $type = array(0 => "HTML", 1 => "PHP");
 
-  $form .= form_textfield("Title", "title", $edit["title"], 50, 64);
+  $form = form_textfield("Title", "title", $edit["title"], 50, 64);
   $form .= form_textfield("Description", "info", $edit["info"], 50, 64);
   $form .= form_textarea("Body", "body", $edit["body"], 70, 10);
-  $form .= form_select("Type", "type", $edit["type"], $type);
+  if (user_access("create PHP content")) {
+    $form .= form_select("Type", "type", $edit["type"], $type);
+  }
 
   if ($edit["bid"]) {
     $form .= form_hidden("bid", $edit["bid"]);
@@ -172,18 +222,17 @@ function block_box_form($edit = array()) {
 }
 
 function block_box_save($edit) {
+  if (!user_access("create PHP content")) {
+    $edit["type"] = 0;
+  }
+
   if ($edit["bid"]) {
     db_query("UPDATE boxes SET title = '%s', body = '%s', info = '%s', type = '%s' WHERE bid = '%s'", $edit["title"], $edit["body"], $edit["info"], $edit["type"], $edit["bid"]);
     return "block updated.";
   }
   else {
     db_query("INSERT INTO boxes (title, body, info, type) VALUES  ('%s', '%s', '%s', '%s')", $edit["title"], $edit["body"], $edit["info"], $edit["type"]);
-    if (db_error()) {
-      return "block added.";
-    }
-    else {
-      return "failed to add block.";
-    }
+    return "block added.";
   }
 }
 
@@ -195,7 +244,7 @@ function block_box_delete($bid) {
 }
 
 function block_admin() {
-  global $op, $edit;
+  global $op, $edit, $theme;
 
   if (user_access("administer blocks")) {
 
@@ -204,9 +253,7 @@ function block_admin() {
     $links[] = la(t("preview"), array("mod" => "block", "op" => "preview"));
     $links[] = la(t("help"), array("mod" => "block", "op" => "help"));
 
-    print "<small>". implode(" &middot; ", $links) ."</small><hr />";
-
-    block_init();
+    print "<small>". $theme->links($links) ."</small><hr />";
 
     switch ($op) {
       case "help":
@@ -225,12 +272,10 @@ function block_admin() {
       case "delete":
         global $id;
         print status(block_box_delete($id));
-        block_init();
         block_admin_display();
         break;
       case "Save block":
         print status(block_box_save($edit));
-        block_init();
         block_admin_display();
         break;
       case "Save blocks":
@@ -248,27 +293,26 @@ function block_admin() {
 function block_user($type, &$edit, &$user) {
   switch ($type) {
     case "register_form":
-      $result = db_query("SELECT * FROM blocks WHERE custom = '%d' ORDER BY name", 1);
+      $result = db_query("SELECT * FROM blocks WHERE custom = '%d' ORDER BY module, delta", 1);
 
       while ($block = db_fetch_object($result)) {
-        $form .= form_hidden("block][$block->name", $block->status);
+        $form .= form_hidden("block][$block->module][$block->delta", $block->status);
       }
 
       return $form;
     case "edit_form":
-      $result = db_query("SELECT * FROM blocks WHERE custom = '%d' ORDER BY name", 1);
+      $result = db_query("SELECT * FROM blocks WHERE custom = '%d' ORDER BY module, delta", 1);
 
       while ($block = db_fetch_object($result)) {
-        $data = module_invoke($block->module, "block");
-        if ($data[$block->delta]["subject"]) {
-          $form .= "<tr><td>$block->name</td><td>". form_checkbox(NULL, "block][$block->name", 1, $user->block[$block->name]) ."</td></tr>\n";
+        $data = module_invoke($block->module, "block", "list");
+        if ($data[$block->delta]["info"]) {
+          $form .= "<tr><td>".$data[$block->delta]["info"]."</td><td>". form_checkbox(NULL, "block][$block->module][$block->delta", 1, $user->block[$block->module][$block->delta]) ."</td></tr>\n";
         }
       }
 
       if (isset($form)) {
-        return form_item(t("Block configuration"), '<table border="0" cellpadding="2" cellspacing="2">'. $form .'</table>', t("Enable the blocks you would like to see displayed in the side bars."));
+        return form_item(t("Block configuration"), "<table border=\"0\" cellpadding=\"2\" cellspacing=\"2\">". $form ."</table>", t("Enable the blocks you would like to see displayed in the side bars."));
       }
-      break;
     case "edit_validate":
       if (!$edit["block"]) {
         $edit["block"] = array();
@@ -278,4 +322,4 @@ function block_user($type, &$edit, &$user) {
   }
 }
 
-?>
+?>
\ No newline at end of file
diff --git a/modules/block/block.module b/modules/block/block.module
index 555861333a90..2359f3ffa7f1 100644
--- a/modules/block/block.module
+++ b/modules/block/block.module
@@ -13,9 +13,9 @@ function block_help() {
   <p>The content of the site can be almost entirely altered through <I>boxes</I>.  Simply put, boxes are small bits of text, HTML or PHP code which will get plugged into the site just like any other block.  Boxes are typically used to add custom blocks to the site.</p>
   <p>Each box consists of a title and an associated block of text, HTML or PHP code that can be as long as you wish and that will 'render' the content of the box.</p>
   <h3>PHP boxes</h3>
-  <p>If you know how to script in PHP, PHP boxes are easy to create.  Don't worry if you're no PHP-wizard: simply use ASCII or HTML boxes instead.</p>
+  <p>If you know how to script in PHP, PHP boxes are easy to create.  Don't worry if you're no PHP-wizard: simply use HTML boxes instead.</p>
   <p>You can use any piece of PHP code to make up the content of a PHP box: this implies that you can declare and use functions, consult the SQL database, access configuration settings and much more.  A PHP box's code is stored in the database and the engine will dynamically embed the PHP code just-in-time for execution.</p>
-  <p>There are however some factors to keep in mind when using and creating PHP boxes: PHP boxes can be extremely useful and flexible, yet they can be dangerous and insecure if not properly used.  If you are not familiar with PHP, SQL or with the site engine, avoid experimenting with PHP boxes because you can - and probably will - corrupt your database or render your site unusable!  If you don't plan to do fancy stuff with boxes then you're probably better off with ASCII or HTML boxes.</p>
+  <p>There are however some factors to keep in mind when using and creating PHP boxes: PHP boxes can be extremely useful and flexible, yet they can be dangerous and insecure if not properly used.  If you are not familiar with PHP, SQL or with the site engine, avoid experimenting with PHP boxes because you can - and probably will - corrupt your database or render your site unusable!  If you don't plan to do fancy stuff with boxes then you're probably better off with HTML boxes.</p>
   <p>Remember that the code within each PHP box must be valid PHP code -- including things like correctly terminating statements with a semicolon so that the parser won't die.  It is highly recommended that you develop your boxes separately using a simple test script on top of a test database before migrating to your production environment.</p>
   <p>Note that you can use global variables such as configuration parameters within the scope of a PHP box. Also keep in mind that variables which have been given values in a PHP box will retain these values in the engine or module afterwards.</p>
   <p>You can use the <code>return</code> statement to return the actual content for your block as well.</p>
@@ -55,44 +55,86 @@ function block_link($type) {
   return $links ? $links : array();
 }
 
-function block_block() {
-  $result = db_query("SELECT * FROM boxes ORDER BY title");
-  while ($block = db_fetch_object($result)) {
-    $blocks[$block->bid]["subject"] = check_output($block->title);
-    $blocks[$block->bid]["content"] = ($block->type == 2) ? eval($block->body) : $block->body;
-    $blocks[$block->bid]["info"] = check_output($block->info);
+function block_block($op = "list", $delta = 0) {
+  if ($op == "list") {
+    $result = db_query("SELECT bid, title, info FROM boxes ORDER BY title");
+    while ($block = db_fetch_object($result)) {
+      $blocks[$block->bid]["info"] = check_output($block->info);
+    }
+    return $blocks;
+  }
+  else {
+    $block = db_fetch_object(db_query("SELECT * FROM boxes WHERE bid = '%d'", $delta));
+    $data["subject"] = check_output($block->title);
+    $data["content"] = ($block->type == 1) ? eval($block->body) : $block->body;
+    return $data;
   }
-  return $blocks;
 }
 
 function block_admin_save($edit) {
-  foreach ($edit as $key => $value) {
-    db_query("UPDATE blocks SET region = '%s', status = '%d', custom = '%d', path = '%s', weight = '%d' WHERE name = '%s'", $value["region"], $value["status"], $value["custom"], $value["path"], $value["weight"], $key);
+  foreach ($edit as $module => $blocks) {
+    foreach ($blocks as $delta => $block) {
+      db_query("UPDATE blocks SET region = '%s', status = '%d', custom = '%d', path = '%s', weight = '%d' WHERE module = '%s' AND delta = '%d'", $block["region"], $block["status"], $block["custom"], $block["path"], $block["weight"], $module, $delta);
+    }
   }
 }
 
-function block_admin_display() {
+function block_rehash() {
   $result = db_query("SELECT * FROM blocks ORDER BY weight");
+  while ($old_block = db_fetch_object($result)) {
+    $old_blocks[$old_block->module][$old_block->delta] = $old_block;
+  }
+
+  db_query("DELETE FROM blocks");
+
+  foreach (module_list() as $module) {
+    $module_blocks = module_invoke($module, "block", "list");
+    if ($module_blocks) {
+      foreach ($module_blocks as $delta => $block) {
+        $block["module"] = $module;
+        $block["delta"]  = $delta;
+        if ($old_blocks[$module][$delta]) {
+          $block["status"] = $old_blocks[$module][$delta]->status;
+          $block["weight"] = $old_blocks[$module][$delta]->weight;
+          $block["region"] = $old_blocks[$module][$delta]->region;
+          $block["path"]   = $old_blocks[$module][$delta]->path;
+          $block["custom"] = $old_blocks[$module][$delta]->custom;
+        }
+        else {
+          $block["status"] = $block["weight"] = $block["region"] = $block["custom"] = 0;
+          $block["path"]   = "";
+        }
+
+        // reinsert blocks into table
+        db_query("INSERT INTO blocks (module, delta, status, weight, region, path, custom) VALUES ('%s', '%d', '%d', '%d', '%d', '%s', '%d')", $block["module"], $block["delta"], $block["status"], $block["weight"], $block["region"], $block["path"], $block["custom"]);
+
+        $blocks[] = $block;
+      }
+    }
+  }
+
+  return $blocks;
+}
 
+function block_admin_display() {
   // Generate output:
   $output = "<table border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n";
   $output .= "<tr><th>block</th><th>module</th><th>enabled</th><th>custom</th><th>weight</th><th>region</th><th>path</th><th colspan=\"2\">operations</th></tr>\n";
 
-  while ($block = db_fetch_object($result)) {
-    $weights = array(0 => 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
-
-    $output .= '<tr>';
-    //$output .= '<td>'. la($block->name, array("mod" => "block", "op" => "view", "id" => $block->delta), "", array("title" => t("View the block details"))) .'</td>';
-    $output .= "<td>$block->name</td>";
-    $output .= '<td>'. (module_hook($block->module, "admin") ? la($block->module, array("mod" => $block->module), "", array("title" => t("Administer module"))) : $block->module) .'</td>';
-    $output .= '<td align="center">'. form_checkbox(NULL, "$block->name][status", 1, $block->status) .'</td>';
-    $output .= '<td align="center">'. form_checkbox(NULL, "$block->name][custom", 1, $block->custom) .'</td>';
-    $output .= '<td>'. form_select(NULL, "$block->name][weight", $block->weight, $weights) .'</td>';
-    $output .= '<td>'. form_select(NULL, "$block->name][region", $block->region, array("left", "right")) .'</td>';
-    $output .= '<td>'. form_textfield(NULL, "$block->name][path", $block->path, 10, 255) .'</td>';
-    if ($block->module == 'block') {
-      $output .= '<td>'. la(t("edit"), array("mod" => "block", "op" => "edit", "id" => $block->delta)) .'</td>';
-      $output .= '<td>'. la(t("delete"), array("mod" => "block", "op" => "delete", "id" => $block->delta)) .'</td>';
+  $blocks = block_rehash();
+
+  foreach ($blocks as $block) {
+    $output .= "<tr>";
+    $output .= "<td>".$block["info"]."</td>";
+    $output .= "<td>". (module_hook($block["module"], "admin") ? la($block["module"], array("mod" => $module), "", array("title" => t("Administer module"))) : $block["module"]) ."</td>";
+    $output .= "<td align=\"center\">". form_checkbox(NULL, $block["module"]."][".$block["delta"]."][status", 1, $block["status"]) ."</td>";
+    $output .= "<td align=\"center\">". form_checkbox(NULL, $block["module"]."][".$block["delta"]."][custom", 1, $block["custom"]) ."</td>";
+    $output .= "<td>". form_weight(NULL, $block["module"]."][".$block["delta"]."][weight", $block["weight"]) ."</td>";
+    $output .= "<td>". form_select(NULL, $block["module"]."][".$block["delta"]."][region", $block["region"], array("left", "right")) ."</td>";
+    $output .= "<td>". form_textfield(NULL, $block["module"]."][".$block["delta"]."][path", $block["path"], 10, 255) ."</td>";
+    if ($block["module"] == 'block') {
+      $output .= "<td>". la(t("edit"), array("mod" => "block", "op" => "edit", "id" => $block["delta"])) ."</td>";
+      $output .= "<td>". la(t("delete"), array("mod" => "block", "op" => "delete", "id" => $block["delta"])) ."</td>";
     }
     $output .= "</tr>\n";
   }
@@ -107,12 +149,20 @@ function block_admin_preview() {
 
   $result = db_query("SELECT * FROM blocks WHERE status > 0 AND region = 0 ORDER BY weight");
   $lblocks .= "<table border=\"0\" cellpadding=\"2\" cellspacing=\"2\">\n";
-  while ($block = db_fetch_object($result)) $lblocks .= " <tr><td nowrap>". ($block->status == 2 ? "<b>$block->name</b>" : $block->name) ."</td><td>$block->weight</td></tr>\n";
+  while ($block = db_fetch_object($result)) {
+    $block_data = module_invoke($block->module, "block", "list");
+    $name = $block_data[$block->delta]["info"];
+    $lblocks .= " <tr><td nowrap=\"nowrap\">". ($block->status == 2 ? "<b>$name</b>" : $name) ."</td><td>$block->weight</td></tr>\n";
+  }
   $lblocks .= "</table>\n";
 
   $result = db_query("SELECT * FROM blocks WHERE status > 0 AND region = 1 ORDER BY weight");
   $rblocks .= "<table border=\"0\" cellpadding=\"2\" cellspacing=\"2\">\n";
-  while ($block = db_fetch_object($result)) $rblocks .= " <tr><td nowrap>". ($block->status == 2 ? "<b>$block->name</b>" : $block->name) ."</td><td>$block->weight</td></tr>\n";
+  while ($block = db_fetch_object($result)) {
+    $block_data = module_invoke($block->module, "block", "list");
+    $name = $block_data[$block->delta]["info"];
+    $rblocks .= " <tr><td nowrap=\"nowrap\">". ($block->status == 2 ? "<b>$name</b>" : $name) ."</td><td>$block->weight</td></tr>\n";
+  }
   $rblocks .= "</table>\n";
 
   $output .= "<h3>layout scheme #1:</h3>\n";
@@ -124,7 +174,11 @@ function block_admin_preview() {
 
   $result = db_query("SELECT * FROM blocks WHERE status > 0 ORDER BY weight");
   $blocks .= "<table border=\"0\" cellpadding=\"2\" cellspacing=\"2\">\n";
-  while ($block = db_fetch_object($result)) $blocks .= " <tr><td nowrap>". ($block->status == 2 ? "<b>$block->name</b>" : $block->name) ."</td><td>$block->weight</td></tr>\n";
+  while ($block = db_fetch_object($result)) {
+    $block_data = module_invoke($block->module, "block", "list");
+    $name = $block_data[$block->delta]["info"];
+    $blocks .= " <tr><td nowrap=\"nowrap\">". ($block->status == 2 ? "<b>$name</b>" : $name) ."</td><td>$block->weight</td></tr>\n";
+  }
   $blocks .= "</table>\n";
 
   $output .= "<h3>layout scheme #2:</h3>\n";
@@ -144,23 +198,19 @@ function block_admin_preview() {
   print $output;
 }
 
-function block_init() {
-  foreach (module_list() as $name) {
-    module_rehash_blocks($name);
-  }
-}
-
 function block_box_get($bid) {
   return db_fetch_array(db_query("SELECT * FROM boxes WHERE bid = '%s'", $bid));
 }
 
 function block_box_form($edit = array()) {
-  $type = array(0 => "ASCII", 1 => "HTML", 2 => "PHP");
+  $type = array(0 => "HTML", 1 => "PHP");
 
-  $form .= form_textfield("Title", "title", $edit["title"], 50, 64);
+  $form = form_textfield("Title", "title", $edit["title"], 50, 64);
   $form .= form_textfield("Description", "info", $edit["info"], 50, 64);
   $form .= form_textarea("Body", "body", $edit["body"], 70, 10);
-  $form .= form_select("Type", "type", $edit["type"], $type);
+  if (user_access("create PHP content")) {
+    $form .= form_select("Type", "type", $edit["type"], $type);
+  }
 
   if ($edit["bid"]) {
     $form .= form_hidden("bid", $edit["bid"]);
@@ -172,18 +222,17 @@ function block_box_form($edit = array()) {
 }
 
 function block_box_save($edit) {
+  if (!user_access("create PHP content")) {
+    $edit["type"] = 0;
+  }
+
   if ($edit["bid"]) {
     db_query("UPDATE boxes SET title = '%s', body = '%s', info = '%s', type = '%s' WHERE bid = '%s'", $edit["title"], $edit["body"], $edit["info"], $edit["type"], $edit["bid"]);
     return "block updated.";
   }
   else {
     db_query("INSERT INTO boxes (title, body, info, type) VALUES  ('%s', '%s', '%s', '%s')", $edit["title"], $edit["body"], $edit["info"], $edit["type"]);
-    if (db_error()) {
-      return "block added.";
-    }
-    else {
-      return "failed to add block.";
-    }
+    return "block added.";
   }
 }
 
@@ -195,7 +244,7 @@ function block_box_delete($bid) {
 }
 
 function block_admin() {
-  global $op, $edit;
+  global $op, $edit, $theme;
 
   if (user_access("administer blocks")) {
 
@@ -204,9 +253,7 @@ function block_admin() {
     $links[] = la(t("preview"), array("mod" => "block", "op" => "preview"));
     $links[] = la(t("help"), array("mod" => "block", "op" => "help"));
 
-    print "<small>". implode(" &middot; ", $links) ."</small><hr />";
-
-    block_init();
+    print "<small>". $theme->links($links) ."</small><hr />";
 
     switch ($op) {
       case "help":
@@ -225,12 +272,10 @@ function block_admin() {
       case "delete":
         global $id;
         print status(block_box_delete($id));
-        block_init();
         block_admin_display();
         break;
       case "Save block":
         print status(block_box_save($edit));
-        block_init();
         block_admin_display();
         break;
       case "Save blocks":
@@ -248,27 +293,26 @@ function block_admin() {
 function block_user($type, &$edit, &$user) {
   switch ($type) {
     case "register_form":
-      $result = db_query("SELECT * FROM blocks WHERE custom = '%d' ORDER BY name", 1);
+      $result = db_query("SELECT * FROM blocks WHERE custom = '%d' ORDER BY module, delta", 1);
 
       while ($block = db_fetch_object($result)) {
-        $form .= form_hidden("block][$block->name", $block->status);
+        $form .= form_hidden("block][$block->module][$block->delta", $block->status);
       }
 
       return $form;
     case "edit_form":
-      $result = db_query("SELECT * FROM blocks WHERE custom = '%d' ORDER BY name", 1);
+      $result = db_query("SELECT * FROM blocks WHERE custom = '%d' ORDER BY module, delta", 1);
 
       while ($block = db_fetch_object($result)) {
-        $data = module_invoke($block->module, "block");
-        if ($data[$block->delta]["subject"]) {
-          $form .= "<tr><td>$block->name</td><td>". form_checkbox(NULL, "block][$block->name", 1, $user->block[$block->name]) ."</td></tr>\n";
+        $data = module_invoke($block->module, "block", "list");
+        if ($data[$block->delta]["info"]) {
+          $form .= "<tr><td>".$data[$block->delta]["info"]."</td><td>". form_checkbox(NULL, "block][$block->module][$block->delta", 1, $user->block[$block->module][$block->delta]) ."</td></tr>\n";
         }
       }
 
       if (isset($form)) {
-        return form_item(t("Block configuration"), '<table border="0" cellpadding="2" cellspacing="2">'. $form .'</table>', t("Enable the blocks you would like to see displayed in the side bars."));
+        return form_item(t("Block configuration"), "<table border=\"0\" cellpadding=\"2\" cellspacing=\"2\">". $form ."</table>", t("Enable the blocks you would like to see displayed in the side bars."));
       }
-      break;
     case "edit_validate":
       if (!$edit["block"]) {
         $edit["block"] = array();
@@ -278,4 +322,4 @@ function block_user($type, &$edit, &$user) {
   }
 }
 
-?>
+?>
\ No newline at end of file
diff --git a/modules/blog.module b/modules/blog.module
index 0869fe19ec8e..9d698c44bb74 100644
--- a/modules/blog.module
+++ b/modules/blog.module
@@ -332,25 +332,24 @@ function blog_link($type, $node = 0, $main) {
   return $links ? $links : array();
 }
 
-function blog_block() {
+function blog_block($op = "list", $delta = 0) {
   global $user;
-
-  $result = db_query("SELECT u.uid, u.name, n.created, n.title, n.nid FROM node n LEFT JOIN users u ON n.uid = u.uid WHERE n.type = 'blog' ORDER BY n.nid DESC LIMIT 10");
-
-  if (user_access("access content")) {
-    while ($node = db_fetch_object($result)) {
-      $output .= l(check_output($node->title), array("id" => $node->nid)) ."<br />\n";
+  if ($op == "list") {
+    $blocks[0]["info"] = t("User blogs");
+    return $blocks;
+  }
+  else {
+    if (user_access("access content")) {
+      $result = db_query("SELECT u.uid, u.name, n.created, n.title, n.nid FROM node n LEFT JOIN users u ON n.uid = u.uid WHERE n.type = 'blog' ORDER BY n.nid DESC LIMIT 10");
+      while ($node = db_fetch_object($result)) {
+        $output .= l(check_output($node->title), array("id" => $node->nid)) ."<br />\n";
+      }
+      $output .= "<br /><div align=\"right\">". lm(t("more"), array("mod" => "blog"), "", array("title" => t("Read the latest blog entries."))) ."</div>";
+      $block["content"] = $output;
+      $block["subject"] = t("User blogs");
     }
-    $output .= "<br /><div align=\"right\">".lm(t("more"), array("mod" => "blog"), "", array("title" => t("Read the latest blog entries."))) ."</div>";
-    $block[0]["content"] = $output;
+    return $block;
   }
-
-
-  $block[0]["subject"] = t("User blogs");
-  $block[0]["info"] = t("User blogs");
-  $block[0]["link"] = drupal_url(array("mod" => "blog"), "module");
-
-  return $block;
 }
 
-?>
+?>
\ No newline at end of file
diff --git a/modules/blog/blog.module b/modules/blog/blog.module
index 0869fe19ec8e..9d698c44bb74 100644
--- a/modules/blog/blog.module
+++ b/modules/blog/blog.module
@@ -332,25 +332,24 @@ function blog_link($type, $node = 0, $main) {
   return $links ? $links : array();
 }
 
-function blog_block() {
+function blog_block($op = "list", $delta = 0) {
   global $user;
-
-  $result = db_query("SELECT u.uid, u.name, n.created, n.title, n.nid FROM node n LEFT JOIN users u ON n.uid = u.uid WHERE n.type = 'blog' ORDER BY n.nid DESC LIMIT 10");
-
-  if (user_access("access content")) {
-    while ($node = db_fetch_object($result)) {
-      $output .= l(check_output($node->title), array("id" => $node->nid)) ."<br />\n";
+  if ($op == "list") {
+    $blocks[0]["info"] = t("User blogs");
+    return $blocks;
+  }
+  else {
+    if (user_access("access content")) {
+      $result = db_query("SELECT u.uid, u.name, n.created, n.title, n.nid FROM node n LEFT JOIN users u ON n.uid = u.uid WHERE n.type = 'blog' ORDER BY n.nid DESC LIMIT 10");
+      while ($node = db_fetch_object($result)) {
+        $output .= l(check_output($node->title), array("id" => $node->nid)) ."<br />\n";
+      }
+      $output .= "<br /><div align=\"right\">". lm(t("more"), array("mod" => "blog"), "", array("title" => t("Read the latest blog entries."))) ."</div>";
+      $block["content"] = $output;
+      $block["subject"] = t("User blogs");
     }
-    $output .= "<br /><div align=\"right\">".lm(t("more"), array("mod" => "blog"), "", array("title" => t("Read the latest blog entries."))) ."</div>";
-    $block[0]["content"] = $output;
+    return $block;
   }
-
-
-  $block[0]["subject"] = t("User blogs");
-  $block[0]["info"] = t("User blogs");
-  $block[0]["link"] = drupal_url(array("mod" => "blog"), "module");
-
-  return $block;
 }
 
-?>
+?>
\ No newline at end of file
diff --git a/modules/cloud.module b/modules/cloud.module
index 2d42992f6e94..0847437c4962 100644
--- a/modules/cloud.module
+++ b/modules/cloud.module
@@ -167,11 +167,16 @@ function cloud_page() {
   }
 }
 
-function cloud_block() {
-  $block[0]["subject"] = t("Site cloud");
-  $block[0]["content"] = cloud_list(20) ."<br /><div align=\"right\">". lm(t("more"), array("mod" => "cloud"), "", array("title" => t("Monitor other sites in the cloud."))) ."</div>";
-  $block[0]["info"] = t("Site cloud");
-  return $block;
+function cloud_block($op = "list", $delta = 0) {
+  if ($op == "list") {
+    $blocks[0]["info"] = t("Site cloud");
+    return $blocks;
+  }
+  else {
+    $block["subject"] = t("Site cloud");
+    $block["content"] = cloud_list(20) ."<br /><div align=\"right\">". lm(t("more"), array("mod" => "cloud"), "", array("title" => t("Monitor other sites in the cloud."))) ."</div>";
+    return $block;
+  }
 }
 
 function cloud_admin() {
@@ -209,4 +214,4 @@ function cloud_admin() {
   }
 }
 
-?>
+?>
\ No newline at end of file
diff --git a/modules/import.module b/modules/import.module
index 364d6ccc2adb..2c640cc4f469 100644
--- a/modules/import.module
+++ b/modules/import.module
@@ -93,20 +93,44 @@ function import_feed_block($feed) {
   return $output;
 }
 
-function import_block() {
-  return array_merge(import_get_bundles(), import_get_feeds());
+function import_block($op, $delta) {
+  if ($op == "list") {
+    $result = db_query("SELECT * FROM bundle ORDER BY title");
+    while ($bundle = db_fetch_object($result)) {
+      $block[$bundle->bid]["info"] = "$bundle->title bundle";
+    }
+
+    $result = db_query("SELECT * FROM feed ORDER BY fid");
+    while ($feed = db_fetch_object($result)) {
+      $block[$feed->fid]["info"] = "$feed->title feed";
+    }
+
+    return $block;
+  }
+  else {
+    $feed = db_fetch_object(db_query("SELECT * FROM feed WHERE fid = '%d'", $delta));
+    if ($feed) {
+      $block["subject"] = $feed->title;
+      $block["content"] = import_feed_block($feed) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "feed", "id" => $feed->fid), "", array("title" => t("View this feed's recent news."))) ."</div></p>";
+    }
+    else {
+      // it was a bundle. this is NOT elegant
+      $bundle = db_fetch_object(db_query("SELECT * FROM bundle WHERE bid = '%d'", $delta));
+      $block["subject"] = $bundle->title;
+      $block["content"] = import_bundle_block($bundle->attributes) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "bundle", "id" => $bundle->bid), "", array("title" => t("View this bundle's recent news."))) ."</div></p>";
+    }
+
+    return $block;
+  }
 }
 
 function import_get_bundles($attributes = 0) {
   $result = db_query("SELECT * FROM bundle ORDER BY title");
 
-  $i = 0;
   while ($bundle = db_fetch_object($result)) {
-    $block[$i]["subject"] = $bundle->title;
-    $block[$i]["content"] = import_bundle_block($bundle->attributes) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "bundle", "id" => $bundle->bid), "", array("title" => t("View this bundle's recent news."))) ."</div></p>";
-    $block[$i]["info"] = "$bundle->title bundle";
-
-    $i++;
+    $block[$bundle->bid]["subject"] = $bundle->title;
+    $block[$bundle->bid]["content"] = import_bundle_block($bundle->attributes) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "bundle", "id" => $bundle->bid), "", array("title" => t("View this bundle's recent news."))) ."</div></p>";
+    $block[$bundle->bid]["info"] = "$bundle->title bundle";
   }
 
   return $block;
@@ -115,13 +139,10 @@ function import_get_bundles($attributes = 0) {
 function import_get_feeds($attributes = 0) {
   $result = db_query("SELECT * FROM feed ORDER BY fid");
 
-  $i = 0;
   while ($feed = db_fetch_object($result)) {
-    $block[$i]["subject"] = $feed->title;
-    $block[$i]["content"] = import_feed_block($feed) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "feed", "id" => $feed->fid), "", array("title" => t("View this feed's recent news."))) ."</div></p>";
-    $block[$i]["info"] = "$feed->title feed";
-
-    $i++;
+    $block[$feed->fid]["subject"] = $feed->title;
+    $block[$feed->fid]["content"] = import_feed_block($feed) ."<p><div align=\"right\">". lm(t("more"), array("mod" => "import", "op" => "feed", "id" => $feed->fid), "", array("title" => t("View this feed's recent news."))) ."</div></p>";
+    $block[$feed->fid]["info"] = "$feed->title feed";
   }
 
   return $block;
@@ -289,10 +310,10 @@ function import_save_bundle($edit) {
     db_query("DELETE FROM bundle WHERE bid = '%s'", $edit["bid"]);
   }
   else if ($edit["title"]) {
-    db_query("INSERT INTO bundle (title, attributes) VALUES ('%s', '%s')", $edit["title"], $edit["attributes"]);
+    // a single unique id for bundles and feeds, to use in blocks
+    $next_id = db_next_id("import");
+    db_query("INSERT INTO bundle (bid, title, attributes) VALUES ('%d', '%s', '%s')", $next_id, $edit["title"], $edit["attributes"]);
   }
-
-  module_rehash_blocks("import");
 }
 
 function import_form_feed($edit = array()) {
@@ -328,7 +349,9 @@ function import_save_feed($edit) {
     db_query("DELETE FROM item WHERE fid = '%s'", $edit["fid"]);
   }
   else if ($edit["title"]) {
-    db_query("INSERT INTO feed (title, url, attributes, refresh) VALUES ('%s', '%s', '%s', '%s')", $edit["title"], $edit["url"], $edit["attributes"], $edit["refresh"]);
+    // a single unique id for bundles and feeds, to use in blocks
+    $next_id = db_next_id("import");
+    db_query("INSERT INTO feed (fid, title, url, attributes, refresh) VALUES ('%d', '%s', '%s', '%s', '%s')", $next_id, $edit["title"], $edit["url"], $edit["attributes"], $edit["refresh"]);
   }
 }
 
@@ -694,26 +717,24 @@ function import_page_feeds() {
 function import_page_blocks($blocks) {
   global $theme;
 
-  $count = count($blocks);
-  $items = ceil($count / 3);
-  $c1 = min($items, $count);
-  $c2 = min(2 * $items, $count);
-  $c3 = $count;
-  $i = 0;
-
   $theme->header();
   $theme->box(t("News feeds"), import_page_info());
   print "<table cellpadding=\"0\" cellspacing=\"5\" border=\"0\" width=\"100%\">\n";
   print " <tr>\n";
-  print "  <td width=\"33%\" valign=\"top\">\n";
-  for ($i; $i < $c1; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]);
-  print "  </td>\n";
-  print "  <td width=\"33%\" valign=\"top\">\n";
-  for ($i; $i < $c2; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]);
-  print "  </td>\n";
-  print "  <td width=\"33%\" valign=\"top\">\n";
-  for ($i; $i < $c3; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]);
-  print "  </td>\n";
+
+  for ($t = 0; $t < 3; $t++) {
+    $i = 1;
+    print "  <td width=\"33%\" valign=\"top\">\n";
+    while ($block = each($blocks)) {
+      $theme->box($block["value"]["subject"], $block["value"]["content"]);
+      if ($i == ceil(count($blocks) / 3)) {
+        break;
+      }
+      $i++;
+    }
+    print "  </td>\n";
+  }
+
   print " </tr>\n";
   print "</table>\n";
   $theme->footer();
@@ -748,4 +769,4 @@ function import_page() {
   }
 }
 
-?>
+?>
\ No newline at end of file
diff --git a/modules/node.module b/modules/node.module
index d337687ad78d..8140914b121e 100644
--- a/modules/node.module
+++ b/modules/node.module
@@ -670,14 +670,18 @@ function node_admin() {
   }
 }
 
-function node_block() {
+function node_block($op = "list", $delta = 0) {
   global $theme;
+  if ($op == "list") {
+    $blocks[0]["info"] = t("Syndicate");
+    return $blocks;
+  }
+  else {
+    $block["subject"] = t("Syndicate");
+    $block["content"] = "<div align=\"center\">". lm("<img src=\"". $theme->image("xml.gif") ."\" width=\"36\" height=\"14\" border=\"0\" alt=\"XML\" />", array("mod" => "node", "op" => "feed"), "", array("title" => t("Read the XML version of this page."))) ."</div>\n";
 
-  $block[0][subject] = t("Syndicate");
-  $block[0][content] = "<div align=\"center\">". lm("<img src=\"". $theme->image("xml.gif") ."\" width=\"36\" height=\"14\" border=\"0\" alt=\"XML\" />", array("mod" => "node", "op" => "feed"), "", array("title" => t("Read the XML version of this page."))) ."</div>\n";
-  $block[0][info] = "Syndicate";
-
-  return $block;
+    return $block;
+  }
 }
 
 function node_feed($nodes = 0, $channel = array()) {
diff --git a/modules/node/node.module b/modules/node/node.module
index d337687ad78d..8140914b121e 100644
--- a/modules/node/node.module
+++ b/modules/node/node.module
@@ -670,14 +670,18 @@ function node_admin() {
   }
 }
 
-function node_block() {
+function node_block($op = "list", $delta = 0) {
   global $theme;
+  if ($op == "list") {
+    $blocks[0]["info"] = t("Syndicate");
+    return $blocks;
+  }
+  else {
+    $block["subject"] = t("Syndicate");
+    $block["content"] = "<div align=\"center\">". lm("<img src=\"". $theme->image("xml.gif") ."\" width=\"36\" height=\"14\" border=\"0\" alt=\"XML\" />", array("mod" => "node", "op" => "feed"), "", array("title" => t("Read the XML version of this page."))) ."</div>\n";
 
-  $block[0][subject] = t("Syndicate");
-  $block[0][content] = "<div align=\"center\">". lm("<img src=\"". $theme->image("xml.gif") ."\" width=\"36\" height=\"14\" border=\"0\" alt=\"XML\" />", array("mod" => "node", "op" => "feed"), "", array("title" => t("Read the XML version of this page."))) ."</div>\n";
-  $block[0][info] = "Syndicate";
-
-  return $block;
+    return $block;
+  }
 }
 
 function node_feed($nodes = 0, $channel = array()) {
diff --git a/modules/poll.module b/modules/poll.module
index 7c22e041c53b..d2ac76cbe0f9 100644
--- a/modules/poll.module
+++ b/modules/poll.module
@@ -42,19 +42,24 @@ function poll_access($op, $node) {
   }
 }
 
-function poll_block() {
-  $timestamp = db_result(db_query("SELECT MAX(created) FROM node WHERE type='poll' AND status='1' AND moderate='0'"));
-  if ($timestamp) {
-    $poll = node_load(array("type" => "poll", "created" => $timestamp, "moderate" => "0", "status" => "1"));
-    if ($poll->nid) {
-      // Poll_view dumps the output into $poll->body
-      poll_view($poll, 1, 1);
+function poll_block($op = "list", $delta = 0) {
+  if ($op == "list") {
+    $blocks[0]["info"] = t("Most recent poll");
+    return $blocks;
+  }
+  else {
+    $timestamp = db_result(db_query("SELECT MAX(created) FROM node WHERE type = 'poll' AND status = '1' AND moderate = '0'"));
+    if ($timestamp) {
+      $poll = node_load(array("type" => "poll", "created" => $timestamp, "moderate" => "0", "status" => "1"));
+      if ($poll->nid) {
+        // Poll_view dumps the output into $poll->body
+        poll_view($poll, 1, 1);
+      }
     }
+    $block["subject"] = t("Latest poll: %t", array("%t" => $poll->title));
+    $block["content"] = $poll->body;
+    return $block;
   }
-  $blocks[0][subject] = t("Latest poll: %t", array("%t" => $poll->title));
-  $blocks[0][content] = $poll->body;
-  $blocks[0][info] = t("Most recent poll");
-  return $blocks;
 }
 
 function poll_cron() {
diff --git a/modules/poll/poll.module b/modules/poll/poll.module
index 7c22e041c53b..d2ac76cbe0f9 100644
--- a/modules/poll/poll.module
+++ b/modules/poll/poll.module
@@ -42,19 +42,24 @@ function poll_access($op, $node) {
   }
 }
 
-function poll_block() {
-  $timestamp = db_result(db_query("SELECT MAX(created) FROM node WHERE type='poll' AND status='1' AND moderate='0'"));
-  if ($timestamp) {
-    $poll = node_load(array("type" => "poll", "created" => $timestamp, "moderate" => "0", "status" => "1"));
-    if ($poll->nid) {
-      // Poll_view dumps the output into $poll->body
-      poll_view($poll, 1, 1);
+function poll_block($op = "list", $delta = 0) {
+  if ($op == "list") {
+    $blocks[0]["info"] = t("Most recent poll");
+    return $blocks;
+  }
+  else {
+    $timestamp = db_result(db_query("SELECT MAX(created) FROM node WHERE type = 'poll' AND status = '1' AND moderate = '0'"));
+    if ($timestamp) {
+      $poll = node_load(array("type" => "poll", "created" => $timestamp, "moderate" => "0", "status" => "1"));
+      if ($poll->nid) {
+        // Poll_view dumps the output into $poll->body
+        poll_view($poll, 1, 1);
+      }
     }
+    $block["subject"] = t("Latest poll: %t", array("%t" => $poll->title));
+    $block["content"] = $poll->body;
+    return $block;
   }
-  $blocks[0][subject] = t("Latest poll: %t", array("%t" => $poll->title));
-  $blocks[0][content] = $poll->body;
-  $blocks[0][info] = t("Most recent poll");
-  return $blocks;
 }
 
 function poll_cron() {
diff --git a/modules/rating.module b/modules/rating.module
index ae869304e6d7..8fa5954a589e 100644
--- a/modules/rating.module
+++ b/modules/rating.module
@@ -103,11 +103,16 @@ function rating_page() {
   $theme->footer();
 }
 
-function rating_block() {
-  $block[0]["subject"] = "Top 10:<br />users";
-  $block[0]["content"] = rating_list(10);
-  $block[0]["info"] = "Top 10: users";
-  return $block;
+function rating_block($op = "list", $delta = 0) {
+  if ($op == "list") {
+    $blocks[0]["info"] = t("Top 10: users");
+    return $blocks;
+  }
+  else {
+    $block["subject"] = t("Top 10: users");
+    $block["content"] = rating_list(10);
+    return $block;
+  }
 }
 
-?>
+?>
\ No newline at end of file
diff --git a/modules/user.module b/modules/user.module
index 835b8a996000..70064130d625 100644
--- a/modules/user.module
+++ b/modules/user.module
@@ -301,54 +301,69 @@ function user_search($keys) {
   return $find;
 }
 
-function user_block() {
+function user_block($op = "list", $delta = 0) {
   global $user, $edit;
+  if ($op == "list") {
+      $blocks[0]["info"] = t("Log in");
+      $blocks[1]["info"] = t("User information");
+      $blocks[2]["info"] = t("Who's new");
 
-  if ($user->uid) {
-    // Display account settings:
-    $block[0]["subject"] = $user->name;
-
-    $output = "<div style=\"{ width: 155; }\">\n";
-
-    $links = array_merge(module_invoke_all("link", "menu.create"), array(""), module_invoke_all("link", "menu.view"), array(""), module_invoke_all("link", "menu.settings"), array(""), module_invoke_all("link", "menu.misc"));
-    $output .= @implode("<br />\n", $links);
-
-    $output .= "</div>";
-    $block[0]["content"] = $output;
+      return $blocks;
   }
   else {
-    $block[1]["subject"] = t("Log in");
-
-    $output = "<div align=\"center\">\n";
-    $output .= "<form action=\"". drupal_url(array("mod" => "user", "op" => "login"), "module") ."\" method=\"post\">\n";
-    // Save the referer.  We record where the user came from such that we
-    // can redirect him after having completed the login form.
-    if (!$edit["destination"]) $edit["destination"] = request_uri();
-    $output .= "<input name=\"edit[destination]\" type=\"hidden\" value=\"" . $edit["destination"] . "\" />";
-    $output .= "<b>". t("Username") .":</b><br /><input name=\"edit[name]\" size=\"15\" /><br />\n";
-    $output .= "<b>". t("Password") .":</b><br /><input name=\"edit[pass]\" size=\"15\" type=\"password\" /><br />\n";
-    $output .= "<input name=\"edit[remember_me]\" type=\"checkbox\" />". t("Remember me") ."<br />\n";
-    $output .= "<input name=\"edit[op]\" type=\"submit\" value=\"". t("Log in") ."\" /><br />\n";
-    $output .= "</form></div>\n";
-    if (variable_get("user_register", 1)) {
-      $output .= "&raquo; ". lm(t("Create account?"), array("mod" => "user", "op" => "register"), "", array("title" => t("Create a new user account."))) ."<br />\n";
-    }
-    $output .= "&raquo; ". lm(t("Forgot password?"), array("mod" => "user", "op" => "password"), "", array("title" => t("Request new password via e-mail.")));
+    switch ($delta) {
+      case 0:
+        if (!$user->uid) {
+          $block["subject"] = t("Log in");
+
+          $output = "<div align=\"center\">\n";
+          $output .= "<form action=\"". drupal_url(array("mod" => "user", "op" => "login"), "module") ."\" method=\"post\">\n";
+          // Save the referer.  We record where the user came from such that we
+          // can redirect him after having completed the login form.
+          if (!$edit["destination"]) $edit["destination"] = request_uri();
+          $output .= "<input name=\"edit[destination]\" type=\"hidden\" value=\"" . $edit["destination"] . "\" />";
+          $output .= "<b>". t("Username") .":</b><br /><input name=\"edit[name]\" size=\"15\" /><br />\n";
+          $output .= "<b>". t("Password") .":</b><br /><input name=\"edit[pass]\" size=\"15\" type=\"password\" /><br />\n";
+
+          if (variable_get("user_remember", 0) == 0) {
+            $output .= "<input name=\"edit[remember_me]\" type=\"checkbox\" />". t("Remember me");
+          }
+          elseif (variable_get("user_remember", 1) == 1) {
+            $output .= form_hidden("remember_me", 1);
+          }
 
-    $block[1]["content"] = $output;
-  }
+          $output .= "<br />\n<input name=\"edit[op]\" type=\"submit\" value=\"". t("Log in") ."\" /><br />\n";
+          $output .= "</form></div>\n";
+          if (variable_get("user_register", 1)) {
+            $output .= "&raquo; ". lm(t("Register"), array("mod" => "user", "op" => "register"), "", array("title" => t("Create a new user account."))) ."<br />\n";
+          }
+          $output .= "&raquo; ". lm(t("New password"), array("mod" => "user", "op" => "password"), "", array("title" => t("Request new password via e-mail.")));
 
-  $block[0]["info"] = t("User information");
-  $block[0]["link"] = drupal_url(array("mod" => "user"), "module");
+          $block["content"] = $output;
+          return $block;
+        }
+        break;
+      case 1:
+        if ($user->uid) {
+          // Display account settings:
+          $block["subject"] = $user->name;
 
-  $block[1]["info"] = t("Log in");
-  $block[1]["link"] = drupal_url(array("mod" => "user"), "module");
+          $output = "<div style=\"{ width: 155; }\">\n";
 
-  $block[2]["subject"] = t("Who's new");
-  $block[2]["info"] = t("Who's new");
-  $block[2]["content"] = user_new_users();
+          $links = array_merge(module_invoke_all("link", "menu.create"), array(""), module_invoke_all("link", "menu.view"), array(""), module_invoke_all("link", "menu.settings"), array(""), module_invoke_all("link", "menu.misc"));
+          $output .= @implode("<br />\n", $links);
 
-  return $block;
+          $output .= "</div>";
+          $block["content"] = $output;
+          return $block;
+        }
+        break;
+      case 2:
+        $block["subject"] = t("Who's new");
+        $block["content"] = user_new_users();
+        return $block;
+    }
+  }
 }
 
 function user_new_users() {
@@ -1076,6 +1091,7 @@ function user_page() {
 function user_conf_options() {
   $output .= form_select("Public registrations", "user_register", variable_get("user_register", 1), array("Only site administrators can create new user accounts.", "Visitors can create accounts and no administrator approval is required.", "Visitors can create accounts but administrator approval is required."));
   $output .= form_textfield("Password words", "user_password", variable_get("user_password", "foo,bar,guy,neo,tux,moo,sun,asm,dot,god,axe,geek,nerd,fish,hack,star,mice,warp,moon,hero,cola,girl,fish,java,perl,boss,dark,sith,jedi,drop,mojo"), 55, 256, "A comma separated list of short words that can be concatenated to generate human-readable passwords.");
+  $output .= form_select("Remember logged user", "user_remember", variable_get("user_remember", 0), array(t("User option (checkbox)"), t("Next time user visits he'll already be logged in"), t("Log user out as soon as he quits the browser")));
   $output .= form_textfield("Welcome e-mail subject", "user_mail_welcome_subject", variable_get("user_mail_welcome_subject", t("User account details for %username at %site")), 80, 180, "Customize the subject of your welcome e-mail, which is sent to new members upon registering.  Available variables are: %username, %site, %password, %uri, %uri_brief, %mailto, %date");
   $output .= form_textarea("Welcome e-mail body", "user_mail_welcome_body", variable_get("user_mail_welcome_body", t("%username,\n\nThank you for registering at %site. You may now login to %uri". drupal_url(array("mod" => "user", "op" => "login"), "module") ." using the following username and password:\n\nusername: %username\npassword: %password\n\nAfter logging in, you may wish to change your password at %uri". drupal_url(array("mod" => "user", "op" => "edit"), "module") ."\n\nYour new %site membership also enables to you to login to other Drupal powered websites (e.g. http://www.drop.org/) without registering. Just use the following Drupal ID and password:\n\nDrupal ID: %username@%uri_brief\npassword: %password\n\n\n--  %site team")), 70, 10, "Customize the body of the welcome e-mail, which is sent to new members upon registering.  Available variables are: %username, %site, %password, %uri, %uri_brief, %mailto");
   $output .= form_textfield("Forgotten password e-mail subject", "user_mail_pass_subject", variable_get("user_mail_pass_subject", t("Replacement login information for %username at %site")), 80, 180, "Customize the Subject of your forgotten password e-mail.  Available variables are: %username, %site, %password, %uri, %uri_brief, %mailto, %date");
@@ -1976,4 +1992,5 @@ function julia_user($type, $edit, &$user) {
 </pre>
   <?php
 }
+
 ?>
diff --git a/modules/user/user.module b/modules/user/user.module
index 835b8a996000..70064130d625 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -301,54 +301,69 @@ function user_search($keys) {
   return $find;
 }
 
-function user_block() {
+function user_block($op = "list", $delta = 0) {
   global $user, $edit;
+  if ($op == "list") {
+      $blocks[0]["info"] = t("Log in");
+      $blocks[1]["info"] = t("User information");
+      $blocks[2]["info"] = t("Who's new");
 
-  if ($user->uid) {
-    // Display account settings:
-    $block[0]["subject"] = $user->name;
-
-    $output = "<div style=\"{ width: 155; }\">\n";
-
-    $links = array_merge(module_invoke_all("link", "menu.create"), array(""), module_invoke_all("link", "menu.view"), array(""), module_invoke_all("link", "menu.settings"), array(""), module_invoke_all("link", "menu.misc"));
-    $output .= @implode("<br />\n", $links);
-
-    $output .= "</div>";
-    $block[0]["content"] = $output;
+      return $blocks;
   }
   else {
-    $block[1]["subject"] = t("Log in");
-
-    $output = "<div align=\"center\">\n";
-    $output .= "<form action=\"". drupal_url(array("mod" => "user", "op" => "login"), "module") ."\" method=\"post\">\n";
-    // Save the referer.  We record where the user came from such that we
-    // can redirect him after having completed the login form.
-    if (!$edit["destination"]) $edit["destination"] = request_uri();
-    $output .= "<input name=\"edit[destination]\" type=\"hidden\" value=\"" . $edit["destination"] . "\" />";
-    $output .= "<b>". t("Username") .":</b><br /><input name=\"edit[name]\" size=\"15\" /><br />\n";
-    $output .= "<b>". t("Password") .":</b><br /><input name=\"edit[pass]\" size=\"15\" type=\"password\" /><br />\n";
-    $output .= "<input name=\"edit[remember_me]\" type=\"checkbox\" />". t("Remember me") ."<br />\n";
-    $output .= "<input name=\"edit[op]\" type=\"submit\" value=\"". t("Log in") ."\" /><br />\n";
-    $output .= "</form></div>\n";
-    if (variable_get("user_register", 1)) {
-      $output .= "&raquo; ". lm(t("Create account?"), array("mod" => "user", "op" => "register"), "", array("title" => t("Create a new user account."))) ."<br />\n";
-    }
-    $output .= "&raquo; ". lm(t("Forgot password?"), array("mod" => "user", "op" => "password"), "", array("title" => t("Request new password via e-mail.")));
+    switch ($delta) {
+      case 0:
+        if (!$user->uid) {
+          $block["subject"] = t("Log in");
+
+          $output = "<div align=\"center\">\n";
+          $output .= "<form action=\"". drupal_url(array("mod" => "user", "op" => "login"), "module") ."\" method=\"post\">\n";
+          // Save the referer.  We record where the user came from such that we
+          // can redirect him after having completed the login form.
+          if (!$edit["destination"]) $edit["destination"] = request_uri();
+          $output .= "<input name=\"edit[destination]\" type=\"hidden\" value=\"" . $edit["destination"] . "\" />";
+          $output .= "<b>". t("Username") .":</b><br /><input name=\"edit[name]\" size=\"15\" /><br />\n";
+          $output .= "<b>". t("Password") .":</b><br /><input name=\"edit[pass]\" size=\"15\" type=\"password\" /><br />\n";
+
+          if (variable_get("user_remember", 0) == 0) {
+            $output .= "<input name=\"edit[remember_me]\" type=\"checkbox\" />". t("Remember me");
+          }
+          elseif (variable_get("user_remember", 1) == 1) {
+            $output .= form_hidden("remember_me", 1);
+          }
 
-    $block[1]["content"] = $output;
-  }
+          $output .= "<br />\n<input name=\"edit[op]\" type=\"submit\" value=\"". t("Log in") ."\" /><br />\n";
+          $output .= "</form></div>\n";
+          if (variable_get("user_register", 1)) {
+            $output .= "&raquo; ". lm(t("Register"), array("mod" => "user", "op" => "register"), "", array("title" => t("Create a new user account."))) ."<br />\n";
+          }
+          $output .= "&raquo; ". lm(t("New password"), array("mod" => "user", "op" => "password"), "", array("title" => t("Request new password via e-mail.")));
 
-  $block[0]["info"] = t("User information");
-  $block[0]["link"] = drupal_url(array("mod" => "user"), "module");
+          $block["content"] = $output;
+          return $block;
+        }
+        break;
+      case 1:
+        if ($user->uid) {
+          // Display account settings:
+          $block["subject"] = $user->name;
 
-  $block[1]["info"] = t("Log in");
-  $block[1]["link"] = drupal_url(array("mod" => "user"), "module");
+          $output = "<div style=\"{ width: 155; }\">\n";
 
-  $block[2]["subject"] = t("Who's new");
-  $block[2]["info"] = t("Who's new");
-  $block[2]["content"] = user_new_users();
+          $links = array_merge(module_invoke_all("link", "menu.create"), array(""), module_invoke_all("link", "menu.view"), array(""), module_invoke_all("link", "menu.settings"), array(""), module_invoke_all("link", "menu.misc"));
+          $output .= @implode("<br />\n", $links);
 
-  return $block;
+          $output .= "</div>";
+          $block["content"] = $output;
+          return $block;
+        }
+        break;
+      case 2:
+        $block["subject"] = t("Who's new");
+        $block["content"] = user_new_users();
+        return $block;
+    }
+  }
 }
 
 function user_new_users() {
@@ -1076,6 +1091,7 @@ function user_page() {
 function user_conf_options() {
   $output .= form_select("Public registrations", "user_register", variable_get("user_register", 1), array("Only site administrators can create new user accounts.", "Visitors can create accounts and no administrator approval is required.", "Visitors can create accounts but administrator approval is required."));
   $output .= form_textfield("Password words", "user_password", variable_get("user_password", "foo,bar,guy,neo,tux,moo,sun,asm,dot,god,axe,geek,nerd,fish,hack,star,mice,warp,moon,hero,cola,girl,fish,java,perl,boss,dark,sith,jedi,drop,mojo"), 55, 256, "A comma separated list of short words that can be concatenated to generate human-readable passwords.");
+  $output .= form_select("Remember logged user", "user_remember", variable_get("user_remember", 0), array(t("User option (checkbox)"), t("Next time user visits he'll already be logged in"), t("Log user out as soon as he quits the browser")));
   $output .= form_textfield("Welcome e-mail subject", "user_mail_welcome_subject", variable_get("user_mail_welcome_subject", t("User account details for %username at %site")), 80, 180, "Customize the subject of your welcome e-mail, which is sent to new members upon registering.  Available variables are: %username, %site, %password, %uri, %uri_brief, %mailto, %date");
   $output .= form_textarea("Welcome e-mail body", "user_mail_welcome_body", variable_get("user_mail_welcome_body", t("%username,\n\nThank you for registering at %site. You may now login to %uri". drupal_url(array("mod" => "user", "op" => "login"), "module") ." using the following username and password:\n\nusername: %username\npassword: %password\n\nAfter logging in, you may wish to change your password at %uri". drupal_url(array("mod" => "user", "op" => "edit"), "module") ."\n\nYour new %site membership also enables to you to login to other Drupal powered websites (e.g. http://www.drop.org/) without registering. Just use the following Drupal ID and password:\n\nDrupal ID: %username@%uri_brief\npassword: %password\n\n\n--  %site team")), 70, 10, "Customize the body of the welcome e-mail, which is sent to new members upon registering.  Available variables are: %username, %site, %password, %uri, %uri_brief, %mailto");
   $output .= form_textfield("Forgotten password e-mail subject", "user_mail_pass_subject", variable_get("user_mail_pass_subject", t("Replacement login information for %username at %site")), 80, 180, "Customize the Subject of your forgotten password e-mail.  Available variables are: %username, %site, %password, %uri, %uri_brief, %mailto, %date");
@@ -1976,4 +1992,5 @@ function julia_user($type, $edit, &$user) {
 </pre>
   <?php
 }
+
 ?>
diff --git a/update.php b/update.php
index 646615de0048..a0a055c45754 100644
--- a/update.php
+++ b/update.php
@@ -54,7 +54,8 @@
   "2002-09-15" => "update_39",
   "2002-09-17" => "update_40",
   "2002-10-13" => "update_41",
-  "2002-10-17" => "update_42"
+  "2002-10-17" => "update_42",
+  "2002-10-17" => "update_43"
 );
 
 // Update functions
@@ -617,6 +618,11 @@ function update_42() {
   update_sql("DROP TABLE referrer");
 }
 
+function update_43() {
+  update_sql("ALTER TABLE blocks DROP remove");
+  update_sql("ALTER TABLE blocks DROP name");
+}
+
 function update_upgrade3() {
   update_sql("INSERT INTO system VALUES ('archive.module','archive','module','',1)");
   update_sql("INSERT INTO system VALUES ('block.module','block','module','',1)");
-- 
GitLab