diff --git a/account.php b/account.php
index 15fa44e28820a730a850d511d6a647aac9c85127..a9cd9850e2ddbc5b23f915f5d34d2d9775f54847 100644
--- a/account.php
+++ b/account.php
@@ -461,7 +461,7 @@ function account_track_comments() {
     $output .= " </UL>\n";
   }
 
-  $output = ($output) ? "$msg $output" : "$info <CENTER><B>You have not posted any comments recently.</B></CENTER>\n";
+  $output = ($output) ? "$msg $output" : "$info <CENTER>You have not posted any comments recently.</CENTER>\n";
 
   $theme->header();
   $theme->box("Track your comments", $output);
@@ -473,7 +473,7 @@ function account_track_stories() {
 
   $msg = "<P>This page might be helpful in case you want to keep track of the stories you contributed.  You are presented an overview of your stories along with the number of replies each story got.\n<P>\n"; 
 
-  $result = db_query("SELECT s.id, s.subject, s.timestamp, s.category, COUNT(s.id) as count FROM comments c LEFT JOIN stories s ON c.sid = s.id WHERE s.status = 2 AND s.author = $user->id GROUP BY s.id DESC");
+  $result = db_query("SELECT s.id, s.subject, s.timestamp, s.category, COUNT(c.cid) as count FROM stories s LEFT JOIN comments c ON c.sid = s.id WHERE s.status = 2 AND s.author = $user->id GROUP BY s.id DESC");
   
   while ($story = db_fetch_object($result)) {
     $output .= "<TABLE BORDER=\"0\" CELLPADDING=\"1\" CELLSPACING=\"1\">\n";
@@ -484,10 +484,8 @@ function account_track_stories() {
     $output .= "<P>\n";
   }
 
-  $output = ($output) ? "$msg $output" : "$info <CENTER><B>You have not posted any stories.</B></CENTER>\n";
-
   $theme->header();
-  $theme->box("Track your stories", $output);
+  $theme->box("Track your stories", ($output ? "$msg $output" : "$msg You have not posted any stories.\n"));
   $theme->footer();
 }
 
@@ -504,6 +502,7 @@ function account_track_site() {
     $block1 .= "</TABLE>\n";
     $block1 .= "<P>\n";
   }
+  $block1 = ($block1) ? $block1 : "<CENTER>You have not posted any comments recently.</CENTER>\n";
 
   $users_total = db_result(db_query("SELECT COUNT(id) FROM users"));
   
diff --git a/admin.php b/admin.php
index 9996cfb202c0fe7922f81dea9e303faf6b88de0e..5af84d7e640eb694456e29ec95719053c7c54a54 100644
--- a/admin.php
+++ b/admin.php
@@ -3,7 +3,7 @@
 include "includes/common.inc";
 
 // validate user permission:
-if (!$user->id || ($user->permissions != 1 && $user->id > 1)) exit();
+if (!($user->permissions == 1 || $user->id == 1)) exit();
 
 function admin_page($mod) {  
   global $repository, $menu, $modules;
@@ -17,7 +17,7 @@ function module($name, $module) {
  ?>
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
   <HTML>
-   <HEAD><TITLE><? echo $site_name; ?> administration center</TITLE></HEAD>
+   <HEAD><TITLE>Administration</TITLE></HEAD>
    <STYLE>
     body { font-family: helvetica, arial; }
     h1   { font-size: 18pt; font-weight: bold; color: #990000; }
@@ -27,7 +27,7 @@ function module($name, $module) {
     td	 { font-family: helvetica, arial; }
    </STYLE>
    <BODY BGCOLOR="#FFFFFF" LINK="#005599" VLINK="#004499" ALINK="#FF0000">
-    <H1>Administration center</H1>
+    <H1>Administration</H1>
  <?
 
   ksort($repository);  
diff --git a/cron.php b/cron.php
index 1c01362db9b5ae3d05426292a779afd75c63289c..d41e4cdd2970759d2f6e179ed824c1cd0d173b8a 100644
--- a/cron.php
+++ b/cron.php
@@ -2,7 +2,7 @@
 
 include "includes/common.inc";
 
-function cron_run($cron) {
+function cron_run() {
   global $repository;
 
   $time = time();
diff --git a/database/database.mysql b/database/database.mysql
index 14e8325ba01bf95b00d27765b51305bc831c5dd4..ab3685850a113bb6041f69ac6dde5bc230ea08ec 100644
--- a/database/database.mysql
+++ b/database/database.mysql
@@ -122,6 +122,7 @@ CREATE TABLE stories (
   score int(11) DEFAULT '0' NOT NULL,
   votes int(11) DEFAULT '0' NOT NULL,
   status int(4) DEFAULT '1',
+  UNIQUE subject (subject),
   PRIMARY KEY (id)
 );
 
diff --git a/includes/function.inc b/includes/function.inc
index a92d349d5d45bc290f8cf516a09470100fc20605..adcb4c5188c7ce8f5efd6249fcac1a97be3bda71 100644
--- a/includes/function.inc
+++ b/includes/function.inc
@@ -68,10 +68,10 @@ function format_interval($timestamp) {
     $output .= floor($timestamp / 60) ." min ";
     $timestamp = $timestamp % 60;
   }
-  if ($timestamp >= 0) {
+  if ($timestamp > 0) {
     $output .= "$timestamp sec";
   }
-  return $output;
+  return ($output) ? $output : "0 sec";
 }
 
 function format_date($timestamp, $type = "medium") {
diff --git a/includes/watchdog.inc b/includes/watchdog.inc
index 2a007e3cee736f97d0071a3bbf720fdf8fcc9674..4de8210dbdb62dd77d66432bd6d6f819ccecd955 100644
--- a/includes/watchdog.inc
+++ b/includes/watchdog.inc
@@ -10,7 +10,7 @@
 function watchdog($id, $message) {
   global $user, $watchdog, $watchdog_history;
 
-  if ($watchdog[$id][1]) {
+  if ($watchdog[$id][1] && !($user->permissions == 1 || $user->id == 1)) {
     if ($log = db_fetch_object(db_query("SELECT * FROM watchdog WHERE hostname = '". getenv("REMOTE_ADDR") ."' AND level = '". $watchdog[$id][0] ."'"))) {
       if (time() - $log->timestamp < $watchdog[$id][1]) { 
         watchdog("warning", "'". getenv("REMOTE_ADDR") ."' exceeded '$id' submission rate"); 
diff --git a/modules/ban.module b/modules/ban.module
index 256d0ac81356e43782f6180a251d25e15f227e88..05f3efcdd4613e2a4324f6fc1b9011be92d417cc 100644
--- a/modules/ban.module
+++ b/modules/ban.module
@@ -4,13 +4,8 @@
 
 include "includes/ban.inc";
 
-function ban_check($mask, $category) {
-  $ban = ban_match($mask, $category);
-  $output .= "". ($ban ? "Matched ban '<B>$ban->mask</B>' with reason: <I>$ban->reason</I>.<P>\n" : "No matching bans for '$mask'.<P>\n") ."";
-  print $output;
-}
 
-function ban_new($mask, $category, $reason) {
+function ban_admin_new($mask, $category, $reason) {
   ban_add($mask, $category, $reason, &$message);
   $output .= "$message\n";
   print $output;
@@ -44,14 +39,17 @@ function ban_display($category = "") {
   $output .= "  <TH>reason</TH>\n";
   $output .= "  <TH>operations</TH>\n";
   $output .= " </TR>\n";
-
   while ($ban = db_fetch_object($result)) {
     $output .= "  <TR><TD>$ban->mask</TD><TD>$ban->reason</TD><TD ALIGN=\"center\"><A HREF=\"admin.php?mod=ban&op=delete&category=$category&id=$ban->id\">delete</A></TD></TR>\n";
   }
-  
   $output .= " <TR><TD COLSPAN=\"3\"><SMALL>%: matches any number of characters, even zero characters.<BR>_: matches exactly one character.</SMALL></TD></TR>\n";
   $output .= "</TABLE>\n";
-  $output .= "<BR><HR>\n";
+  
+  print $output;
+}
+
+function ban_admin_add() {
+  global $type2index;
 
   $output .= "<H3>Add new ban:</H3>\n";
   $output .= "<FORM ACTION=\"admin.php?mod=ban\" METHOD=\"post\">\n";
@@ -67,7 +65,18 @@ function ban_display($category = "") {
   $output .= "<TEXTAREA NAME=\"reason\" COLS=\"50\" ROWS=\"5\"></TEXTAREA><P>\n";
   $output .= "<INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Add ban\"><BR>\n";
   $output .= "</FORM>\n";
-  $output .= "<BR><HR>\n";
+  
+  print $output;
+}
+
+function ban_check($mask, $category) {
+  $ban = ban_match($mask, $category);
+  $output .= "". ($ban ? "Matched ban '<B>$ban->mask</B>' with reason: <I>$ban->reason</I>.<P>\n" : "No matching bans for '$mask'.<P>\n") ."";
+  print $output;
+}
+
+function ban_admin_check() {
+  global $type2index;
 
   $output .= "<H3>Ban check:</H3>\n";
   $output .= "<FORM ACTION=\"admin.php?mod=ban\" METHOD=\"post\">\n";
@@ -88,14 +97,21 @@ function ban_display($category = "") {
 function ban_admin() {
   global $op, $id, $mask, $category, $reason;
 
+  print "<SMALL><A HREF=\"admin.php?mod=ban&op=add\">add ban</A> | <A HREF=\"admin.php?mod=ban&op=check\">check ban</A> | <A HREF=\"admin.php?mod=ban\">overview</A></SMALL><HR>\n";
+
   switch ($op) {
     case "Add ban":
-      ban_new($mask, $category, $reason);
+      ban_admin_new($mask, $category, $reason);
       ban_display($category);
       break;
     case "Check ban":
       ban_check($mask, $category);
-      ban_display($category);
+      break;
+    case "add":
+      ban_admin_add();
+      break;
+    case "check":
+      ban_admin_check();
       break;
     case "delete":
       ban_delete($id);
diff --git a/modules/box.module b/modules/box.module
index d4f3525671501bd17dd2f225802b7867fd3cf61e..70124bc31a012c1a6bb4709345b1135e7da656bf 100644
--- a/modules/box.module
+++ b/modules/box.module
@@ -39,7 +39,7 @@ function box_block() {
   $i = 0;
   while ($block = db_fetch_object($result)) {
     $blocks[$i]["subject"] = check_output($block->subject);
-    $blocks[$i]["content"] = ($block->type == 2) ? eval($block->content) : check_output($block->content);
+    $blocks[$i]["content"] = ($block->type == 2) ? eval($block->content) : check_output($block->content, ($block->type == 1) ? 0 : 1);
     $blocks[$i]["info"] = check_output($block->info);
     $blocks[$i]["link"] = check_output($block->link);
     $i++;
@@ -58,13 +58,19 @@ function box_admin_display() {
     $output .= " <TR><TH>Subject:</TH><TD>". format_data($block->subject) ."</TD></TR>\n";
     $output .= " <TR><TH>Content:</TH><TD>". nl2br(htmlentities($block->content)) ."</TD></TR>\n";
     $output .= " <TR><TH>Type:</TH><TD>". $type[$block->type] ."</TD></TR>\n";
-    $output .= " <TR><TH>Description:</TH><TD><I>". format_data($block->info) ."</I></TD></TR>\n";
+    $output .= " <TR><TH>Description:</TH><TD>". format_data($block->info) ."</TD></TR>\n";
     $output .= " <TR><TH>Link:</TH><TD>". format_url($block->link) ."</TD></TR>\n";
     $output .= " <TR><TH>Operations:</TH><TD><A HREF=\"admin.php?mod=box&op=edit&id=$block->id\">edit</A>, <A HREF=\"admin.php?mod=box&op=delete&id=$block->id\">delete</A></TD></TR>\n";
     $output .= "</TABLE>\n";
     $output .= "<BR><BR>\n";
   }
 
+  print $output;
+}
+
+function box_admin_new() {
+  $type = array(0 => "ASCII", 1 => "HTML", 2 => "PHP");
+
   foreach ($type as $key=>$value) {
     $selection .= "  <OPTION VALUE=\"$key\">$value</OPTION>\n";
   }
@@ -79,7 +85,6 @@ function box_admin_display() {
   $output .= " <TR><TH>Operations:</TH><TD><INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Add box\"></TD></TR>\n";
   $output .= "</TABLE>\n";
   $output .= "</FORM>\n";
-
   print $output;
 }
 
@@ -146,6 +151,8 @@ function box_admin_save($id, $subject, $content, $info, $link, $type) {
 function box_admin() {
   global $op, $id, $subject, $content, $info, $link, $type;
 
+  print "<SMALL><A HREF=\"admin.php?mod=box&op=add\">add new box</A> | <A HREF=\"admin.php?mod=box\">overview</A> | <A HREF=\"admin.php?mod=box&op=help\">help</A></SMALL><HR>\n";
+
   switch ($op) {
     case "Add box":
       box_admin_add($subject, $content, $info, $link, $type);
@@ -157,6 +164,12 @@ function box_admin() {
       box_admin_display();
       box_admin_rehash();
       break;
+    case "help":
+      box_help();
+      break;
+    case "add":
+      box_admin_new();
+      break;
     case "edit":
       box_admin_edit($id);
       break;
diff --git a/modules/cron.module b/modules/cron.module
index 2bb82fcba2497a04d881e7e1fbb6048a0920df32..dab94675036f681cce792dc3a04fc1cbb2b220f9 100644
--- a/modules/cron.module
+++ b/modules/cron.module
@@ -1,6 +1,15 @@
 <?
 
-$module = array("admin" => "cron_admin");
+$module = array("help" => "cron_help",
+                "admin" => "cron_admin");
+
+function cron_help() {
+ ?>
+   <P>Cron (which stands for chronograph) is a periodic command scheduler: it executes commands at intervals specified in seconds.  It can be used to control the execution of daily, weekly and monthly jobs (or anything with a period of n seconds).   Automating tasks is one of the best ways to keep a system running smoothly, and if most of your administration does not require your direct involvement, cron is an ideal solution.</P>
+   <P>Note that cron does not guarantee that the commands will be executed at the specified interval.  However, the engine will make sure that the commands are run at the specified intervals as closely as possible.</P>
+   <P>Check the <A HREF="admin.php?mod=documentation">documentation</A> for more information about cron and how to setup it correctly.</P>
+ <?
+}
 
 function cron_save($edit) {
   foreach ($edit as $key=>$value) {
@@ -32,13 +41,18 @@ function cron_display() {
 function cron_admin() {
   global $op, $edit, $name;
 
+  print "<SMALL><A HREF=\"admin.php?mod=cron\">overview</A> | <A HREF=\"admin.php?mod=cron&op=help\">help</A></SMALL><HR>\n";
+
   switch($op) {
+    case "help":
+      cron_help();
+      break;
     case "Save crons":
       cron_save($edit);
-      break;
+      // fall through
+    default:
+      cron_display();
   }
-  
-  cron_display();
 }
 
 ?>
diff --git a/modules/documentation.module b/modules/documentation.module
index 8d8e21ed9548e107b9eb9ab64a793b020789a3ec..04d04c19f5fe4c73b2130d5fc671d004c57e5645 100644
--- a/modules/documentation.module
+++ b/modules/documentation.module
@@ -42,15 +42,16 @@ function documentation() {
   <BLOCKQUOTE>$ cp includes/hostname.conf includes/www.yourdomain.com.conf</BLOCKQUOTE>
   <P>6. Edit your configuration file to set the required settings such as the database options and to customize your site to your likings.</P>
   <P>7. Launch your browser and point it to http://yourdomain.com/, create an account, log in and head on to http://yourdomain.com/admin.php.  The first user will automatically have administrator permissions.  Play with it for a bit and spend some time getting used to the administration interfaces.</P>
-  <P>8. Optionally (yet recommended for smooth operation) setup a crontab to periodically visit http://yourdomain.com/cron.php.</P>
+  <P>8. Optionally (yet recommended for smooth operation) edit the <CODE>.htaccess</CODE> file and set the values of the PHP variables to your likings: <CODE>session.name</CODE>, <CODE>session.cookie_lifetime</CODE>, <CODE>session.gc_maxlifetime</CODE>, <CODE>session.cache_expire</CODE> and <CODE>session.save_path</CODE>.  Check your PHP reference manual for the exact purpose of each variable mentioned.</P>
+  <P>9. Optionally (yet recommended for smooth operation) setup a crontab to periodically visit http://yourdomain.com/cron.php.</P>
   <P>Use a browser like lynx or wget but make sure the process terminates: either use /usr/bin/lynx -source http://yourdomain.com/cron.php or /usr/bin/wget -O /dev/null http://yourdomain.com/cron.php. Take a look at the example scripts in the <CODE>scripts</CODE>-directory and make sure to adjust them to your needs.</P>
   <P>A good crontab-line to run the cron-script once every hour would be:</P>
   <PRE>
     00 * * * * /home/www/drupal/scripts/cron-lynx
   </PRE>
-  <P>9. (optional) Create your site's theme or at least customize the existing themes.  To get started, head on to the <CODE>themes</CODE>-directory and make a custom logo for each theme.
-  <P>10. (optional) Add and remove modules to customize the functionality of your site.  Adding and removing modules is plain easy.  You can add a module by copying the files into the <CODE>modules</CODE>-directory and you can remove a module by removing a module's file from the <CODE>modules</CODE>-directory.  The drupal engine will then automatically include or exclude this module.  If for some reason, this seems to fail, "manually" rehash the modules list from http://yourdomain.com/admin.php?mod=module.</P>
-  <P>11. If you get it to run, let us know at <A HREF="mailto:info@drop.org">info@drop.org</A> so we can add your site to our list of drupal sites.  If you can't get it to run, you can find support at the drupal site or you can contact us by e-mail at <A HREF="mailto:info@drop.org">info@drop.org</A>.</P>
+  <P>10. Optionally create your site's theme or at least customize the existing themes.  To get started, head on to the <CODE>themes</CODE>-directory and make a custom logo for each theme.
+  <P>11. Optionally add and remove modules to customize the functionality of your site.  Adding and removing modules is plain easy.  You can add a module by copying the files into the <CODE>modules</CODE>-directory and you can remove a module by removing a module's file from the <CODE>modules</CODE>-directory.  The drupal engine will then automatically include or exclude this module.  If for some reason, this seems to fail, "manually" rehash the modules list from http://yourdomain.com/admin.php?mod=module.</P>
+  <P>12. If you get it to run, let us know at <A HREF="mailto:info@drop.org">info@drop.org</A> so we can add your site to our list of drupal sites.  If you can't get it to run, you can find support at the drupal site or you can contact us by e-mail at <A HREF="mailto:info@drop.org">info@drop.org</A>.</P>
 
   <H2>More than one (sub)domain on one machine</H2>
 
@@ -172,7 +173,7 @@ function documentation() {
    </TR>
    <TR>
     <TD VALIGN="top"><CODE>user</CODE></TD>
-    <TD VALIGN="top"></TD>
+    <TD VALIGN="top">If a module requires to extend any of the setting pages available to individual users, it should implement the user hook.  The function takes 3 parameters, resp.: <CODE>$username</CODE>, <CODE>$section</CODE> ("user", "site", "content") and <CODE>$operation</CODE> ("edit", "view", "save").</TD>
    </TR>
   </TABLE>
   <P>Even though we aim towards modularity, a basic rule is to avoid defined interfaces.  We are exceptionally careful when it comes down to adding hooks because once you give a hook to developers they will start coding to it and once somebody's using it, you are stuck with it.</P>
diff --git a/modules/faq.module b/modules/faq.module
index 9ca4cfa13f21568f84a72a69c7a505d0d6d93035..80fe80ac0b91260ac36626b2d7451aab4c0cd0e3 100644
--- a/modules/faq.module
+++ b/modules/faq.module
@@ -55,7 +55,7 @@ function faq_page() {
    <DD>Write us a bugreport or send us a patch!  Writing a good bug report takes patience, but doing it right the first time saves both you and us time.  It is most helpful when a good description of the problem is included in the bug report. That is, a good example of all the things you did that led to the problem and the problem itself exactly described. The best reports are those that include a full example showing how to reproduce the bug or problem.<P></DD>
 
    <DT><B>Is the source code of this site available?</B></DT>
-   <DD>This site is powered by <A HREF=\"http://www.fsf.org/\">Free Software</A>; including <A HREF=\"http://www.apache.org/\">Apache</A>, <A HREF=\"http://www.php.net/\">PHP</A>, <A HREF=\"http://www.mysql.com/\">MySQL</A> and <A HREF=\"http://www.linux.com/\">Linux</A>, and is inspired by several <A HREF=\"http://www.fsf.org/\">Free Software</A> projects.  Therefor we have decided to make the software engine of this site available under terms of GPL.<P>However, the sources are <B>not</B> available yet at this time, but will be released as soon we have a first, well-rounded source tree that has proven to be stable.  If you can't wait or in case you have big plans (like `total domination') with the engine, don't hesitate to contact us and we might grant you CVS access.<P></DD>
+   <DD>This site is powered by <A HREF=\"http://www.fsf.org/\">Free Software</A>; including <A HREF=\"http://www.apache.org/\">Apache</A>, <A HREF=\"http://www.php.net/\">PHP</A>, <A HREF=\"http://www.mysql.com/\">MySQL</A> and <A HREF=\"http://www.linux.com/\">Linux</A>, and is inspired by several <A HREF=\"http://www.fsf.org/\">Free Software</A> projects.  Therefor we have decided to make the software engine of this site, called <A HREF=\"module.php?mod=drupal\">drupal</A> available under terms of GPL.<P> The source code and more information about <A HREF=\"module.php?mod=drupal\">drupal</A> are available <A HREF=\"module.php?mod=drupal\">here</A>.<P></DD>
 
    <DT><B>What features does the engine have?</B></DT>
    <DD>
diff --git a/modules/headline.module b/modules/headline.module
index 358a1cc046886bc19e18cd74dcd609ae9a32023b..7629594d52025ef081d56d57d32af8d6090cbaea 100644
--- a/modules/headline.module
+++ b/modules/headline.module
@@ -100,7 +100,7 @@ function headline_block() {
   return $blocks;
 }
 
-function headline_admin_main() {
+function headline_admin_display() {
   global $theme;
 
   // Get channel info:
@@ -123,8 +123,11 @@ function headline_admin_main() {
   }  
 
   $output .= "</TABLE>\n";
-  $output .= "<BR><BR>\n";
-  $output .= "<HR>\n";
+  
+  print $output;
+}
+
+function headline_admin_add() {
   $output .= " <FORM ACTION=\"admin.php?mod=headline\" METHOD=\"post\">\n";
   $output .= "  <P>\n";
   $output .= "   <B>Site name:</B><BR>\n";
@@ -151,23 +154,31 @@ function headline_admin_main() {
 function headline_admin() {
   global $op, $id, $site, $url, $backend, $contact;
   
+  print "<SMALL><A HREF=\"admin.php?mod=headline&op=add\">add new channel</A> | <A HREF=\"admin.php?mod=headline\">overview</A> | <A HREF=\"admin.php?mod=headline&op=help\">help</A></SMALL><HR>";
+
   switch($op) {
-    case "refresh":
-      $backend = new backend($id);
-      $backend->refresh();
-      headline_admin_main();
+    case "add":
+      headline_admin_add();
       break;
     case "delete":
       $backend = new backend($id);
       $backend->delete();
-      headline_admin_main();
+      headline_admin_display();
+      break;
+    case "help":
+      headline_help();
+      break;
+    case "refresh":
+      $backend = new backend($id);
+      $backend->refresh();
+      headline_admin_display();
       break;
     case "Add backend":
       $backend = new backend($id, $site, $url, $backend, $contact);
       $backend->add();
       // fall through:
     default:
-      headline_admin_main();
+      headline_admin_display();
   }
 }
 
diff --git a/modules/story.module b/modules/story.module
index 5a18671a1d8c2a037c7d0a1e12c57c791ce2aff0..3e7d6a8b29c787256da39059a30c6bb0204211a2 100644
--- a/modules/story.module
+++ b/modules/story.module
@@ -1,10 +1,28 @@
 <?
 
-$module = array("block" => "story_block",
+$module = array("cron" => "story_cron",
+                "help" => "story_help",
+                "block" => "story_block",
                 "admin" => "story_admin");
 
+function story_cron() {
+  $result = db_query("SELECT * FROM stories WHERE status = 3 AND timestamp <= ". time() ."");
+  while ($story = db_fetch_object($result)) {
+    db_query("UPDATE stories SET status = '1', timestamp = '". time() ."' WHERE id = '$story->id'");   
+  }
+}
+
+function story_help() {
+ ?>
+  <P><B>Scheduled stories</B>: stories that are scheduled to be automatically published at a given date and time.  Useful when you have to leave the site alone for a while or when you want to regulate the flow of new content.</P>
+  <P><B>Queued stories</B>: user-contributed stories are automatically whisked away to a submission queue for moderators to frown at it.  Moderators vote whether or not a story should be carried to the front page for discussion.</P>
+  <P><B>Posted stories</B>: published stories accessible to all visitors.</P>
+  <P><B>Dumped stories</B>: rejected stories that are no longer available to visitors.</P>
+ <?
+}
+
 function story_block() {
-  $result = db_query("select s.id, COUNT(s.id) as comments, s.subject from stories s left join comments c on s.id = c.sid WHERE s.status = 2 GROUP BY s.id ORDER BY comments DESC LIMIT 10");
+  $result = db_query("SELECT s.id, COUNT(s.id) AS comments, s.subject FROM stories s LEFT JOIN comments c ON s.id = c.sid WHERE s.status = 2 GROUP BY s.id ORDER BY comments DESC LIMIT 10");
   while ($story = db_fetch_object($result)) {
     $content .= "<LI><A HREF=\"discussion.php?id=$story->id\">$story->subject</A><BR><SMALL>(". format_plural($story->comments, "comment", "comments") .")</SMALL></LI>\n";
   }
@@ -15,7 +33,7 @@ function story_block() {
 
   unset($content);
 
-  $result = db_query("select s.id, COUNT(s.id) as comments, s.subject from stories s left join comments c on s.id = c.sid WHERE s.status = 2 AND ". time() ." - s.timestamp < 2419200 GROUP BY s.id ORDER BY comments DESC LIMIT 10");
+  $result = db_query("SELECT s.id, COUNT(s.id) AS comments, s.subject FROM stories s LEFT JOIN comments c ON s.id = c.sid WHERE s.status = 2 AND ". time() ." - s.timestamp < 2419200 GROUP BY s.id ORDER BY comments DESC LIMIT 10");
   while ($story = db_fetch_object($result)) {
     $content .= "<LI><A HREF=\"discussion.php?id=$story->id\">$story->subject</A><BR><SMALL>(". format_plural($story->comments, "comment", "comments") .")</SMALL></LI>\n";
   }
@@ -27,13 +45,68 @@ function story_block() {
   return $blocks;
 }
 
+function story_add() {
+  global $allowed_html, $categories;
+
+  $output .= "<FORM ACTION=\"admin.php?mod=story\" METHOD=\"post\">\n";
+ 
+  $output .= "<P>\n";
+  $output .= " <B>Subject:</B><BR>\n";
+  $output .= " <INPUT TYPE=\"text\" NAME=\"edit[subject]\" SIZE=\"50\" MAXLENGTH=\"60\"><BR>\n";
+  $output .= "</P>\n";
+
+  $output .= "<P><B>Category:</B><BR>\n";
+  $output .= " <SELECT NAME=\"edit[category]\">\n";  
+  for ($i = 0; $i < sizeof($categories); $i++) {
+    $output .= "  <OPTION VALUE=\"$categories[$i]\">$categories[$i]</OPTION>\n";  
+  }
+  $output .= " </SELECT>\n";
+  $output .= "</P>\n";
+
+  $output .= "<P>\n"; 
+  $output .= " <B>Abstract:</B><BR>\n";
+  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"10\" NAME=\"edit[abstract]\" MAXLENGTH=\"20\"></TEXTAREA><BR>\n";
+  $output .= " <SMALL><I>Allowed HTML tags: ". htmlspecialchars($allowed_html) .".</I></SMALL>\n";
+  $output .= "</P>\n";
+
+  $output .= "<P>\n"; 
+  $output .= " <B>Extended story:</B><BR>\n";
+  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"15\" NAME=\"edit[article]\"></TEXTAREA><BR>\n";
+  $output .= " <SMALL><I>Allowed HTML tags: ". htmlspecialchars($allowed_html) .".</I></SMALL>\n";
+  $output .= "</P>\n";
+
+  $output .= "<P>\n";
+  $output .= " <B>Status:</B><BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"3\">scheduled story for <INPUT TYPE=\"text\" NAME=\"edit[date]\" SIZE=\"30\" VALUE=\"". date("j F Y G:i") ."\"><BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"2\">posted story<BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"1\" CHECKED>queued story<BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"0\">dumped story<BR>\n";
+  $output .= " <SMALL><I>The textfield for scheduled stories expects a string containing an English date format of when you want to have your story automatically published.<BR>Example input: '". date("j F Y G:i") ."', '". date("m/d/y H:i") ."', '". date("F j, Y H:i") ."', ...</I></SMALL>\n";
+  $output .= "</P>\n";
+ 
+  $output .= "<P>\n";
+  $output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Add story\">\n";
+  $output .= "</P>\n";
+
+  $output .= "</FORM>\n";
+
+  print $output;
+}
+
+function story_add_save($edit) {
+  global $user;
+  $timestamp = ($edit[status] == 3 && strtotime($edit[date]) > time()) ? strtotime($edit[date]) : time();
+  db_query("INSERT INTO stories (author, subject, abstract, article, category, status, timestamp) VALUES ('$user->id', '". check_input($edit[subject]) ."', '". check_input($edit[abstract]) ."', '". check_input($edit[article]) ."', '". check_input($edit[category]) ."', '$edit[status]', '$timestamp')");
+  watchdog("story", "story: added '$edit[subject]'");
+}
+
 function story_edit($id) {
-  global $categories;
+  global $allowed_html, $categories;
 
   $result = db_query("SELECT s.*, u.userid FROM stories s LEFT JOIN users u ON s.author = u.id WHERE s.id = $id");
   $story = db_fetch_object($result);
 
-  $output .= "<FORM ACTION=\"admin.php?mod=story&op=save&id=$id\" METHOD=\"post\">\n";
+  $output .= "<FORM ACTION=\"admin.php?mod=story&id=$id\" METHOD=\"post\">\n";
 
   $output .= "<P>\n";
   $output .= " <B>Author:</B><BR>\n";
@@ -42,40 +115,43 @@ function story_edit($id) {
 
   $output .= "<P>\n";
   $output .= " <B>Subject:</B><BR>\n";
-  $output .= " <INPUT TYPE=\"text\" NAME=\"subject\" SIZE=\"50\" VALUE=\"". check_output(check_field($story->subject)) ."\"><BR>\n";
+  $output .= " <INPUT TYPE=\"text\" NAME=\"edit[subject]\" SIZE=\"50\" VALUE=\"". check_output(check_field($story->subject)) ."\"><BR>\n";
   $output .= "</P>\n";
 
-  $output .= "<P><B>Category:</B><BR>\n";
-  $output .= " <SELECT NAME=\"category\">\n";
+  $output .= "<P>\n";
+  $output .= " <B>Category:</B><BR>\n";
+  $output .= " <SELECT NAME=\"edit[category]\">\n";
   for ($i = 0; $i < sizeof($categories); $i++) {
-    $output .= "  <OPTION VALUE=\"$categories[$i]\" ";
-    if ($story->category == $categories[$i]) $output .= "SELECTED";
-    $output .= ">$categories[$i]</OPTION>\n";
+    $output .= "  <OPTION VALUE=\"$categories[$i]\"". ($story->category == $categories[$i] ? " SELECTED" : "") .">$categories[$i]</OPTION>\n";
   }
   $output .= "</SELECT>\n";
   $output .= "</P>\n";
 
   $output .= "<P>\n";
-  $output .= "<B>Abstract:</B><BR>\n";
-  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"10\" NAME=\"abstract\">". check_output($story->abstract) ."</TEXTAREA><BR>\n";
+  $output .= " <B>Abstract:</B><BR>\n";
+  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"10\" NAME=\"edit[abstract]\">". check_output($story->abstract) ."</TEXTAREA><BR>\n";
+  $output .= " <SMALL><I>Allowed HTML tags: ". htmlspecialchars($allowed_html) .".</I></SMALL>\n";
   $output .= "</P>\n";
 
   $output .= "<P>\n";
-  $output .= "<B>Editor's note/updates:</B><BR>\n";
-  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"10\" NAME=\"updates\">". check_output($story->updates) ."</TEXTAREA><BR>\n";
+  $output .= " <B>Editor's note/updates:</B><BR>\n";
+  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"10\" NAME=\"edit[updates]\">". check_output($story->updates) ."</TEXTAREA><BR>\n";
+  $output .= " <SMALL><I>Allowed HTML tags: ". htmlspecialchars($allowed_html) .".</I></SMALL>\n";
   $output .= "</P>\n";
 
   $output .= "<P>\n";
   $output .= " <B>Extended story:</B><BR>\n";
-  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"15\" NAME=\"article\">". check_output($story->article) ."</TEXTAREA><BR>\n";
+  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"15\" NAME=\"edit[article]\">". check_output($story->article) ."</TEXTAREA><BR>\n";
+  $output .= " <SMALL><I>Allowed HTML tags: ". htmlspecialchars($allowed_html) .".</I></SMALL>\n";
   $output .= "</P>\n";
 
-  $output .= "<P><B>Status:</B><BR>\n";
-  $output .= " <SELECT NAME=\"status\">\n";
-  $output .= ($story->status == 0) ? "  <OPTION VALUE=\"0\" SELECTED>Deleted story</OPTION>\n" : "  <OPTION VALUE=\"0\">Deleted story </OPTION>\n";
-  $output .= ($story->status == 1) ? "  <OPTION VALUE=\"1\" SELECTED>Pending story</OPTION>\n" : "  <OPTION VALUE=\"1\">Pending story</OPTION>\n";
-  $output .= ($story->status == 2) ? "  <OPTION VALUE=\"2\" SELECTED>Public story</OPTION>\n" : "  <OPTION VALUE=\"2\">Public story</OPTION>\n";
-  $output .= "</SELECT>\n";
+  $output .= "<P>\n";
+  $output .= " <B>Status:</B><BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"3\"". ($story->status == 3 ? " CHECKED" : "") .">scheduled story for <INPUT TYPE=\"text\" NAME=\"edit[date]\" SIZE=\"30\" VALUE=\"". date("j F Y G:i", $story->timestamp) ."\"><BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"2\"". ($story->status == 2 ? " CHECKED" : "") .">posted story<BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"1\"". ($story->status == 1 ? " CHECKED" : "") .">queued story<BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"0\"". ($story->status == 0 ? " CHECKED" : "") .">dumped story<BR>\n";
+  $output .= " <SMALL><I>The textfield for scheduled stories expects a string containing an English date format of when you want to have your story automatically published.<BR>Example input: '". date("j F Y G:i") ."', '". date("m/d/y H:i") ."', '". date("F j, Y H:i") ."', ...</I></SMALL>\n";
   $output .= "</P>\n";
 
   $output .= "<P>\n";
@@ -86,63 +162,70 @@ function story_edit($id) {
   print $output;
 }
 
-function story_save($id, $subject, $abstract, $updates, $article, $category, $status) {
-  db_query("UPDATE stories SET subject = '". check_input($subject) ."', abstract = '". check_input($abstract) ."', updates = '". check_input($updates) ."', article = '". check_input($article) ."', category = '". check_input($category) ."', status = '$status' WHERE id = $id");
+function story_edit_save($id, $edit) {
+  if ($edit[status] == 3 && strtotime($edit[date]) > time()) db_query("UPDATE stories SET subject = '". check_input($edit[subject]) ."', abstract = '". check_input($edit[abstract]) ."', updates = '". check_input($edit[updates]) ."', article = '". check_input($edit[article]) ."', category = '". check_input($edit[category]) ."', status = '$edit[status]', timestamp = '". strtotime($edit[date]) ."' WHERE id = '$id'");
+  else db_query("UPDATE stories SET subject = '". check_input($edit[subject]) ."', abstract = '". check_input($edit[abstract]) ."', updates = '". check_input($edit[updates]) ."', article = '". check_input($edit[article]) ."', category = '". check_input($edit[category]) ."', status = '$edit[status]' WHERE id = '$id'");
   watchdog("message", "story: modified `$subject'");
 }
 
-function story_display($order = "date") {
-  // Initialize variables:
-  $status = array("deleted", "pending", "public");
-  $fields = array("author" => "author", "category" => "category", "date" => "timestamp DESC", "status" => "status DESC");
-
-  // Perform SQL query:
-  $result = db_query("SELECT s.*, u.userid FROM stories s LEFT JOIN users u ON u.id = s.author ORDER BY s.$fields[$order]");
-  
-  // Display stories:
+function story_display() {  
   $output .= "<TABLE BORDER=\"1\" CELLPADDING=\"2\" CELLSPACING=\"2\">\n";
-  $output .= " <TR>\n";
-  $output .= "  <TH ALIGN=\"right\" COLSPAN=\"5\">\n";
-  $output .= "   <FORM ACTION=\"admin.php?mod=story\" METHOD=\"post\">\n";
-  $output .= "    <SELECT NAME=\"order\">\n";
-  foreach ($fields as $key=>$value) {
-    $output .= "     <OPTION VALUE=\"$key\"". ($key == $order ? " SELECTED" : "") .">Sort by $key</OPTION>\n";
+
+  // Pending stories:
+  $result = db_query("SELECT s.*, u.userid FROM stories s LEFT JOIN users u ON u.id = s.author WHERE s.status = 1 ORDER BY timestamp DESC");
+  $output .= " <TR><TH COLSPAN=\"4\">queued stories</TH></TR>\n";
+  while ($story = db_fetch_object($result)) {
+    $output .= " <TR><TD><A HREF=\"discussion.php?id=$story->id\">". check_output($story->subject) ."</A></TD><TD>". format_username($story->userid, 1) ."</TD><TD>votes: $story->votes, score: $story->score</TD><TD ALIGN=\"center\"><A HREF=\"admin.php?mod=story&op=edit&id=$story->id\">edit</A></TD></TR>\n";
   }
-  $output .= "    </SELECT>\n";
-  $output .= "    <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Update\">\n";
-  $output .= "   </FORM>\n";
-  $output .= "  </TH>\n";
-  $output .= " </TR>\n";
-
-  $output .= " <TR>\n";
-  $output .= "  <TH>subject</TH>\n";
-  $output .= "  <TH>author</TH>\n";
-  $output .= "  <TH>category</TH>\n";
-  $output .= "  <TH>status</TH>\n";
-  $output .= "  <TH>operations</TH>\n";
-  $output .= " </TR>\n";
 
+  // Scheduled stories:
+  $result = db_query("SELECT s.*, u.userid FROM stories s LEFT JOIN users u ON u.id = s.author WHERE s.status = 3 ORDER BY timestamp");
+  $output .= " <TR><TH COLSPAN=\"4\">scheduled stories</TH></TR>\n";
   while ($story = db_fetch_object($result)) {
-    $output .= " <TR><TD><A HREF=\"discussion.php?id=$story->id\">". check_output($story->subject) ."</A></TD><TD>". format_username($story->userid, 1) ."</TD><TD>$story->category</TD><TD ALIGN=\"center\">". $status[$story->status] ."</TD><TD ALIGN=\"center\"><A HREF=\"admin.php?mod=story&op=edit&id=$story->id\">edit</A></TD></TR>\n";
+    $output .= " <TR><TD><A HREF=\"discussion.php?id=$story->id\">". check_output($story->subject) ."</A></TD><TD>". format_username($story->userid, 1) ."</TD><TD>". date("D, m/d/Y H:i", $story->timestamp) ." - ". format_interval($story->timestamp - time()) ." left</TD><TD ALIGN=\"center\"><A HREF=\"admin.php?mod=story&op=edit&id=$story->id\">edit</A></TD></TR>\n";
   }
 
+  // Dumped stories:
+  $result = db_query("SELECT s.*, u.userid FROM stories s LEFT JOIN users u ON u.id = s.author WHERE s.status = 0 ORDER BY timestamp DESC LIMIT 5");
+  $output .= " <TR><TH COLSPAN=\"4\">dumped stories</TTH></TR>\n";
+  while ($story = db_fetch_object($result)) {
+    $output .= " <TR><TD><A HREF=\"discussion.php?id=$story->id\">". check_output($story->subject) ."</A></TD><TD>". format_username($story->userid, 1) ."</TD><TD>$story->category</TD><TD ALIGN=\"center\"><A HREF=\"admin.php?mod=story&op=edit&id=$story->id\">edit</A></TD></TR>\n";
+  }
+
+  // Posted stories:
+  $result = db_query("SELECT s.*, u.userid FROM stories s LEFT JOIN users u ON u.id = s.author WHERE s.status = 2 ORDER BY timestamp DESC LIMIT 15");
+  $output .= " <TR><TH COLSPAN=\"4\">posted stories</TH></TR>\n";
+  while ($story = db_fetch_object($result)) {
+    $output .= " <TR><TD><A HREF=\"discussion.php?id=$story->id\">". check_output($story->subject) ."</A></TD><TD>". format_username($story->userid, 1) ."</TD><TD>$story->category</TD><TD ALIGN=\"center\"><A HREF=\"admin.php?mod=story&op=edit&id=$story->id\">edit</A></TD></TR>\n";
+  }
+ 
   $output .= "</TABLE>\n";
  
   print $output;
 }
 
 function story_admin() {
-  global $op, $id, $subject, $abstract, $updates, $article, $category, $status, $order;
+  global $op, $id, $edit;
+
+  print "<SMALL><A HREF=\"admin.php?mod=story&op=add\">add new story</A> | <A HREF=\"admin.php?mod=story\">overview</A> | <A HREF=\"admin.php?mod=story&op=help\">help</A></SMALL><HR>\n";
+
   switch ($op) {
+    case "add":
+      story_add();
+      break;
     case "edit":
       story_edit($id);
       break;
-    case "Save story":
-      story_save($id, $subject, $abstract, $updates, $article, $category, $status);
-      story_edit($id);
+    case "help":
+      story_help();
       break;
-    case "Update":
-      story_display($order);
+    case "Add story":
+      story_add_save($edit);
+      story_display();
+      break;
+    case "Save story":
+      story_edit_save($id, $edit);
+      story_display();
       break;
     default:
       story_display();
diff --git a/modules/story/story.module b/modules/story/story.module
index 5a18671a1d8c2a037c7d0a1e12c57c791ce2aff0..3e7d6a8b29c787256da39059a30c6bb0204211a2 100644
--- a/modules/story/story.module
+++ b/modules/story/story.module
@@ -1,10 +1,28 @@
 <?
 
-$module = array("block" => "story_block",
+$module = array("cron" => "story_cron",
+                "help" => "story_help",
+                "block" => "story_block",
                 "admin" => "story_admin");
 
+function story_cron() {
+  $result = db_query("SELECT * FROM stories WHERE status = 3 AND timestamp <= ". time() ."");
+  while ($story = db_fetch_object($result)) {
+    db_query("UPDATE stories SET status = '1', timestamp = '". time() ."' WHERE id = '$story->id'");   
+  }
+}
+
+function story_help() {
+ ?>
+  <P><B>Scheduled stories</B>: stories that are scheduled to be automatically published at a given date and time.  Useful when you have to leave the site alone for a while or when you want to regulate the flow of new content.</P>
+  <P><B>Queued stories</B>: user-contributed stories are automatically whisked away to a submission queue for moderators to frown at it.  Moderators vote whether or not a story should be carried to the front page for discussion.</P>
+  <P><B>Posted stories</B>: published stories accessible to all visitors.</P>
+  <P><B>Dumped stories</B>: rejected stories that are no longer available to visitors.</P>
+ <?
+}
+
 function story_block() {
-  $result = db_query("select s.id, COUNT(s.id) as comments, s.subject from stories s left join comments c on s.id = c.sid WHERE s.status = 2 GROUP BY s.id ORDER BY comments DESC LIMIT 10");
+  $result = db_query("SELECT s.id, COUNT(s.id) AS comments, s.subject FROM stories s LEFT JOIN comments c ON s.id = c.sid WHERE s.status = 2 GROUP BY s.id ORDER BY comments DESC LIMIT 10");
   while ($story = db_fetch_object($result)) {
     $content .= "<LI><A HREF=\"discussion.php?id=$story->id\">$story->subject</A><BR><SMALL>(". format_plural($story->comments, "comment", "comments") .")</SMALL></LI>\n";
   }
@@ -15,7 +33,7 @@ function story_block() {
 
   unset($content);
 
-  $result = db_query("select s.id, COUNT(s.id) as comments, s.subject from stories s left join comments c on s.id = c.sid WHERE s.status = 2 AND ". time() ." - s.timestamp < 2419200 GROUP BY s.id ORDER BY comments DESC LIMIT 10");
+  $result = db_query("SELECT s.id, COUNT(s.id) AS comments, s.subject FROM stories s LEFT JOIN comments c ON s.id = c.sid WHERE s.status = 2 AND ". time() ." - s.timestamp < 2419200 GROUP BY s.id ORDER BY comments DESC LIMIT 10");
   while ($story = db_fetch_object($result)) {
     $content .= "<LI><A HREF=\"discussion.php?id=$story->id\">$story->subject</A><BR><SMALL>(". format_plural($story->comments, "comment", "comments") .")</SMALL></LI>\n";
   }
@@ -27,13 +45,68 @@ function story_block() {
   return $blocks;
 }
 
+function story_add() {
+  global $allowed_html, $categories;
+
+  $output .= "<FORM ACTION=\"admin.php?mod=story\" METHOD=\"post\">\n";
+ 
+  $output .= "<P>\n";
+  $output .= " <B>Subject:</B><BR>\n";
+  $output .= " <INPUT TYPE=\"text\" NAME=\"edit[subject]\" SIZE=\"50\" MAXLENGTH=\"60\"><BR>\n";
+  $output .= "</P>\n";
+
+  $output .= "<P><B>Category:</B><BR>\n";
+  $output .= " <SELECT NAME=\"edit[category]\">\n";  
+  for ($i = 0; $i < sizeof($categories); $i++) {
+    $output .= "  <OPTION VALUE=\"$categories[$i]\">$categories[$i]</OPTION>\n";  
+  }
+  $output .= " </SELECT>\n";
+  $output .= "</P>\n";
+
+  $output .= "<P>\n"; 
+  $output .= " <B>Abstract:</B><BR>\n";
+  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"10\" NAME=\"edit[abstract]\" MAXLENGTH=\"20\"></TEXTAREA><BR>\n";
+  $output .= " <SMALL><I>Allowed HTML tags: ". htmlspecialchars($allowed_html) .".</I></SMALL>\n";
+  $output .= "</P>\n";
+
+  $output .= "<P>\n"; 
+  $output .= " <B>Extended story:</B><BR>\n";
+  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"15\" NAME=\"edit[article]\"></TEXTAREA><BR>\n";
+  $output .= " <SMALL><I>Allowed HTML tags: ". htmlspecialchars($allowed_html) .".</I></SMALL>\n";
+  $output .= "</P>\n";
+
+  $output .= "<P>\n";
+  $output .= " <B>Status:</B><BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"3\">scheduled story for <INPUT TYPE=\"text\" NAME=\"edit[date]\" SIZE=\"30\" VALUE=\"". date("j F Y G:i") ."\"><BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"2\">posted story<BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"1\" CHECKED>queued story<BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"0\">dumped story<BR>\n";
+  $output .= " <SMALL><I>The textfield for scheduled stories expects a string containing an English date format of when you want to have your story automatically published.<BR>Example input: '". date("j F Y G:i") ."', '". date("m/d/y H:i") ."', '". date("F j, Y H:i") ."', ...</I></SMALL>\n";
+  $output .= "</P>\n";
+ 
+  $output .= "<P>\n";
+  $output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Add story\">\n";
+  $output .= "</P>\n";
+
+  $output .= "</FORM>\n";
+
+  print $output;
+}
+
+function story_add_save($edit) {
+  global $user;
+  $timestamp = ($edit[status] == 3 && strtotime($edit[date]) > time()) ? strtotime($edit[date]) : time();
+  db_query("INSERT INTO stories (author, subject, abstract, article, category, status, timestamp) VALUES ('$user->id', '". check_input($edit[subject]) ."', '". check_input($edit[abstract]) ."', '". check_input($edit[article]) ."', '". check_input($edit[category]) ."', '$edit[status]', '$timestamp')");
+  watchdog("story", "story: added '$edit[subject]'");
+}
+
 function story_edit($id) {
-  global $categories;
+  global $allowed_html, $categories;
 
   $result = db_query("SELECT s.*, u.userid FROM stories s LEFT JOIN users u ON s.author = u.id WHERE s.id = $id");
   $story = db_fetch_object($result);
 
-  $output .= "<FORM ACTION=\"admin.php?mod=story&op=save&id=$id\" METHOD=\"post\">\n";
+  $output .= "<FORM ACTION=\"admin.php?mod=story&id=$id\" METHOD=\"post\">\n";
 
   $output .= "<P>\n";
   $output .= " <B>Author:</B><BR>\n";
@@ -42,40 +115,43 @@ function story_edit($id) {
 
   $output .= "<P>\n";
   $output .= " <B>Subject:</B><BR>\n";
-  $output .= " <INPUT TYPE=\"text\" NAME=\"subject\" SIZE=\"50\" VALUE=\"". check_output(check_field($story->subject)) ."\"><BR>\n";
+  $output .= " <INPUT TYPE=\"text\" NAME=\"edit[subject]\" SIZE=\"50\" VALUE=\"". check_output(check_field($story->subject)) ."\"><BR>\n";
   $output .= "</P>\n";
 
-  $output .= "<P><B>Category:</B><BR>\n";
-  $output .= " <SELECT NAME=\"category\">\n";
+  $output .= "<P>\n";
+  $output .= " <B>Category:</B><BR>\n";
+  $output .= " <SELECT NAME=\"edit[category]\">\n";
   for ($i = 0; $i < sizeof($categories); $i++) {
-    $output .= "  <OPTION VALUE=\"$categories[$i]\" ";
-    if ($story->category == $categories[$i]) $output .= "SELECTED";
-    $output .= ">$categories[$i]</OPTION>\n";
+    $output .= "  <OPTION VALUE=\"$categories[$i]\"". ($story->category == $categories[$i] ? " SELECTED" : "") .">$categories[$i]</OPTION>\n";
   }
   $output .= "</SELECT>\n";
   $output .= "</P>\n";
 
   $output .= "<P>\n";
-  $output .= "<B>Abstract:</B><BR>\n";
-  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"10\" NAME=\"abstract\">". check_output($story->abstract) ."</TEXTAREA><BR>\n";
+  $output .= " <B>Abstract:</B><BR>\n";
+  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"10\" NAME=\"edit[abstract]\">". check_output($story->abstract) ."</TEXTAREA><BR>\n";
+  $output .= " <SMALL><I>Allowed HTML tags: ". htmlspecialchars($allowed_html) .".</I></SMALL>\n";
   $output .= "</P>\n";
 
   $output .= "<P>\n";
-  $output .= "<B>Editor's note/updates:</B><BR>\n";
-  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"10\" NAME=\"updates\">". check_output($story->updates) ."</TEXTAREA><BR>\n";
+  $output .= " <B>Editor's note/updates:</B><BR>\n";
+  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"10\" NAME=\"edit[updates]\">". check_output($story->updates) ."</TEXTAREA><BR>\n";
+  $output .= " <SMALL><I>Allowed HTML tags: ". htmlspecialchars($allowed_html) .".</I></SMALL>\n";
   $output .= "</P>\n";
 
   $output .= "<P>\n";
   $output .= " <B>Extended story:</B><BR>\n";
-  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"15\" NAME=\"article\">". check_output($story->article) ."</TEXTAREA><BR>\n";
+  $output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"15\" NAME=\"edit[article]\">". check_output($story->article) ."</TEXTAREA><BR>\n";
+  $output .= " <SMALL><I>Allowed HTML tags: ". htmlspecialchars($allowed_html) .".</I></SMALL>\n";
   $output .= "</P>\n";
 
-  $output .= "<P><B>Status:</B><BR>\n";
-  $output .= " <SELECT NAME=\"status\">\n";
-  $output .= ($story->status == 0) ? "  <OPTION VALUE=\"0\" SELECTED>Deleted story</OPTION>\n" : "  <OPTION VALUE=\"0\">Deleted story </OPTION>\n";
-  $output .= ($story->status == 1) ? "  <OPTION VALUE=\"1\" SELECTED>Pending story</OPTION>\n" : "  <OPTION VALUE=\"1\">Pending story</OPTION>\n";
-  $output .= ($story->status == 2) ? "  <OPTION VALUE=\"2\" SELECTED>Public story</OPTION>\n" : "  <OPTION VALUE=\"2\">Public story</OPTION>\n";
-  $output .= "</SELECT>\n";
+  $output .= "<P>\n";
+  $output .= " <B>Status:</B><BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"3\"". ($story->status == 3 ? " CHECKED" : "") .">scheduled story for <INPUT TYPE=\"text\" NAME=\"edit[date]\" SIZE=\"30\" VALUE=\"". date("j F Y G:i", $story->timestamp) ."\"><BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"2\"". ($story->status == 2 ? " CHECKED" : "") .">posted story<BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"1\"". ($story->status == 1 ? " CHECKED" : "") .">queued story<BR>\n";
+  $output .= " <INPUT TYPE=\"radio\" NAME=\"edit[status]\" VALUE=\"0\"". ($story->status == 0 ? " CHECKED" : "") .">dumped story<BR>\n";
+  $output .= " <SMALL><I>The textfield for scheduled stories expects a string containing an English date format of when you want to have your story automatically published.<BR>Example input: '". date("j F Y G:i") ."', '". date("m/d/y H:i") ."', '". date("F j, Y H:i") ."', ...</I></SMALL>\n";
   $output .= "</P>\n";
 
   $output .= "<P>\n";
@@ -86,63 +162,70 @@ function story_edit($id) {
   print $output;
 }
 
-function story_save($id, $subject, $abstract, $updates, $article, $category, $status) {
-  db_query("UPDATE stories SET subject = '". check_input($subject) ."', abstract = '". check_input($abstract) ."', updates = '". check_input($updates) ."', article = '". check_input($article) ."', category = '". check_input($category) ."', status = '$status' WHERE id = $id");
+function story_edit_save($id, $edit) {
+  if ($edit[status] == 3 && strtotime($edit[date]) > time()) db_query("UPDATE stories SET subject = '". check_input($edit[subject]) ."', abstract = '". check_input($edit[abstract]) ."', updates = '". check_input($edit[updates]) ."', article = '". check_input($edit[article]) ."', category = '". check_input($edit[category]) ."', status = '$edit[status]', timestamp = '". strtotime($edit[date]) ."' WHERE id = '$id'");
+  else db_query("UPDATE stories SET subject = '". check_input($edit[subject]) ."', abstract = '". check_input($edit[abstract]) ."', updates = '". check_input($edit[updates]) ."', article = '". check_input($edit[article]) ."', category = '". check_input($edit[category]) ."', status = '$edit[status]' WHERE id = '$id'");
   watchdog("message", "story: modified `$subject'");
 }
 
-function story_display($order = "date") {
-  // Initialize variables:
-  $status = array("deleted", "pending", "public");
-  $fields = array("author" => "author", "category" => "category", "date" => "timestamp DESC", "status" => "status DESC");
-
-  // Perform SQL query:
-  $result = db_query("SELECT s.*, u.userid FROM stories s LEFT JOIN users u ON u.id = s.author ORDER BY s.$fields[$order]");
-  
-  // Display stories:
+function story_display() {  
   $output .= "<TABLE BORDER=\"1\" CELLPADDING=\"2\" CELLSPACING=\"2\">\n";
-  $output .= " <TR>\n";
-  $output .= "  <TH ALIGN=\"right\" COLSPAN=\"5\">\n";
-  $output .= "   <FORM ACTION=\"admin.php?mod=story\" METHOD=\"post\">\n";
-  $output .= "    <SELECT NAME=\"order\">\n";
-  foreach ($fields as $key=>$value) {
-    $output .= "     <OPTION VALUE=\"$key\"". ($key == $order ? " SELECTED" : "") .">Sort by $key</OPTION>\n";
+
+  // Pending stories:
+  $result = db_query("SELECT s.*, u.userid FROM stories s LEFT JOIN users u ON u.id = s.author WHERE s.status = 1 ORDER BY timestamp DESC");
+  $output .= " <TR><TH COLSPAN=\"4\">queued stories</TH></TR>\n";
+  while ($story = db_fetch_object($result)) {
+    $output .= " <TR><TD><A HREF=\"discussion.php?id=$story->id\">". check_output($story->subject) ."</A></TD><TD>". format_username($story->userid, 1) ."</TD><TD>votes: $story->votes, score: $story->score</TD><TD ALIGN=\"center\"><A HREF=\"admin.php?mod=story&op=edit&id=$story->id\">edit</A></TD></TR>\n";
   }
-  $output .= "    </SELECT>\n";
-  $output .= "    <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Update\">\n";
-  $output .= "   </FORM>\n";
-  $output .= "  </TH>\n";
-  $output .= " </TR>\n";
-
-  $output .= " <TR>\n";
-  $output .= "  <TH>subject</TH>\n";
-  $output .= "  <TH>author</TH>\n";
-  $output .= "  <TH>category</TH>\n";
-  $output .= "  <TH>status</TH>\n";
-  $output .= "  <TH>operations</TH>\n";
-  $output .= " </TR>\n";
 
+  // Scheduled stories:
+  $result = db_query("SELECT s.*, u.userid FROM stories s LEFT JOIN users u ON u.id = s.author WHERE s.status = 3 ORDER BY timestamp");
+  $output .= " <TR><TH COLSPAN=\"4\">scheduled stories</TH></TR>\n";
   while ($story = db_fetch_object($result)) {
-    $output .= " <TR><TD><A HREF=\"discussion.php?id=$story->id\">". check_output($story->subject) ."</A></TD><TD>". format_username($story->userid, 1) ."</TD><TD>$story->category</TD><TD ALIGN=\"center\">". $status[$story->status] ."</TD><TD ALIGN=\"center\"><A HREF=\"admin.php?mod=story&op=edit&id=$story->id\">edit</A></TD></TR>\n";
+    $output .= " <TR><TD><A HREF=\"discussion.php?id=$story->id\">". check_output($story->subject) ."</A></TD><TD>". format_username($story->userid, 1) ."</TD><TD>". date("D, m/d/Y H:i", $story->timestamp) ." - ". format_interval($story->timestamp - time()) ." left</TD><TD ALIGN=\"center\"><A HREF=\"admin.php?mod=story&op=edit&id=$story->id\">edit</A></TD></TR>\n";
   }
 
+  // Dumped stories:
+  $result = db_query("SELECT s.*, u.userid FROM stories s LEFT JOIN users u ON u.id = s.author WHERE s.status = 0 ORDER BY timestamp DESC LIMIT 5");
+  $output .= " <TR><TH COLSPAN=\"4\">dumped stories</TTH></TR>\n";
+  while ($story = db_fetch_object($result)) {
+    $output .= " <TR><TD><A HREF=\"discussion.php?id=$story->id\">". check_output($story->subject) ."</A></TD><TD>". format_username($story->userid, 1) ."</TD><TD>$story->category</TD><TD ALIGN=\"center\"><A HREF=\"admin.php?mod=story&op=edit&id=$story->id\">edit</A></TD></TR>\n";
+  }
+
+  // Posted stories:
+  $result = db_query("SELECT s.*, u.userid FROM stories s LEFT JOIN users u ON u.id = s.author WHERE s.status = 2 ORDER BY timestamp DESC LIMIT 15");
+  $output .= " <TR><TH COLSPAN=\"4\">posted stories</TH></TR>\n";
+  while ($story = db_fetch_object($result)) {
+    $output .= " <TR><TD><A HREF=\"discussion.php?id=$story->id\">". check_output($story->subject) ."</A></TD><TD>". format_username($story->userid, 1) ."</TD><TD>$story->category</TD><TD ALIGN=\"center\"><A HREF=\"admin.php?mod=story&op=edit&id=$story->id\">edit</A></TD></TR>\n";
+  }
+ 
   $output .= "</TABLE>\n";
  
   print $output;
 }
 
 function story_admin() {
-  global $op, $id, $subject, $abstract, $updates, $article, $category, $status, $order;
+  global $op, $id, $edit;
+
+  print "<SMALL><A HREF=\"admin.php?mod=story&op=add\">add new story</A> | <A HREF=\"admin.php?mod=story\">overview</A> | <A HREF=\"admin.php?mod=story&op=help\">help</A></SMALL><HR>\n";
+
   switch ($op) {
+    case "add":
+      story_add();
+      break;
     case "edit":
       story_edit($id);
       break;
-    case "Save story":
-      story_save($id, $subject, $abstract, $updates, $article, $category, $status);
-      story_edit($id);
+    case "help":
+      story_help();
       break;
-    case "Update":
-      story_display($order);
+    case "Add story":
+      story_add_save($edit);
+      story_display();
+      break;
+    case "Save story":
+      story_edit_save($id, $edit);
+      story_display();
       break;
     default:
       story_display();
diff --git a/submission.php b/submission.php
index b80f2b437c5c36454517015bca2d4d398b8fd1b7..148cfb9a20e616dd6e685a7eda162d4899fdf053 100644
--- a/submission.php
+++ b/submission.php
@@ -3,7 +3,7 @@
 include "includes/submission.inc";
 include "includes/common.inc";
 
-function submission_displayMain() {
+function submission_display_main() {
   global $PHP_SELF, $theme, $user;
 
   // Perform query:
@@ -23,7 +23,7 @@ function submission_displayMain() {
   $theme->footer();
 }
 
-function submission_displayItem($id) {
+function submission_display_item($id) {
   global $PHP_SELF, $theme, $user, $submission_votes;
 
   if ($vote = user_getHistory($user->history, "s$id")) {
@@ -67,14 +67,14 @@ function submission_displayItem($id) {
 if ($user->id) {
   switch($op) {
     case "view":
-      submission_displayItem($id);
+      submission_display_item($id);
       break;
     case "Vote";
       submission_vote($id, $vote, $comment);
-      submission_displayItem($id);
+      submission_display_item($id);
       break;
     default:
-      submission_displayMain();
+      submission_display_main();
       break;
   }
 }
diff --git a/submit.php b/submit.php
index dac2bc182014539d559c61176aa74d24b88acb34..5d7711a41eb233e7c8d78dd845595de359fbf155 100644
--- a/submit.php
+++ b/submit.php
@@ -130,7 +130,7 @@ function submit_submit($subject, $abstract, $article, $category) {
   global $user, $theme;
 
   // Add log entry:
-  watchdog("story", "added new story with subject `$subject'");
+  watchdog("story", "story: added '$subject'");
   
   // Add submission to SQL table:
   db_query("INSERT INTO stories (author, subject, abstract, article, category, timestamp) VALUES ('$user->id', '". check_input($subject) ."', '". check_input($abstract) ."', '". check_input($article) ."', '". check_input($category) ."', '". time() ."')");