diff --git a/account.php b/account.php
index babbd592100572abb2ed958ac6cd036c85cdc553..7035a49a23f4c6315c617f3476f8c4d50a51bf6a 100644
--- a/account.php
+++ b/account.php
@@ -24,7 +24,7 @@ function account_email() {
 
 function account_create($error = "") {
   global $theme;
-  
+
   if ($error) {
     $output .= "<P><FONT COLOR=\"red\">". t("Failed to create account") .": ". check_output($error) .".</FONT></P>\n";
     watchdog("account", "failed to create account: $error.");
diff --git a/database/database.mysql b/database/database.mysql
index bdb675fbf95bf94f8b8ec63499234b2075e2f404..9e9984bd40ceea32d50f1ddea0d39c000cbb9a53 100644
--- a/database/database.mysql
+++ b/database/database.mysql
@@ -1,12 +1,4 @@
-# MySQL dump 7.1
-#
-# Host: localhost    Database: drop
-#--------------------------------------------------------
-# Server version  3.22.32
-
-#
-# Table structure for table 'access'
-#
+
 DROP TABLE IF EXISTS access;
 CREATE TABLE access (
   id tinyint(10) DEFAULT '0' NOT NULL auto_increment,
@@ -17,9 +9,6 @@ CREATE TABLE access (
   PRIMARY KEY (id)
 );
 
-#
-# Table structure for table 'blocks'
-#
 DROP TABLE IF EXISTS blocks;
 CREATE TABLE blocks (
   name varchar(64) DEFAULT '' NOT NULL,
@@ -32,9 +21,6 @@ CREATE TABLE blocks (
   PRIMARY KEY (name)
 );
 
-#
-# Table structure for table 'book'
-#
 DROP TABLE IF EXISTS book;
 CREATE TABLE book (
   lid int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
@@ -43,12 +29,11 @@ CREATE TABLE book (
   section int(10) DEFAULT '0' NOT NULL,
   parent int(10) DEFAULT '0' NOT NULL,
   weight tinyint(3) DEFAULT '0' NOT NULL,
+  pid int(10) DEFAULT '0' NOT NULL,
+  log text NOT NULL,
   PRIMARY KEY (lid)
 );
 
-#
-# Table structure for table 'boxes'
-#
 DROP TABLE IF EXISTS boxes;
 CREATE TABLE boxes (
   id tinyint(4) DEFAULT '0' NOT NULL auto_increment,
@@ -62,9 +47,15 @@ CREATE TABLE boxes (
   PRIMARY KEY (id)
 );
 
-#
-# Table structure for table 'category'
-#
+DROP TABLE IF EXISTS bundle;
+CREATE TABLE bundle (
+  bid int(11) DEFAULT '0' NOT NULL auto_increment,
+  title varchar(255) DEFAULT '' NOT NULL,
+  attributes varchar(255) DEFAULT '' NOT NULL,
+  UNIQUE title (title),
+  PRIMARY KEY (bid)
+);
+
 DROP TABLE IF EXISTS category;
 CREATE TABLE category (
   cid int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
@@ -80,9 +71,6 @@ CREATE TABLE category (
   PRIMARY KEY (cid)
 );
 
-#
-# Table structure for table 'channel'
-#
 DROP TABLE IF EXISTS channel;
 CREATE TABLE channel (
   id int(11) DEFAULT '0' NOT NULL auto_increment,
@@ -97,9 +85,15 @@ CREATE TABLE channel (
   PRIMARY KEY (id)
 );
 
-#
-# Table structure for table 'comments'
-#
+DROP TABLE IF EXISTS collection;
+CREATE TABLE collection (
+  cid int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
+  name varchar(32) DEFAULT '' NOT NULL,
+  types varchar(128) DEFAULT '' NOT NULL,
+  UNIQUE name (name),
+  PRIMARY KEY (cid)
+);
+
 DROP TABLE IF EXISTS comments;
 CREATE TABLE comments (
   cid int(6) DEFAULT '0' NOT NULL auto_increment,
@@ -118,9 +112,6 @@ CREATE TABLE comments (
   KEY lid (lid)
 );
 
-#
-# Table structure for table 'cvs'
-#
 DROP TABLE IF EXISTS cvs;
 CREATE TABLE cvs (
   user varchar(32) DEFAULT '' NOT NULL,
@@ -130,9 +121,6 @@ CREATE TABLE cvs (
   timestamp int(11) DEFAULT '0' NOT NULL
 );
 
-#
-# Table structure for table 'diaries'
-#
 DROP TABLE IF EXISTS diaries;
 CREATE TABLE diaries (
   id int(5) DEFAULT '0' NOT NULL auto_increment,
@@ -142,9 +130,51 @@ CREATE TABLE diaries (
   PRIMARY KEY (id)
 );
 
-#
-# Table structure for table 'forum'
-#
+DROP TABLE IF EXISTS diary;
+CREATE TABLE diary (
+  lid int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
+  nid int(10) unsigned DEFAULT '0' NOT NULL,
+  body text NOT NULL,
+  PRIMARY KEY (lid)
+);
+
+DROP TABLE IF EXISTS entry;
+CREATE TABLE entry (
+  eid int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
+  name varchar(32) DEFAULT '' NOT NULL,
+  attributes varchar(255) DEFAULT '' NOT NULL,
+  collection varchar(32) DEFAULT '' NOT NULL,
+  UNIQUE name (name,collection),
+  PRIMARY KEY (eid)
+);
+
+DROP TABLE IF EXISTS feed;
+CREATE TABLE feed (
+  fid int(11) DEFAULT '0' NOT NULL auto_increment,
+  title varchar(255) DEFAULT '' NOT NULL,
+  link varchar(255) DEFAULT '' NOT NULL,
+  refresh int(11),
+  uncache int(11),
+  timestamp int(11),
+  attributes varchar(255) DEFAULT '' NOT NULL,
+  UNIQUE title (title),
+  UNIQUE link (link),
+  PRIMARY KEY (fid)
+);
+
+DROP TABLE IF EXISTS file;
+CREATE TABLE file (
+  lid int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
+  nid int(10) unsigned DEFAULT '0' NOT NULL,
+  version varchar(10) DEFAULT '' NOT NULL,
+  url varchar(255) DEFAULT '' NOT NULL,
+  downloads int(10) unsigned DEFAULT '0' NOT NULL,
+  abstract text NOT NULL,
+  description text NOT NULL,
+  homepage varchar(255) DEFAULT '' NOT NULL,
+  PRIMARY KEY (lid)
+);
+
 DROP TABLE IF EXISTS forum;
 CREATE TABLE forum (
   lid int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
@@ -153,31 +183,25 @@ CREATE TABLE forum (
   PRIMARY KEY (lid)
 );
 
-#
-# Table structure for table 'headlines'
-#
-DROP TABLE IF EXISTS headlines;
-CREATE TABLE headlines (
-  id int(11) DEFAULT '0' NOT NULL,
+DROP TABLE IF EXISTS item;
+CREATE TABLE item (
+  iid int(11) DEFAULT '0' NOT NULL auto_increment,
+  fid int(11) DEFAULT '0' NOT NULL,
   title varchar(255) DEFAULT '' NOT NULL,
   link varchar(255) DEFAULT '' NOT NULL,
-  number int(3) DEFAULT '0' NOT NULL,
-  UNIQUE title (title),
-  UNIQUE link (link)
+  author varchar(255) DEFAULT '' NOT NULL,
+  description text NOT NULL,
+  timestamp int(11),
+  attributes varchar(255) DEFAULT '' NOT NULL,
+  PRIMARY KEY (iid)
 );
 
-#
-# Table structure for table 'layout'
-#
 DROP TABLE IF EXISTS layout;
 CREATE TABLE layout (
   user int(11) DEFAULT '0' NOT NULL,
   block varchar(64) DEFAULT '' NOT NULL
 );
 
-#
-# Table structure for table 'locales'
-#
 DROP TABLE IF EXISTS locales;
 CREATE TABLE locales (
   id int(11) DEFAULT '0' NOT NULL auto_increment,
@@ -194,24 +218,16 @@ CREATE TABLE locales (
   PRIMARY KEY (id)
 );
 
-#
-# Table structure for table 'modules'
-#
 DROP TABLE IF EXISTS modules;
 CREATE TABLE modules (
   name varchar(64) DEFAULT '' NOT NULL,
   PRIMARY KEY (name)
 );
 
-#
-# Table structure for table 'node'
-#
 DROP TABLE IF EXISTS node;
 CREATE TABLE node (
   nid int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
   lid int(10) DEFAULT '0' NOT NULL,
-  pid int(10) DEFAULT '0' NOT NULL,
-  log text NOT NULL,
   type varchar(16) DEFAULT '' NOT NULL,
   title varchar(128) DEFAULT '' NOT NULL,
   score int(11) DEFAULT '0' NOT NULL,
@@ -219,12 +235,14 @@ CREATE TABLE node (
   author int(6) DEFAULT '0' NOT NULL,
   status int(4) DEFAULT '1' NOT NULL,
   timestamp int(11) DEFAULT '0' NOT NULL,
-  cid int(10) unsigned DEFAULT '0' NOT NULL,
-  tid int(10) unsigned DEFAULT '0' NOT NULL,
   comment int(2) DEFAULT '1' NOT NULL,
   promote int(2) DEFAULT '1' NOT NULL,
   moderate text NOT NULL,
   users text NOT NULL,
+  timestamp_posted int(11) DEFAULT '0' NOT NULL,
+  timestamp_queued int(11) DEFAULT '0' NOT NULL,
+  timestamp_hidden int(11) DEFAULT '0' NOT NULL,
+  attributes varchar(255) DEFAULT '' NOT NULL,
   KEY type (lid,type),
   KEY author (author),
   KEY title (title,type),
@@ -233,9 +251,6 @@ CREATE TABLE node (
   KEY status (status)
 );
 
-#
-# Table structure for table 'page'
-#
 DROP TABLE IF EXISTS page;
 CREATE TABLE page (
   lid int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
@@ -245,9 +260,7 @@ CREATE TABLE page (
   PRIMARY KEY (lid)
 );
 
-#
-# Table structure for table 'poll'
-#
+DROP TABLE IF EXISTS poll;
 CREATE TABLE poll (
   lid int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
   nid int(10) unsigned DEFAULT '0' NOT NULL,
@@ -257,9 +270,7 @@ CREATE TABLE poll (
   PRIMARY KEY (lid)
 );
 
-#
-# Table structure for table 'poll_choices'
-#
+DROP TABLE IF EXISTS poll_choices;
 CREATE TABLE poll_choices (
   chid int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
   nid int(10) unsigned DEFAULT '0' NOT NULL,
@@ -269,9 +280,6 @@ CREATE TABLE poll_choices (
   PRIMARY KEY (chid)
 );
 
-#
-# Table structure for table 'rating'
-#
 DROP TABLE IF EXISTS rating;
 CREATE TABLE rating (
   user int(6) DEFAULT '0' NOT NULL,
@@ -280,9 +288,6 @@ CREATE TABLE rating (
   PRIMARY KEY (user)
 );
 
-#
-# Table structure for table 'story'
-#
 DROP TABLE IF EXISTS story;
 CREATE TABLE story (
   lid int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
@@ -292,36 +297,16 @@ CREATE TABLE story (
   PRIMARY KEY (lid)
 );
 
-#
-# Table structure for table 'testac'
-#
-DROP TABLE IF EXISTS testac;
-CREATE TABLE testac (
-  object_id int(11),
-  object_title varchar(64)
-);
-
-#
-# Table structure for table 'testad'
-#
-DROP TABLE IF EXISTS testad;
-CREATE TABLE testad (
-  object_id int(11),
-  object_title varchar(64)
-);
-
-#
-# Table structure for table 'testae'
-#
-DROP TABLE IF EXISTS testae;
-CREATE TABLE testae (
-  object_id int(11),
-  object_title varchar(64)
+DROP TABLE IF EXISTS tag;
+CREATE TABLE tag (
+  tid int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
+  name varchar(32) DEFAULT '' NOT NULL,
+  attributes varchar(255) DEFAULT '' NOT NULL,
+  collections varchar(32) DEFAULT '' NOT NULL,
+  UNIQUE name (name,collections),
+  PRIMARY KEY (tid)
 );
 
-#
-# Table structure for table 'topic'
-#
 DROP TABLE IF EXISTS topic;
 CREATE TABLE topic (
   tid int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
@@ -332,9 +317,6 @@ CREATE TABLE topic (
   PRIMARY KEY (tid)
 );
 
-#
-# Table structure for table 'users'
-#
 DROP TABLE IF EXISTS users;
 CREATE TABLE users (
   id int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
@@ -362,9 +344,6 @@ CREATE TABLE users (
   PRIMARY KEY (id)
 );
 
-#
-# Table structure for table 'variable'
-#
 DROP TABLE IF EXISTS variable;
 CREATE TABLE variable (
   name varchar(32) DEFAULT '' NOT NULL,
@@ -372,15 +351,11 @@ CREATE TABLE variable (
   PRIMARY KEY (name)
 );
 
-#
-# Table structure for table 'watchdog'
-#
 DROP TABLE IF EXISTS watchdog;
 CREATE TABLE watchdog (
   id int(5) DEFAULT '0' NOT NULL auto_increment,
   user int(6) DEFAULT '0' NOT NULL,
   type varchar(16) DEFAULT '' NOT NULL,
-  link varchar(16) DEFAULT '' NOT NULL,
   message varchar(255) DEFAULT '' NOT NULL,
   location varchar(128) DEFAULT '' NOT NULL,
   hostname varchar(128) DEFAULT '' NOT NULL,
diff --git a/includes/comment.inc b/includes/comment.inc
index 9b0bd321985d8d3fc91384dc370cc951ed384020..cf49b49e6906fe4237a8c8e59ff70a094f151b9c 100644
--- a/includes/comment.inc
+++ b/includes/comment.inc
@@ -71,7 +71,7 @@ function comment_form($edit) {
     $form .= form_submit(t("Preview comment"));
     $form .= form_submit(t("Post comment"));
   }
-  
+
   return form($REQUEST_URL, $form);
 }
 
@@ -230,7 +230,7 @@ function comment_thread_min($cid, $threshold) {
 
   while ($comment = db_fetch_object($result)) {
     print "<UL>";
-    print " <LI>". comment_view($comment) ."</LI>\n";
+    print comment_view($comment);
     comment_thread_min($comment->cid, $threshold);
     print "</UL>";
   }
diff --git a/includes/node.inc b/includes/node.inc
index 056268c63e5933a78db01e185c85332b3bc95079..73e4526ab10da584bf02738274882d5487ad17dd 100644
--- a/includes/node.inc
+++ b/includes/node.inc
@@ -63,7 +63,7 @@ function node_get_comments($nid) {
 }
 
 function node_save($node, $filter) {
-  $rows = array(nid, pid, lid, cid, tid, log, type, title, score, votes, author, status, comment, promote, moderate, attributes, timestamp, timestamp_posted, timestamp_queued, timestamp_hidden);
+  $rows = array(nid, lid, cid, tid, type, title, score, votes, author, status, comment, promote, moderate, attributes, timestamp, timestamp_posted, timestamp_queued, timestamp_hidden);
 
   if ($node[nid] > 0) {
     $n = node_get_object(array("nid" => $node[nid]));
@@ -82,7 +82,8 @@ function node_save($node, $filter) {
 
     if ($u1) db_query("UPDATE node SET ". implode(", ", $u1) ." WHERE nid = '$node[nid]'");
     if ($u2) db_query("UPDATE $n->type SET ". implode(", ", $u2) ." WHERE nid = '$node[nid]'");
-    if ($n->pid && ($node[status] == node_status("posted"))) db_query("UPDATE node SET status = '". node_status("expired") ."' WHERE nid = '$n->pid'");
+
+    if ($node[nid]) module_invoke($n->type, "update", node_get_object(array(nid => $n->nid)));
 
     return $node[nid];
   }
@@ -123,9 +124,6 @@ function node_save($node, $filter) {
         if ($result && $lid = db_insert_id()) {
           $result = db_query("UPDATE node SET lid = '$lid' WHERE nid = '$nid'");
           if ($result) {
-            if (($node[pid]) && ($node[status] == node_status("posted"))) {
-              db_query("UPDATE node SET status = '". node_status(expired) ."' WHERE nid = '$node[pid]'");
-            }
             watchdog("special", "node: added $filter[type] '$node[title]'");
           }
           else {
@@ -142,6 +140,8 @@ function node_save($node, $filter) {
       }
     }
 
+    if ($nid) module_invoke($filter[type], "insert", node_get_object(array(nid => $nid)));
+
     return $nid;
   }
 }
@@ -222,10 +222,9 @@ function node_attributes_save($type, $edit) {
 }
 
 function node_attributes_view($string) {
-  foreach (explode(",", $string) as $data) {
-    $entry = explode("=", $data);
-    if ($entry[0] && $entry[1]) {
-      $array[] = "<a href=\"?$entry[0]=$entry[1]\">$entry[1]</a>";
+  foreach (explode(",", $string) as $attribute) {
+    if ($attribute = trim($attribute)) {
+      $array[] = "<a href=\"?meta=". urlencode($attribute) ."\">$attribute</a>";
     }
   }
   return $array ? $array : array();
diff --git a/index.php b/index.php
index c4fad109387f216d8a4584a55867da72822a3f78..fcdd9df6e824e34897dc58b9b0dabf3073392f66 100644
--- a/index.php
+++ b/index.php
@@ -4,13 +4,7 @@
 
 page_header();
 
-foreach(explode("&", $QUERY_STRING) as $attribute) {
-  if ($attribute) $query .= "attributes LIKE '%". check_input($attribute) ."%' AND ";
-}
-
-$query = !$date ? $query : "";
-
-$result = db_query("SELECT nid, type FROM node WHERE $query promote = '1' AND status = '". node_status("posted") ."' AND timestamp <= '". ($date > 0 ? check_input($date) : time()) ."' ORDER BY timestamp DESC LIMIT ". ($user->nodes ? $user->nodes : variable_get(default_nodes_main, 10)));
+$result = db_query("SELECT nid, type FROM node WHERE ". ($meta ? "attributes LIKE '%". check_input($meta) ."%' AND " : "") ." promote = '1' AND status = '". node_status("posted") ."' AND timestamp <= '". ($date > 0 ? check_input($date) : time()) ."' ORDER BY timestamp DESC LIMIT ". ($user->nodes ? $user->nodes : variable_get(default_nodes_main, 10)));
 
 $theme->header();
 while ($node = db_fetch_object($result)) {
diff --git a/modules/account.module b/modules/account.module
index 3ef4632e372c223c4f1ccd3f962a0e19decf236a..fe654f5a6e9a84c5ffb40c06d7a25f8d0621feb4 100644
--- a/modules/account.module
+++ b/modules/account.module
@@ -169,36 +169,36 @@ function account_save($edit, &$name) {
       }
     }
     db_query("UPDATE users SET $query access = '' WHERE userid = '$name'");
-  
+
     if ($edit[access]) {
       foreach ($edit[access] as $key=>$value) {
         $account = user_load($name);
         db_query("UPDATE users SET access = '". field_set($account->access, $value, 1) ."' WHERE id = $account->id");
       }
     }
-  
+
     watchdog("account", "account: modified user '$name'");
   }
   else {
     $edit[userid] = trim($edit[userid]);
     $edit[real_email] = trim($edit[real_email]);
     $edit[name] = $edit[realname];
-  
+
     if ($error = account_validate($edit)) {
       return $error;
     }
     else {
       $edit[passwd] = account_password();
       $edit[hash] = substr(md5("$edit[userid]. ". time()), 0, 12);
-  
+
       $user = user_save("", array("userid" => $edit[userid], "real_email" => $edit[real_email], "passwd" => $edit[passwd], "status" => 1, "hash" => $edit[hash]));
-  
+
       $link = path_uri() ."account.php?op=confirm&name=$edit[userid]&hash=$edit[hash]";
       $subject = strtr(t("Account details for %a"), array("%a" => variable_get(site_name, "drupal")));
       $message = strtr(t("%a,\n\n\nsomeone signed up for a user account on %b and supplied this e-mail address as their contact.  If it wasn't you, don't get your panties in a knot and simply ignore this mail.  If this was you, you will have to confirm your account first or you will not be able to login.  To confirm your account visit the URL below:\n\n   %c\n\nOnce confirmed you can login using the following username and password:\n\n   username: %a\n   password: %d\n\n\n-- %b team\n"), array("%a" => $edit[userid], "%b" => variable_get(site_name, "drupal"), "%c" => $link, "%d" => $edit[passwd]));
-  
+
       watchdog("account", "new account: `$edit[userid]' &lt;$edit[real_email]&gt;");
-  
+
       mail($edit[real_email], $subject, $message, "From: noreply");
       $name = $edit[userid];
     }
diff --git a/modules/book.module b/modules/book.module
index 8d226800dc6754fd8198f331c6fa4d2b405f105c..87e6bff58c2fd5ba5244a4f809dec4eb2516799d 100644
--- a/modules/book.module
+++ b/modules/book.module
@@ -116,10 +116,8 @@ function book_form($edit = array()) {
   $form .= form_hidden(userid, $edit[userid]);
   $form .= form_textfield(t("Subject"), "title", $edit[title], 50, 64);
 
-  if ($edit[pid]) {
-    $node = node_get_object(array("nid" => $edit[pid]));
-    $form .= form_item(t("Parent"), "<A HREF=\"node.php?id=$node->id\">". check_output($node->title) ."</A>", t("The parent subject or category the page belongs in."));
-    $form .= form_hidden("parent", $edit[parent]);
+  if ($edit[pid] > 0) {
+    $form .= form_hidden("pid", $edit[pid]);
   }
   else {
     $form .= form_select(t("Parent"), "parent", $edit[parent], book_toc(), t("The parent subject or category the page belongs in."));
@@ -133,11 +131,10 @@ function book_form($edit = array()) {
   }
 
   if ($edit[nid] > 0) {
-    $form .= form_hidden("pid", $edit[pid]);
     $form .= form_hidden("nid", $edit[nid]);
   }
 
-  if (!$edit[title]) {
+  if ($edit && !$edit[title]) {
     $form .= "<FONT COLOR=\"red\">". t("Warning: you did not supply a title.") ."</FONT><P>\n";
     $form .= form_submit(t("Preview"));
   }
@@ -153,13 +150,31 @@ function book_save($edit) {
   global $status, $user;
 
   if (!$edit[nid]) {
-    node_save($edit, array(author => $user->id, body, comment => variable_get("book_comment", 0), log, moderate => variable_get("book_moderate", ""), parent, promote => variable_get("book_promote", 0), score => 0, status => variable_get("book_status", $status[queued]), timestamp => time(), title, type => "book", votes => 0, weight));
+    node_save($edit, array(author => $user->id, body, comment => variable_get("book_comment", 0), log, moderate => variable_get("book_moderate", ""), parent, pid, promote => variable_get("book_promote", 0), score => 0, status => variable_get("book_status", $status[queued]), timestamp => time(), title, type => "book", votes => 0, weight));
   }
   else if (user_access($user)) {
     node_save($edit, array(body, log, parent, title, type => "book", weight));
   }
 }
 
+function book_delete($node) {
+  if ($node->pid && $node->status == node_status("posted")) {
+    db_query("UPDATE node SET status = '". node_status("posted") ."' WHERE nid = '$node->pid'");
+  }
+}
+
+function book_insert($node) {
+  if ($node->pid && $node->status == node_status("posted")) {
+    db_query("UPDATE node SET status = '". node_status("expired") ."' WHERE nid = '$node->pid'");
+  }
+}
+
+function book_update($node) {
+  if ($node->pid && $node->status == node_status("posted")) {
+    db_query("UPDATE node SET status = '". node_status("expired") ."' WHERE nid = '$node->pid'");
+  }
+}
+
 function book_parent($nid) {
   global $status;
   if ($node = node_get_object(array("nid" => $nid))) {
@@ -206,7 +221,7 @@ function book_page() {
   $theme->footer();
 }
 
-function book_update($id) {
+function book_edit($id) {
   global $status;
 
   if ($node = node_get_object(array("nid" => $id))) {
@@ -229,7 +244,7 @@ function book_user() {
 
   switch($op) {
     case "update":
-      $theme->box($title, book_update($id));
+      $theme->box($title, book_edit($id));
       break;
     case t("Preview"):
       $theme->box($title, book_form($edit));
diff --git a/modules/book/book.module b/modules/book/book.module
index 8d226800dc6754fd8198f331c6fa4d2b405f105c..87e6bff58c2fd5ba5244a4f809dec4eb2516799d 100644
--- a/modules/book/book.module
+++ b/modules/book/book.module
@@ -116,10 +116,8 @@ function book_form($edit = array()) {
   $form .= form_hidden(userid, $edit[userid]);
   $form .= form_textfield(t("Subject"), "title", $edit[title], 50, 64);
 
-  if ($edit[pid]) {
-    $node = node_get_object(array("nid" => $edit[pid]));
-    $form .= form_item(t("Parent"), "<A HREF=\"node.php?id=$node->id\">". check_output($node->title) ."</A>", t("The parent subject or category the page belongs in."));
-    $form .= form_hidden("parent", $edit[parent]);
+  if ($edit[pid] > 0) {
+    $form .= form_hidden("pid", $edit[pid]);
   }
   else {
     $form .= form_select(t("Parent"), "parent", $edit[parent], book_toc(), t("The parent subject or category the page belongs in."));
@@ -133,11 +131,10 @@ function book_form($edit = array()) {
   }
 
   if ($edit[nid] > 0) {
-    $form .= form_hidden("pid", $edit[pid]);
     $form .= form_hidden("nid", $edit[nid]);
   }
 
-  if (!$edit[title]) {
+  if ($edit && !$edit[title]) {
     $form .= "<FONT COLOR=\"red\">". t("Warning: you did not supply a title.") ."</FONT><P>\n";
     $form .= form_submit(t("Preview"));
   }
@@ -153,13 +150,31 @@ function book_save($edit) {
   global $status, $user;
 
   if (!$edit[nid]) {
-    node_save($edit, array(author => $user->id, body, comment => variable_get("book_comment", 0), log, moderate => variable_get("book_moderate", ""), parent, promote => variable_get("book_promote", 0), score => 0, status => variable_get("book_status", $status[queued]), timestamp => time(), title, type => "book", votes => 0, weight));
+    node_save($edit, array(author => $user->id, body, comment => variable_get("book_comment", 0), log, moderate => variable_get("book_moderate", ""), parent, pid, promote => variable_get("book_promote", 0), score => 0, status => variable_get("book_status", $status[queued]), timestamp => time(), title, type => "book", votes => 0, weight));
   }
   else if (user_access($user)) {
     node_save($edit, array(body, log, parent, title, type => "book", weight));
   }
 }
 
+function book_delete($node) {
+  if ($node->pid && $node->status == node_status("posted")) {
+    db_query("UPDATE node SET status = '". node_status("posted") ."' WHERE nid = '$node->pid'");
+  }
+}
+
+function book_insert($node) {
+  if ($node->pid && $node->status == node_status("posted")) {
+    db_query("UPDATE node SET status = '". node_status("expired") ."' WHERE nid = '$node->pid'");
+  }
+}
+
+function book_update($node) {
+  if ($node->pid && $node->status == node_status("posted")) {
+    db_query("UPDATE node SET status = '". node_status("expired") ."' WHERE nid = '$node->pid'");
+  }
+}
+
 function book_parent($nid) {
   global $status;
   if ($node = node_get_object(array("nid" => $nid))) {
@@ -206,7 +221,7 @@ function book_page() {
   $theme->footer();
 }
 
-function book_update($id) {
+function book_edit($id) {
   global $status;
 
   if ($node = node_get_object(array("nid" => $id))) {
@@ -229,7 +244,7 @@ function book_user() {
 
   switch($op) {
     case "update":
-      $theme->box($title, book_update($id));
+      $theme->box($title, book_edit($id));
       break;
     case t("Preview"):
       $theme->box($title, book_form($edit));
diff --git a/modules/conf.module b/modules/conf.module
index fc50556833a15ea53b50d7ef7e1003e9559d5a04..340308c904292adc1d6114feef294ce653f2bdcc 100644
--- a/modules/conf.module
+++ b/modules/conf.module
@@ -31,7 +31,7 @@ function conf_view_system() {
 
   // node settings:
   $output .= "<H3>Node settings</H3>\n";
-  $output .= form_select(t("Default number of nodes to display"), "default_nodes_main", variable_get("default_nodes_main", 10), array(10 => 10, 15 => 15, 20 => 20, 25 => 25, 30 => 30), t("The default maximum number of nodes to display on the main page."));
+  $output .= form_select(t("Default number of nodes to display"), "default_nodes_main", variable_get("default_nodes_main", 10), array(1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 =>  5, 6 => 6, 7 => 7, 8 => 8, 9 => 9, 10 => 10, 15 => 15, 20 => 20, 25 => 25, 30 => 30), t("The default maximum number of nodes to display on the main page."));
   $output .= "<HR>\n";
 
   // comment settings:
diff --git a/modules/meta.module b/modules/meta.module
index 8ff9640d8c90b747e55d555ba9d9a60ce4b2c166..32af339e78be28fa79daecf9404d0fb31d626d37 100644
--- a/modules/meta.module
+++ b/modules/meta.module
@@ -22,7 +22,7 @@ function meta_form($type, $edit = array()) {
 function meta_save($type, $edit = array()) {
   $result = db_query("SELECT * FROM collection WHERE types LIKE '%". check_input($type) ."%'");
   while ($collection = db_fetch_object($result)) {
-    $output = field_merge($output, $edit[$collection->name]);
+    $output .= ", ". $edit[$collection->name];
   }
   return $output;
 }
@@ -54,8 +54,8 @@ function meta_form_tag($edit = array()) {
   global $REQUEST_URI;
 
   $form .= form_textfield("Meta-tag name", "name", $edit[name], 50, 64, "Required.  The name for this meta-tag.  Example: 'Apache'.");
-  $form .= form_textfield("Attributes", "attributes", $edit[attributes], 50, 64, htmlentities("Required.  Format: <type>=<value>,<type>=<value>;.  Example: 'software=apache,type=webserver,os=linux,'."));
-  $form .= form_textfield("Collections", "collections", $edit[collections], 50, 64, "Required.  A comma-seperated list of collections you want to associate this meta-tag with.  Example: 'Software, Internet'");
+  $form .= form_textfield("Attributes", "attributes", $edit[attributes], 50, 64, "Required.  A comma-seperated list of keywords you want to associate this meta-tag with.  Example: 'Computers, Software, Webservers'.");
+  $form .= form_textfield("Collections", "collections", $edit[collections], 50, 64, "Required.  A comma-seperated list of collections you want to associate this meta-tag with.  Example: 'Section'.");
   $form .= form_submit("Submit");
 
   if ($edit[tid]) {
diff --git a/modules/node.module b/modules/node.module
index 0d53b94ec61d45597c29085f06adff01b2232420..5a68ec7dd3a1dabdce83cf2aefd0a433dac35cd0 100644
--- a/modules/node.module
+++ b/modules/node.module
@@ -60,6 +60,18 @@ function node_cron() {
   db_query("UPDATE node SET status = '". node_status("dumped") ."', timestamp_posted = '' WHERE timestamp_hidden > 0 AND timestamp_hidden < ". time());
 }
 
+function node_link($nid, $type) {
+  global $op;
+
+  $link[] = ($op == "view") ? "view node" : "<A HREF=\"node.php?id$nid\">view node</A>";
+  $link[] = ($op == "content") ? "edit content" : "<A HREF=\"admin.php?mod=node&type=$type&op=content&id=$nid\">edit content</A>";
+  $link[] = ($op == "option") ? "edit options" : "<A HREF=\"admin.php?mod=node&op=option&id=$nid\">edit options</A>";
+  $link[] = ($op == "status") ? "edit status" : "<A HREF=\"admin.php?mod=node&op=status&id=$nid\">edit status</A>";
+  $link[] = ($op == "attribute") ? "edit attribute" : "<A HREF=\"admin.php?mod=node&op=attribute&id=$nid\">edit attributes</A>";
+  $link[] = ($op == "delete") ? "delete node" : "<A HREF=\"admin.php?mod=node&op=delete&id=$nid\">delete node</A>";
+  return $link;
+}
+
 function node_overview($query) {
   global $user;
 
@@ -73,18 +85,10 @@ function node_overview($query) {
   $output .= " <TR><TH>title</TH><TH>type</TH><TH>status</TH><TH>meta attributes</TH><TH>author</TH><TH>date</TH></TR>\n";
 
   while ($node = db_fetch_object($result)) {
-    unset ($link);
-
-    $link[] = "<A HREF=\"admin.php?mod=node&type=$node->type&op=edit&id=$node->nid\">edit content</A>";
-    $link[] = "<A HREF=\"admin.php?mod=node&op=option&id=$node->nid\">edit options</A>";
-    $link[] = "<A HREF=\"admin.php?mod=node&op=status&id=$node->nid\">edit status</A>";
-    $link[] = "<A HREF=\"admin.php?mod=node&op=attribute&id=$node->nid\">edit attributes</A>";
-    $link[] = "<A HREF=\"admin.php?mod=node&op=delete&id=$node->nid\">delete node</A>";
-
     $bg = $color[$i++ % sizeof($color)];
 
     $output .= " <TR BGCOLOR=\"$bg\"><TD><A HREF=\"node.php?id=$node->nid\">". check_output($node->title) ."</A></TD><TD ALIGN=\"center\">$node->type</TD><TD>". node_status($node->status) ."</TD><TD>". check_output($node->attributes) ."</TD><TD>". format_username($node->userid) ."</TD><TD>". format_date($node->timestamp, "small") ."</TD></TR>\n";
-    $output .= " <TR BGCOLOR=\"$bg\"><TD ALIGN=\"right\" COLSPAN=\"6\"><SMALL>". implode(", ", $link) ."</SMALL></TD>\n";
+    $output .= " <TR BGCOLOR=\"$bg\"><TD ALIGN=\"right\" COLSPAN=\"6\"><SMALL>". implode(", ", node_link($node->nid, $node->type)) ."</SMALL></TD>\n";
   }
   $output .= "</TABLE>\n";
 
@@ -96,9 +100,10 @@ function node_edit_option($id) {
 
   $node = node_get_object(array("nid" => $id));
 
-  $form .= form_item("Document title", check_output($node->title));
-  $form .= form_select("Comment", "comment", $node->comment, node_comment_status(), "Allow users to post comments to this document.");
-  $form .= form_select("Promote", "promote", $node->promote, node_promote_status(), "Promote this document on the main page.");
+  $form .= form_item("Title", check_output($node->title));
+  $form .= form_item("Operations", implode("<br />", node_link($node->nid, $node->type)));
+  $form .= form_select("Comment", "comment", $node->comment, node_comment_status(), "Allow users to post comments to this node.");
+  $form .= form_select("Promote", "promote", $node->promote, node_promote_status(), "Promote this node on the main page.");
   $form .= form_textfield("Moderate", "moderate", $node->moderate, 35, 255, t("A comma-seperated list of the moderators their usernames."));
   $form .= form_hidden("nid", $node->nid);
   $form .= form_submit("Save node");
@@ -111,8 +116,9 @@ function node_edit_attribute($id) {
 
   $node = node_get_object(array("nid" => $id));
 
-  $form .= form_item("Document title", check_output($node->title));
-  $form .= form_textfield("Attributes", "attributes", $node->attributes, 50, 128, htmlentities("A list meta attributes.  Format: <type>:<value>;<type>:<value>;.  Example: 'software=apache,type=webserver,os=linux,'."));
+  $form .= form_item("Title", check_output($node->title));
+  $form .= form_item("Operations", implode("<br />", node_link($node->nid, $node->type)));
+  $form .= form_textfield("Attributes", "attributes", $node->attributes, 64, 128, "A comma-seperated list of attributes.  Example: 'Software, Webserver, Apache'.");
   $form .= form_hidden("nid", $node->nid);
   $form .= form_submit("Save node");
 
@@ -124,7 +130,8 @@ function node_edit_status($id) {
 
   $node = node_get_object(array("nid" => $id));
 
-  $form .= form_item("Document title", check_output($node->title));
+  $form .= form_item("Title", check_output($node->title));
+  $form .= form_item("Operations", implode("<br />", node_link($node->nid, $node->type)));
   $form .= form_select("Current status", "status", $node->status, node_status($node->type));
   $form .= form_textfield("Automatically post document", "timestamp_posted", ($node->timestamp_posted ? format_date($node->timestamp_posted) : ""), 30, 55, "The date at which your document will be automatically posted.  Leave empty if you don't want to schedule this document, or fill out a string containing an English date format.  Example input: '". date("j F Y G:i") ."', '". date("m/d/y H:i") ."', '". date("F j, Y H:i") ."', ...");
   $form .= form_textfield("Automatically queue document", "timestamp_queued", ($node->timestamp_queued ? format_date($node->timestamp_queued) : ""), 30, 55, "The date at which your document will be automatically queued.  Leave empty if you don't want to schedule this document, or fill out a string containing an English date format.  Example input: '". date("j F Y G:i") ."', '". date("m/d/y H:i") ."', '". date("F j, Y H:i") ."', ...");
@@ -135,8 +142,18 @@ function node_edit_status($id) {
   return form($REQUEST_URI, $form);
 }
 
+function node_edit_content($edit, $type) {
+  $edit[type] = $type;
+  return node_invoke($edit, "form");
+}
+
+function node_save_content($edit, $type) {
+  $edit[type] = $type;
+  return node_invoke($edit, "save");
+}
+
 function node_delete($id) {
-  return (node_del(array("nid" => $id)) ? "node has been deleted." : "failed to delete node: node must be dumped first.");
+  return (node_del(array("nid" => $id)) ? "node has been deleted." : "failed to delete node: set node status to 'dumped' first.");
 }
 
 function node_query($type = -1) {
@@ -230,14 +247,11 @@ function node_module_find() {
   return $output;
 }
 
-function node_module_edit($edit, $type) {
-  $edit[type] = $type;
-  return node_invoke($edit, "form");
-}
 
-function node_module_save($edit, $type) {
-  $edit[type] = $type;
-  return node_invoke($edit, "save");
+function node_edit($node) {
+  $output .= form_item("Title", $node->title);
+  $output .= form_item("Operations", implode("<br />", node_link($node->nid, $node->type)));
+  return $output;
 }
 
 function node_admin() {
@@ -273,6 +287,9 @@ function node_admin() {
     case "attribute":
       print node_edit_attribute($id);
       break;
+    case "content":
+      print node_edit_content(node_get_array(array("nid" => $id)), $type);
+      break;
     case "default":
       print node_setting();
       break;
@@ -296,13 +313,16 @@ function node_admin() {
       print node_overview($query);
       break;
     case "edit":
-      print node_module_edit(node_get_array(array("nid" => $id)), $type);
+      print node_edit(node_get_object(array("nid" => $id)));
+      break;
+    case "view":
+      print node_module_view(node_get_array(array("nid" => $id)), $type);
       break;
     case "Preview":
-      print node_module_edit($edit, $type);
+      print node_edit_content($edit, $type);
       break;
     case "Submit":
-      print status(node_module_save($edit, $type));
+      print status(node_save_content($edit, $type));
       // fall through:
     default:
       print node_overview($query);
diff --git a/modules/node/node.module b/modules/node/node.module
index 0d53b94ec61d45597c29085f06adff01b2232420..5a68ec7dd3a1dabdce83cf2aefd0a433dac35cd0 100644
--- a/modules/node/node.module
+++ b/modules/node/node.module
@@ -60,6 +60,18 @@ function node_cron() {
   db_query("UPDATE node SET status = '". node_status("dumped") ."', timestamp_posted = '' WHERE timestamp_hidden > 0 AND timestamp_hidden < ". time());
 }
 
+function node_link($nid, $type) {
+  global $op;
+
+  $link[] = ($op == "view") ? "view node" : "<A HREF=\"node.php?id$nid\">view node</A>";
+  $link[] = ($op == "content") ? "edit content" : "<A HREF=\"admin.php?mod=node&type=$type&op=content&id=$nid\">edit content</A>";
+  $link[] = ($op == "option") ? "edit options" : "<A HREF=\"admin.php?mod=node&op=option&id=$nid\">edit options</A>";
+  $link[] = ($op == "status") ? "edit status" : "<A HREF=\"admin.php?mod=node&op=status&id=$nid\">edit status</A>";
+  $link[] = ($op == "attribute") ? "edit attribute" : "<A HREF=\"admin.php?mod=node&op=attribute&id=$nid\">edit attributes</A>";
+  $link[] = ($op == "delete") ? "delete node" : "<A HREF=\"admin.php?mod=node&op=delete&id=$nid\">delete node</A>";
+  return $link;
+}
+
 function node_overview($query) {
   global $user;
 
@@ -73,18 +85,10 @@ function node_overview($query) {
   $output .= " <TR><TH>title</TH><TH>type</TH><TH>status</TH><TH>meta attributes</TH><TH>author</TH><TH>date</TH></TR>\n";
 
   while ($node = db_fetch_object($result)) {
-    unset ($link);
-
-    $link[] = "<A HREF=\"admin.php?mod=node&type=$node->type&op=edit&id=$node->nid\">edit content</A>";
-    $link[] = "<A HREF=\"admin.php?mod=node&op=option&id=$node->nid\">edit options</A>";
-    $link[] = "<A HREF=\"admin.php?mod=node&op=status&id=$node->nid\">edit status</A>";
-    $link[] = "<A HREF=\"admin.php?mod=node&op=attribute&id=$node->nid\">edit attributes</A>";
-    $link[] = "<A HREF=\"admin.php?mod=node&op=delete&id=$node->nid\">delete node</A>";
-
     $bg = $color[$i++ % sizeof($color)];
 
     $output .= " <TR BGCOLOR=\"$bg\"><TD><A HREF=\"node.php?id=$node->nid\">". check_output($node->title) ."</A></TD><TD ALIGN=\"center\">$node->type</TD><TD>". node_status($node->status) ."</TD><TD>". check_output($node->attributes) ."</TD><TD>". format_username($node->userid) ."</TD><TD>". format_date($node->timestamp, "small") ."</TD></TR>\n";
-    $output .= " <TR BGCOLOR=\"$bg\"><TD ALIGN=\"right\" COLSPAN=\"6\"><SMALL>". implode(", ", $link) ."</SMALL></TD>\n";
+    $output .= " <TR BGCOLOR=\"$bg\"><TD ALIGN=\"right\" COLSPAN=\"6\"><SMALL>". implode(", ", node_link($node->nid, $node->type)) ."</SMALL></TD>\n";
   }
   $output .= "</TABLE>\n";
 
@@ -96,9 +100,10 @@ function node_edit_option($id) {
 
   $node = node_get_object(array("nid" => $id));
 
-  $form .= form_item("Document title", check_output($node->title));
-  $form .= form_select("Comment", "comment", $node->comment, node_comment_status(), "Allow users to post comments to this document.");
-  $form .= form_select("Promote", "promote", $node->promote, node_promote_status(), "Promote this document on the main page.");
+  $form .= form_item("Title", check_output($node->title));
+  $form .= form_item("Operations", implode("<br />", node_link($node->nid, $node->type)));
+  $form .= form_select("Comment", "comment", $node->comment, node_comment_status(), "Allow users to post comments to this node.");
+  $form .= form_select("Promote", "promote", $node->promote, node_promote_status(), "Promote this node on the main page.");
   $form .= form_textfield("Moderate", "moderate", $node->moderate, 35, 255, t("A comma-seperated list of the moderators their usernames."));
   $form .= form_hidden("nid", $node->nid);
   $form .= form_submit("Save node");
@@ -111,8 +116,9 @@ function node_edit_attribute($id) {
 
   $node = node_get_object(array("nid" => $id));
 
-  $form .= form_item("Document title", check_output($node->title));
-  $form .= form_textfield("Attributes", "attributes", $node->attributes, 50, 128, htmlentities("A list meta attributes.  Format: <type>:<value>;<type>:<value>;.  Example: 'software=apache,type=webserver,os=linux,'."));
+  $form .= form_item("Title", check_output($node->title));
+  $form .= form_item("Operations", implode("<br />", node_link($node->nid, $node->type)));
+  $form .= form_textfield("Attributes", "attributes", $node->attributes, 64, 128, "A comma-seperated list of attributes.  Example: 'Software, Webserver, Apache'.");
   $form .= form_hidden("nid", $node->nid);
   $form .= form_submit("Save node");
 
@@ -124,7 +130,8 @@ function node_edit_status($id) {
 
   $node = node_get_object(array("nid" => $id));
 
-  $form .= form_item("Document title", check_output($node->title));
+  $form .= form_item("Title", check_output($node->title));
+  $form .= form_item("Operations", implode("<br />", node_link($node->nid, $node->type)));
   $form .= form_select("Current status", "status", $node->status, node_status($node->type));
   $form .= form_textfield("Automatically post document", "timestamp_posted", ($node->timestamp_posted ? format_date($node->timestamp_posted) : ""), 30, 55, "The date at which your document will be automatically posted.  Leave empty if you don't want to schedule this document, or fill out a string containing an English date format.  Example input: '". date("j F Y G:i") ."', '". date("m/d/y H:i") ."', '". date("F j, Y H:i") ."', ...");
   $form .= form_textfield("Automatically queue document", "timestamp_queued", ($node->timestamp_queued ? format_date($node->timestamp_queued) : ""), 30, 55, "The date at which your document will be automatically queued.  Leave empty if you don't want to schedule this document, or fill out a string containing an English date format.  Example input: '". date("j F Y G:i") ."', '". date("m/d/y H:i") ."', '". date("F j, Y H:i") ."', ...");
@@ -135,8 +142,18 @@ function node_edit_status($id) {
   return form($REQUEST_URI, $form);
 }
 
+function node_edit_content($edit, $type) {
+  $edit[type] = $type;
+  return node_invoke($edit, "form");
+}
+
+function node_save_content($edit, $type) {
+  $edit[type] = $type;
+  return node_invoke($edit, "save");
+}
+
 function node_delete($id) {
-  return (node_del(array("nid" => $id)) ? "node has been deleted." : "failed to delete node: node must be dumped first.");
+  return (node_del(array("nid" => $id)) ? "node has been deleted." : "failed to delete node: set node status to 'dumped' first.");
 }
 
 function node_query($type = -1) {
@@ -230,14 +247,11 @@ function node_module_find() {
   return $output;
 }
 
-function node_module_edit($edit, $type) {
-  $edit[type] = $type;
-  return node_invoke($edit, "form");
-}
 
-function node_module_save($edit, $type) {
-  $edit[type] = $type;
-  return node_invoke($edit, "save");
+function node_edit($node) {
+  $output .= form_item("Title", $node->title);
+  $output .= form_item("Operations", implode("<br />", node_link($node->nid, $node->type)));
+  return $output;
 }
 
 function node_admin() {
@@ -273,6 +287,9 @@ function node_admin() {
     case "attribute":
       print node_edit_attribute($id);
       break;
+    case "content":
+      print node_edit_content(node_get_array(array("nid" => $id)), $type);
+      break;
     case "default":
       print node_setting();
       break;
@@ -296,13 +313,16 @@ function node_admin() {
       print node_overview($query);
       break;
     case "edit":
-      print node_module_edit(node_get_array(array("nid" => $id)), $type);
+      print node_edit(node_get_object(array("nid" => $id)));
+      break;
+    case "view":
+      print node_module_view(node_get_array(array("nid" => $id)), $type);
       break;
     case "Preview":
-      print node_module_edit($edit, $type);
+      print node_edit_content($edit, $type);
       break;
     case "Submit":
-      print status(node_module_save($edit, $type));
+      print status(node_save_content($edit, $type));
       // fall through:
     default:
       print node_overview($query);
diff --git a/modules/story.module b/modules/story.module
index 527523985d69032d97c1860e535f787810fd9881..ca9ff6946de34fe2a9570112ddf1c127b946ef63 100644
--- a/modules/story.module
+++ b/modules/story.module
@@ -53,11 +53,11 @@ function story_form($edit = array()) {
     $form .= form_hidden("nid", $edit[nid]);
   }
 
-  if (!$edit[title]) {
+  if ($edit && !$edit[title]) {
     $form .= "<FONT COLOR=\"red\">". t("Warning: you did not supply a subject.") ."</FONT><P>\n";
     $form .= form_submit(t("Preview"));
   }
-  else if (!$edit[abstract]) {
+  else if ($edit && !$edit[abstract]) {
     $form .= "<FONT COLOR=\"red\">". t("Warning: you did not supply an abstract.") ."</FONT><P>\n";
     $form .= form_submit(t("Preview"));
   }
diff --git a/modules/story/story.module b/modules/story/story.module
index 527523985d69032d97c1860e535f787810fd9881..ca9ff6946de34fe2a9570112ddf1c127b946ef63 100644
--- a/modules/story/story.module
+++ b/modules/story/story.module
@@ -53,11 +53,11 @@ function story_form($edit = array()) {
     $form .= form_hidden("nid", $edit[nid]);
   }
 
-  if (!$edit[title]) {
+  if ($edit && !$edit[title]) {
     $form .= "<FONT COLOR=\"red\">". t("Warning: you did not supply a subject.") ."</FONT><P>\n";
     $form .= form_submit(t("Preview"));
   }
-  else if (!$edit[abstract]) {
+  else if ($edit && !$edit[abstract]) {
     $form .= "<FONT COLOR=\"red\">". t("Warning: you did not supply an abstract.") ."</FONT><P>\n";
     $form .= form_submit(t("Preview"));
   }
diff --git a/modules/watchdog.module b/modules/watchdog.module
index 8abe4dc3fce87c08dbe70d4d6e573866554bac38..02c7c23ca6752e34697ce4c1a2dc3238db7a832b 100644
--- a/modules/watchdog.module
+++ b/modules/watchdog.module
@@ -55,7 +55,7 @@ function watchdog_view($id) {
 function watchdog_admin() {
   global $op, $id, $type, $order;
 
-  print "<SMALL><A HREF=\"admin.php?mod=watchdog&type=account\">account messages</A> | <A HREF=\"admin.php?mod=watchdog&type=message\">regular messages</A> | <A HREF=\"admin.php?mod=watchdog&type=special\">special messages</A> | <A HREF=\"admin.php?mod=watchdog&type=warning\">warning messages</A> | <A HREF=\"admin.php?mod=watchdog&type=error\">error messages</A> | <A HREF=\"admin.php?mod=watchdog&type=httpd\">httpd messages</A> | <A HREF=\"admin.php?mod=watchdog\">overview</A> | <A HREF=\"admin.php?mod=watchdog&op=help\">help</A></SMALL><HR>\n";
+  print "<SMALL><A HREF=\"admin.php?mod=watchdog&type=account\">account messages</A> | <A HREF=\"admin.php?mod=watchdog&type=regular\">regular messages</A> | <A HREF=\"admin.php?mod=watchdog&type=special\">special messages</A> | <A HREF=\"admin.php?mod=watchdog&type=warning\">warning messages</A> | <A HREF=\"admin.php?mod=watchdog&type=error\">error messages</A> | <A HREF=\"admin.php?mod=watchdog&type=httpd\">httpd messages</A> | <A HREF=\"admin.php?mod=watchdog\">overview</A> | <A HREF=\"admin.php?mod=watchdog&op=help\">help</A></SMALL><HR>\n";
 
   switch ($op) {
     case "help":
diff --git a/modules/watchdog/watchdog.module b/modules/watchdog/watchdog.module
index 8abe4dc3fce87c08dbe70d4d6e573866554bac38..02c7c23ca6752e34697ce4c1a2dc3238db7a832b 100644
--- a/modules/watchdog/watchdog.module
+++ b/modules/watchdog/watchdog.module
@@ -55,7 +55,7 @@ function watchdog_view($id) {
 function watchdog_admin() {
   global $op, $id, $type, $order;
 
-  print "<SMALL><A HREF=\"admin.php?mod=watchdog&type=account\">account messages</A> | <A HREF=\"admin.php?mod=watchdog&type=message\">regular messages</A> | <A HREF=\"admin.php?mod=watchdog&type=special\">special messages</A> | <A HREF=\"admin.php?mod=watchdog&type=warning\">warning messages</A> | <A HREF=\"admin.php?mod=watchdog&type=error\">error messages</A> | <A HREF=\"admin.php?mod=watchdog&type=httpd\">httpd messages</A> | <A HREF=\"admin.php?mod=watchdog\">overview</A> | <A HREF=\"admin.php?mod=watchdog&op=help\">help</A></SMALL><HR>\n";
+  print "<SMALL><A HREF=\"admin.php?mod=watchdog&type=account\">account messages</A> | <A HREF=\"admin.php?mod=watchdog&type=regular\">regular messages</A> | <A HREF=\"admin.php?mod=watchdog&type=special\">special messages</A> | <A HREF=\"admin.php?mod=watchdog&type=warning\">warning messages</A> | <A HREF=\"admin.php?mod=watchdog&type=error\">error messages</A> | <A HREF=\"admin.php?mod=watchdog&type=httpd\">httpd messages</A> | <A HREF=\"admin.php?mod=watchdog\">overview</A> | <A HREF=\"admin.php?mod=watchdog&op=help\">help</A></SMALL><HR>\n";
 
   switch ($op) {
     case "help":
diff --git a/themes/marvin/marvin.theme b/themes/marvin/marvin.theme
index b6f875904ef02f7f01ae123e019e69683f722e6d..c24cb68f34ab03b902b9ea9138299f294ff498e4 100644
--- a/themes/marvin/marvin.theme
+++ b/themes/marvin/marvin.theme
@@ -19,139 +19,139 @@ class Theme extends BaseTheme {
 
    function header() {
     ?>
-     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-     <HTML>
-     <HEAD>
-      <TITLE><?php print variable_get(site_name, "drupal"); ?></TITLE>
-     </HEAD>
-     <STYLE type="text/css">
+     <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
+     <html>
+     <head>
+      <title><?php print variable_get("site_name", "drupal") ." - ". variable_get("site_slogan", ""); ?></title>
+     </head>
+     <style type="text/css">
       <!--
-       BODY, P, DIV, TH, TD, TR, FORM, OL, UL, LI, INPUT, TEXTAREA, SELECT, A { font-family: Verdana, Tahoma, Arial, Helvetica; }
+       P, DIV, TH, TD, TR, FORM, OL, UL, LI, INPUT, TEXTAREA, SELECT, A { font-family: Verdana, Tahoma, Arial, Helvetica; }
+       BODY { margin: 10px; font-size: 10pt; font-family: Verdana, Tahoma, Arial, Helvetica; }
+       SMALL { font-size: 10pt; }
+       BIG { font-size: 12pt; }
       -->
-     </STYLE>
-     <BODY TEXT="#000000" BGCOLOR="#FFFFFF" ALINK="#CCCCCC" LINK="#665555" VLINK="#665555">
-      <TABLE BORDER="0" CELLPADDING="8" CELLSPACING="0">
-       <TR>
-        <TD WIDTH="30" ROWSPAN="3">&nbsp;</TD>
-        <TD><A HREF="index.php"><IMG SRC="themes/marvin/images/logo.gif" ALT="" BORDER="0"></A></TD>
-        <TD>&nbsp;</TD>
-       </TR>
-       <TR>
-        <TD ALIGN="right" COLSPAN="2">
+     </style>
+     <body text="#000000" bgcolor="#FFFFFF" alink="#CCCCCC" link="#665555" vlink="#665555">
+      <table border="0" cellpadding="8" cellspacing="0">
+       <tr>
+        <td><a href="index.php"><img src="themes/marvin/images/logo.gif" alt="" border="0" /></a></td>
+        <td>&nbsp;</td>
+       </tr>
+       <tr>
+        <td align="right" colspan="2">
          <?php
-           print "<SMALL>". theme_link() ."</SMALL>\n";
+           print "<small>". theme_link() ."</small>\n";
          ?>
-        </TD>
-       </TR>
-       <TR>
-        <TD VALIGN="top" WIDTH="85%">
+        </td>
+       </tr>
+       <tr>
+        <td valign="top" width="85%">
     <?php
    }
 
    function node($node, $main = 0, $links = 0) {
      print "\n<!-- node: \"$node->title\" -->\n";
-     print "<TABLE BORDER=\"0\" CELLPADDING=\"0\" CELLSPACING=\"2\" WIDTH=\"100%\">\n";
-     print " <TR><TD COLSPAN=\"2\"><IMG SRC=\"themes/marvin/images/drop.gif\" ALT=\"\"> &nbsp; <B>". check_output($node->title) ."</B></TD></TR>\n";
-     print " <TR VALIGN=\"bottom\"><TD COLSPAN=\"2\" BGCOLOR=\"#000000\" WIDTH=\"100%\"><IMG SRC=\"themes/marvin/images/pixel.gif\" WIDTH=\"1\" HEIGHT=\"0\" ALT=\"\"></TD></TR>\n";
-     print " <TR>\n";
-     print "  <TD>\n";
-     print "   <FONT COLOR=\"#7C7C7C\"><SMALL>". strtr(t("Submitted by %a on %b"), array("%a" => format_username($node->userid), "%b" => format_date($node->timestamp, "large"))); ?><?php print "</SMALL></FONT></TD><TD ALIGN=\"right\" VALIGN=\"top\" NOWRAP><SMALL>". node_index($node) ."</SMALL>\n";
-     print "  </TD>\n";
-     print " </TR>\n";
-     print " <TR><TD COLSPAN=\"2\">&nbsp;</TD></TR>\n";
-     print " <TR>\n";
-     print "  <TD COLSPAN=\"2\"><P>". check_output($node->body, 1) ."</P></TD>\n";
-     print " </TR>\n";
-     print " <TR><TD COLSPAN=\"2\">&nbsp;</TD></TR>\n";
-     if (node_links($links, $node, $main)) print " <TR><TD COLSPAN=\"2\">". $this->links($links, $main) ."</TD></TR>\n";
-     print "</TABLE>\n";
-     print "<BR><BR>\n\n";
+     print "<table border=\"0\" cellpadding=\"0\" cellspacing=\"2\" width=\"100%\">\n";
+     print " <tr><td colspan=\"2\"><img src=\"themes/marvin/images/drop.gif\" alt=\"\" /> &nbsp; <b>". check_output($node->title) ."</b></td></tr>\n";
+     print " <tr valign=\"bottom\"><td colspan=\"2\" bgcolor=\"#000000\" width=\"100%\"><img src=\"themes/marvin/images/pixel.gif\" width=\"1\" height=\"0\" alt=\"\" /></td></tr>\n";
+     print " <tr><td><font color=\"#7C7C7C\"><small>". strtr(t("Submitted by %a on %b"), array("%a" => format_username($node->userid), "%b" => format_date($node->timestamp, "large"))); ?><?php print "</small></font></td><td align=\"right\" valign=\"top\" nowrap><small>". node_index($node) ."</small></td></tr>\n";
+     print " <tr><td colspan=\"2\">&nbsp;</td></tr>\n";
+     print " <tr><td colspan=\"2\"><p>". check_output($node->body, 1) ."</p></td></tr>\n";
+     print " <tr><td colspan=\"2\">&nbsp;</tr></tr>\n";
+     if (node_links($links, $node, $main)) {
+       print " <tr><td colspan=\"2\">". $this->links($links, $main) ."</td></tr>\n";
+     }
+     print "</table>\n";
+     print "<br /><br />\n\n";
    }
 
    function comment($comment, $link = "") {
-     print "<A NAME=\"$comment->cid\">\n";
+     print "<a name=\"$comment->cid\">\n";
 
      // Create comment header:
-     print "<TABLE BORDER=\"0\" CELLPADDING=\"0\" CELLSPACING=\"0\" BGCOLOR=\"#000000\" WIDTH=\"100%\">\n";
-     print " <TR BGCOLOR=\"#000000\">\n";
-     print "  <TD>\n";
-     print "   <TABLE BORDER=\"0\" CELLPADDING=\"3\" CELLSPACING=\"1\" WIDTH=\"100%\">\n";
-     print "    <TR>\n";
-     print "     <TD BGCOLOR=\"#EAEAEA\">\n";
-     print "      <TABLE BORDER=\"0\" CELLPADDING=\"2\" CELLSPACING=\"1\" WIDTH=\"100%\">\n";
-     print "       <TR>\n";
+     print "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"#000000\" width=\"100%\">\n";
+     print " <tr bgcolor=\"#000000\">\n";
+     print "  <td>\n";
+     print "   <table border=\"0\" cellpadding=\"3\" cellspacing=\"1\" width=\"100%\">\n";
+     print "    <tr>\n";
+     print "     <td bgcolor=\"#eaeaea\">\n";
+     print "      <table border=\"0\" cellpadding=\"2\" cellspacing=\"1\" width=\"100%\">\n";
+     print "       <tr>\n";
 
      // Subject:
-     print "        <TD ALIGN=\"right\" WIDTH=\"5%\"><B>". t("Subject") .":</FONT></TD>\n";
-     print "        <TD WIDTH=\"80%\"><B><FONT COLOR=\"#666699\">". check_output($comment->subject) ."</FONT></B></TD>\n";
+     print "        <td align=\"right\" width=\"5%\"><b>". t("Subject") .":</b></td>\n";
+     print "        <td width=\"80%\"><b><font color=\"#666699\">". check_output($comment->subject) ."</font></b></td>\n";
 
      // Moderation:
-     print "        <TD ALIGN=\"right\" ROWSPAN=\"3\" VALIGN=\"middle\" WIDTH=\"15%\">\n";
+     print "        <td align=\"right\" rowspan=\"3\" valign=\"middle\" width=\"15%\">\n";
      print comment_moderation($comment);
-     print "        </TD>\n";
-     print "       </TR>\n";
+     print "        </td>\n";
+     print "       </tr>\n";
 
      // Author:
-     print "       <TR>\n";
-     print "        <TD ALIGN=\"right\" VALIGN=\"top\">". t("Author") .":</TD><TD>". format_username($comment->userid) ."</TD>\n";
-     print "       </TR>\n";
+     print "       <tr>\n";
+     print "        <td align=\"right\" valign=\"top\">". t("Author") .":</td><td>". format_username($comment->userid) ."</td>\n";
+     print "       </tr>\n";
 
      // Date
-     print "       <TR>\n";
-     print "        <TD ALIGN=\"right\">". t("Date") .":</TD><TD>". format_date($comment->timestamp) ."</TD>\n";
-     print "       </TR>\n";
+     print "       <tr>\n";
+     print "        <td align=\"right\">". t("Date") .":</td><td>". format_date($comment->timestamp) ."</td>\n";
+     print "       </tr>\n";
 
-     print "      </TABLE>\n";
-     print "     </TD>\n";
-     print "    </TR>\n";
+     print "      </table>\n";
+     print "     </td>\n";
+     print "    </tr>\n";
 
      // Print body of comment:
-     if ($comment->comment) print "    <TR><TD BGCOLOR=\"#FFFFFF\">". check_output($comment->comment, 1) ."</TD></TR>\n";
+     if ($comment->comment) {
+       print "    <tr><td bgcolor=\"#FFFFFF\">". check_output($comment->comment, 1) ."</td></tr>\n";
+     }
 
      // Print bottom link(s):
-     print "    <TR><TD ALIGN=\"right\" BGCOLOR=\"#EAEAEA\">[ $link ]</TD></TR>\n";
-     print "   </TABLE>\n";
-     print "  </TD>\n";
-     print " </TR>\n";
-     print "</TABLE>\n";
-     print "<BR>\n\n";
+     print "    <tr><td align=\"right\" bgcolor=\"#EAEAEA\">[ $link ]</td></tr>\n";
+     print "   </table>\n";
+     print "  </td>\n";
+     print " </tr>\n";
+     print "</table>\n";
+     print "<br />\n\n";
    }
 
    function box($subject, $content, $options = "") {
      print "\n<!-- box: \"$subject\" -->\n";
-     print "<TABLE BORDER=\"0\" CELLPADDING=\"0\" CELLSPACING=\"0\" BGCOLOR=\"#000000\" WIDTH=\"100%\">\n";
-     print " <TR>\n";
-     print "  <TD>\n";
-     print "   <TABLE BORDER=\"0\" CELLPADDING=\"5\" CELLSPACING=\"1\" WIDTH=\"100%\">\n";
-     print "    <TR><TD ALIGN=\"center\" BGCOLOR=\"#EAEAEA\" NOWRAP><FONT COLOR=\"#404040\"><B>$subject</B></FONT></TD></TR>\n";
-     print "    <TR><TD BGCOLOR=\"#FFFFFF\">$content</TD></TR>\n";
-     print "   </TABLE>\n";
-     print "  </TD>\n";
-     print " </TR>\n";
-     print "</TABLE>\n";
-     print "<BR>\n\n";
+     print "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"#000000\" width=\"100%\">\n";
+     print " <tr>\n";
+     print "  <td>\n";
+     print "   <table border=\"0\" cellpadding=\"5\" cellspacing=\"1\" width=\"100%\">\n";
+     print "    <tr><td align=\"center\" bgcolor=\"#eaeaea\" nowrap><font color=\"#404040\"><b>$subject</b></font></td></tr>\n";
+     print "    <tr><td bgcolor=\"#ffffff\">$content</td></tr>\n";
+     print "   </table>\n";
+     print "  </td>\n";
+     print " </tr>\n";
+     print "</table>\n";
+     print "<br />\n\n";
    }
 
    function footer() {
      ?>
-       </TD>
-       <TD VALIGN="top" WIDTH="200">
+       </td>
+       <td valign="top" width="200">
          <?php
           theme_account($this);
           theme_blocks("all", $this);
          ?>
-       </TD>
-      </TR>
-      <TR>
-       <TD ALIGN="center" COLSPAN="3">
+       </tr>
+      </tr>
+      <tr>
+       <td align="center" colspan="2">
         <?php
-          print "<P><SMALL>[ ". theme_link() ." ]</SMALL></P><P>". variable_get(site_footer, "") ."</P>\n";
+          print "<p><small>[ ". theme_link() ." ]</small></p><p>". variable_get("site_footer", "") ."</p>\n";
         ?>
-       </TD>
-      </TR>
-     </TABLE>
-    </BODY>
-    </HTML>
+       </td>
+      </tr>
+     </table>
+    </body>
+    </html>
     <?php
    }
  }
diff --git a/updates/2.00-to-x.xx.sql b/updates/2.00-to-x.xx.sql
index a0722d9c5ffcc5475b0dce3b2d5ec3334536b427..501c4bfe0d0d9ea01d77c7cb1f3e8ca44f478287 100644
--- a/updates/2.00-to-x.xx.sql
+++ b/updates/2.00-to-x.xx.sql
@@ -259,14 +259,9 @@ CREATE TABLE collection (
   PRIMARY KEY (cid)
 );
 
-# test data:
-
-INSERT INTO collection (name, types) VALUES ('Software', 'story, book, poll');
-INSERT INTO collection (name, types) VALUES ('Hardware', 'story');
-
-INSERT INTO tag (collections, name) VALUES ('Software', 'ThatWare');
-INSERT INTO tag (collections, name) VALUES ('Software', 'phpWeblog');
-INSERT INTO tag (collections, name) VALUES ('Software', 'PHP-Nuke');
-INSERT INTO tag (collections, name) VALUES ('Software', 'Drupal');
-INSERT INTO tag (collections, name) VALUES ('Hardware', 'ARM CPU');
-INSERT INTO tag (collections, name) VALUES ('Hardware', 'x86 CPU');
+# 17/06/01
+ALTER TABLE book ADD pid int(10) DEFAULT '0' NOT NULL;
+ALTER TABLE book ADD log text NOT NULL;
+ALTER TABLE node DROP pid;
+ALTER TABLE node DROP log;
+DROP TABLE headlines;