Commit c1a88d5d authored by Dries's avatar Dries

Again, a large batch of updates - I'm twisting things around here:

 1. improved .htaccess to be more "secure": to keep prying
    eyes out

 2. rewrote the administration section from scratch using a
    modular approach

 3. improved the information gathered by error.php - we can
    now (hopefully) track what bots are crawling us.

 4. fixed a bug in submit.php, fixed a bug in theme zaphod,
    fixed a bug in theme marvin.

 5. rewrote cron from scratch - it now interfaces with
    modules as it should have been from the beginning.
    Very cool if you ask me - it can use UNIX/Linux
    crontabs.

 6. updated widget.inc to be module aware - needs more
    work though - maybe this afternoon?

 7. updated most modules: small bugfixes, improvements, and
    even the documentation

 8. removed diary.php and made it a module - you can now
    run a drop.org site without a diary system if someone
    would prefer so

 9. updated all themes to use the new modules where
    appropriate

 10. added a robots.txt because the error message in the
     watchdog become annoying.

 11. added the new configuration system (mutliple vhosts
     on the same source tree) - use hostname.conf instead
     of config.inc

 12. removed calendar.inc and made it a module

 13. added format_interval() to functions.inc (UnConeD)

 14. whatever I forgot ...
parent 8a778619
......@@ -7,26 +7,30 @@
ForceType application/x-httpd-php
</Files>
# Protect .inc files:
# .inc files can be read from the web so make sure we keep it
# away from the casual prying eyes. Especially `config.inc'.
<Files *.inc>
# Protect includes-directory:
<Files *includes>
order deny,allow
deny from all
</Files>
# Protect CVS directories:
<Files *CVS>
# Protect modules-directory:
<Files *modules>
order deny,allow
deny from all
</Files>
# Protect theme directories:
# Protect themes-directory:
<Files *themes>
order deny,allow
deny from all
</Files>
# Protect CVS directories:
<Files *CVS>
order deny,allow
deny from all
</Files>
# Customized server error messages:
ErrorDocument 400 /error.php
ErrorDocument 402 /error.php
......@@ -47,4 +51,3 @@ ErrorDocument 500 /error.php
php_value session.gc_maxlifetime 2000000
php_value session.cache_expire 200000
</IfModule>
......@@ -254,7 +254,7 @@ function account_user($uname) {
$result = db_query("SELECT d.* FROM diaries d LEFT JOIN users u ON u.id = d.author WHERE u.userid = '$uname' AND d.timestamp > ". (time() - 1209600) ." ORDER BY id DESC LIMIT 2");
while ($diary = db_fetch_object($result)) {
$box3 .= "<DL><DT><B>". date("l, F jS", $diary->timestamp) .":</B></DT><DD><P>". check_output($diary->text) ."</P><P>[ <A HREF=\"diary.php?op=view&name=$uname\">more</A> ]</P></DD></DL>\n";
$box3 .= "<DL><DT><B>". date("l, F jS", $diary->timestamp) .":</B></DT><DD><P>". check_output($diary->text) ."</P><P>[ <A HREF=\"module.php?mod=diary&op=view&name=$uname\">more</A> ]</P></DD></DL>\n";
$diaries++;
}
......
......@@ -4,6 +4,7 @@
if (!$user->id || $user->id > 4) exit();
include "includes/admin.inc";
include "includes/cron.inc";
// display admin header:
admin_header();
......@@ -17,6 +18,7 @@
}
else {
include_once "modules/$filename.module";
if ($module["cron"] && !cron_get($filename)) cron_set($filename, 172800);
if ($module["admin"]) $output .= "<A HREF=\"admin.php?mod=$filename\">$filename</A> | ";
}
}
......
<?
include "includes/theme.inc";
include "includes/cron.inc";
$result = db_query("SELECT * FROM cron");
while ($cron = db_fetch_object($result)) {
if (time() - $cron->timestamp > $cron->scheduled) cron_execute($cron);
}
cron_run();
?>
<?
include "includes/theme.inc";
function diary_overview($num = 20) {
global $theme, $user;
$result = db_query("SELECT d.*, u.userid FROM diaries d LEFT JOIN users u ON d.author = u.id ORDER BY d.timestamp DESC LIMIT $num");
$output .= "<P>This part of the website is dedicated to providing easy to write and easy to read online diaries or journals filled with daily thoughts, poetry, boneless blather, spiritual theories, intimate details, valuable experiences, cynical rants, semi-coherent comments, writing experiments, artistic babblings, critics on actuality, fresh insights, diverse dreams, chronicles and general madness available for general human consumption.</P>";
while ($diary = db_fetch_object($result)) {
if ($time != date("F jS", $diary->timestamp)) {
$output .= "<B>". date("l, F jS", $diary->timestamp) ."</B>\n";
$time = date("F jS", $diary->timestamp);
}
$output .= "<DL>\n";
$output .= " <DD><P><B>$diary->userid wrote:</B></P></DD>\n";
$output .= " <DL>\n";
$output .= " <DD><P>". check_output($diary->text, 1) ."</P><P>[ <A HREF=\"diary.php?op=view&name=$diary->userid\">more</A> ]</P></DD>\n";
$output .= " </DL>\n";
$output .= "</DL>\n";
}
$theme->header();
$theme->box("Online diary", $output);
$theme->footer();
}
function diary_entry($timestamp, $text, $id = 0) {
if ($id) {
$output .= "<DL>\n";
$output .= " <DT><B>". date("l, F jS", $timestamp) .":</B> </DT>\n";
$output .= " <DD><P>[ <A HREF=\"diary.php?op=edit&id=$id\">edit</A> ]</P><P>". check_output($text, 1) ."</P></DD>\n";
$output .= "</DL>\n";
}
else {
$output .= "<DL>\n";
$output .= " <DT><B>". date("l, F jS", $timestamp) .":</B></DT>\n";
$output .= " <DD><P>". check_output($text, 1) ."</P></DD>\n";
$output .= "</DL>\n";
}
return $output;
}
function diary_display($username) {
global $theme, $user;
$result = db_query("SELECT d.*, u.userid FROM diaries d LEFT JOIN users u ON d.author = u.id WHERE u.userid = '$username' ORDER BY timestamp DESC");
if ($username == $user->userid) {
$output .= diary_entry(time(), "<BIG><A HREF=\"diary.php?op=add\">Add new diary entry!</A></BIG><P>");
while ($diary = db_fetch_object($result)) $output .= diary_entry($diary->timestamp, $diary->text, $diary->id);
}
else {
$output .= "<P>". format_username($username) ."'s diary:</P>\n";
while ($diary = db_fetch_object($result)) $output .= diary_entry($diary->timestamp, $diary->text);
}
$theme->header();
$theme->box("$username's online diary", $output);
$theme->footer();
}
function diary_add() {
global $theme, $user, $allowed_html;
$output .= "<FORM ACTION=\"diary.php\" METHOD=\"post\">\n";
$output .= "<P>\n";
$output .= " <B>Enter new diary entry:</B><BR>\n";
$output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"15\" NAME=\"text\" MAXLENGTH=\"20\"></TEXTAREA><BR>\n";
$output .= " <SMALL><I>Allowed HTML tags: ". htmlspecialchars($allowed_html) .".</I></SMALL>\n";
$output .= "</P>\n";
$output .= "<P>\n";
$output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Preview diary entry\">\n";
$output .= "</P>\n";
$output .= "</FORM>\n";
$theme->header();
$theme->box("Online diary", $output);
$theme->footer();
}
function diary_edit($id) {
global $theme, $user, $allowed_html;
$result = db_query("SELECT * FROM diaries WHERE id = $id");
$diary = db_fetch_object($result);
$output .= diary_entry($diary->timestamp, $diary->text);
$output .= "<FORM ACTION=\"diary.php\" METHOD=\"post\">\n";
$output .= "<P>\n";
$output .= " <B>Edit diary entry:</B><BR>\n";
$output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"15\" NAME=\"text\">". check_input($diary->text) ."</TEXTAREA><BR>\n";
$output .= " <SMALL><I>Allowed HTML tags: ". htmlspecialchars($allowed_html) .".</I></SMALL>\n";
$output .= "</P>\n";
$output .= "<P>\n";
$output .= " <INPUT TYPE=\"hidden\" NAME=\"id\" VALUE=\"$diary->id\">\n";
$output .= " <INPUT TYPE=\"hidden\" NAME=\"timestamp\" VALUE=\"$diary->timestamp\">\n";
$output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Preview diary entry\"> <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Submit diary entry\">\n";
$output .= "</P>\n";
$output .= "</FORM>\n";
$theme->header();
$theme->box("Online diary", $output);
$theme->footer();
}
function diary_preview($text, $timestamp, $id = 0) {
global $theme, $user, $allowed_html;
$output .= diary_entry($timestamp, $text);
$output .= "<FORM ACTION=\"diary.php\" METHOD=\"post\">\n";
$output .= "<P>\n";
$output .= " <B>Preview diary entry:</B><BR>\n";
$output .= " <TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"15\" NAME=\"text\">". check_output($text) ."</TEXTAREA><BR>\n";
$output .= " <SMALL><I>Allowed HTML tags: ". htmlspecialchars($allowed_html) .".</I></SMALL>\n";
$output .= "</P>\n";
$output .= "<P>\n";
$output .= " <INPUT TYPE=\"hidden\" NAME=\"id\" VALUE=\"$id\">\n";
$output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Preview diary entry\">\n";
$output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Submit diary entry\">\n";
$output .= "</P>\n";
$output .= "</FORM>\n";
$theme->header();
$theme->box("Online diary", $output);
$theme->footer();
}
function diary_submit($text, $id = 0) {
global $user, $theme;
if ($id) {
watchdog("message", "old diary entry updated");
db_query("UPDATE diaries SET text = '". check_input($text) ."' WHERE id = $id");
}
else {
watchdog("diary", "new diary entry added");
db_query("INSERT INTO diaries (author, text, timestamp) VALUES ('$user->id', '". check_input($text) ."', '". time() ."')");
}
header("Location: diary.php?op=view&name=$user->userid");
}
### Security check:
if (strstr($id, " ") || strstr($name, " ")) {
watchdog("error", "diary: attempt to provide malicious input through URI");
exit();
}
switch($op) {
case "add":
diary_add();
break;
case "edit":
diary_edit($id);
break;
case "view":
diary_display($name);
break;
case "Preview diary entry":
if ($id) diary_preview($text, $timestamp, $id);
else diary_preview($text, time());
break;
case "Submit diary entry":
if ($id) diary_submit($text, $id);
else diary_submit($text);
break;
default:
diary_overview();
}
?>
......@@ -7,7 +7,7 @@ function error_flood() {
}
function error_httpd() {
global $REDIRECT_STATUS, $REDIRECT_URL, $HTTP_REFERER;
global $REDIRECT_STATUS, $REDIRECT_URL, $HTTP_REFERER, $HTTP_USER_AGENT;
switch($REDIRECT_STATUS) {
case 500:
......@@ -29,7 +29,7 @@ function error_httpd() {
$message = "unknown error";
}
watchdog("error", "message: `$message' - requested url: $REDIRECT_URL - referring url: $HTTP_REFERER");
watchdog("error", "message: `$message' - requested url: $REDIRECT_URL - referring url: $HTTP_REFERER - user agent: $HTTP_USER_AGENT");
print "<PRE>\n";
print "<H1>Oops, an error occured!</H1>\n";
......
<?
class Calendar {
var $date;
function calendar($date) {
$this->date = $date;
}
function display() {
global $PHP_SELF;
### Extract information from the given date:
$month = date("n", $this->date);
$year = date("Y", $this->date);
$day = date("d", $this->date);
### Extract first day of the month:
$first = date("w", mktime(0, 0, 0, $month, 1, $year));
### Extract last day of the month:
$last = date("t", mktime(0, 0, 0, $month, 1, $year));
### Calculate previous and next months dates:
$prev = mktime(0, 0, 0, $month - 1, $day, $year);
$next = mktime(0, 0, 0, $month + 1, $day, $year);
### Generate calendar header:
$output .= "\n<!-- calendar -->\n";
$output .= "<TABLE WIDTH=\"100%\" BORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"1\">\n";
$output .= " <TR><TD ALIGN=\"center\" COLSPAN=\"7\"><SMALL><A HREF=\"$PHP_SELF?date=$prev\">&lt;</A> &nbsp; ". date("F Y", $this->date) ." &nbsp; <A HREF=\"$PHP_SELF?date=$next\">&gt;</A></SMALL></TD></TR>\n";
$output .= " <TR><TD ALIGN=\"center\"><SMALL>S</SMALL></TD><TD ALIGN=\"center\"><SMALL>M</SMALL></TD><TD ALIGN=\"center\"><SMALL>T</SMALL></TD><TD ALIGN=\"center\"><SMALL>W</SMALL></TD><TD ALIGN=\"center\"><SMALL>T</SMALL></TD><TD ALIGN=\"center\"><SMALL>F</SMALL></TD><TD ALIGN=\"center\"><SMALL>S</SMALL></TD></TR>\n";
### Initialize temporary variables:
$nday = 1;
$sday = $first;
### Loop through all the days of the month:
while ($nday <= $last) {
### Set up blank days for first week of the month:
if ($first) {
$output .= " <TR><TD COLSPAN=\"$first\">&nbsp</TD>\n";
$first = 0;
}
### Start every week on a new line:
if ($sday == 0) $output .= " <TR>\n";
### Print one cell:
$date = mktime(24, 0, 0, $month, $nday, $year);
if ($nday == $day) $output .= " <TD ALIGN=\"center\"><SMALL><B>$nday</B></SMALL></TD>\n";
else if ($date > time()) $output .= " <TD ALIGN=\"center\"><SMALL>$nday</SMALL></TD>\n";
else $output .= " <TD ALIGN=\"center\"><SMALL><A HREF=\"$PHP_SELF?date=$date\" STYLE=\"text-decoration: none;\">$nday</A></SMALL></TD>\n";
### Start every week on a new line:
if ($sday == 6) $output .= " </TR>\n";
### Update temporary variables:
$sday++;
$sday = $sday % 7;
$nday++;
}
### Complete the calendar:
if ($sday) {
$end = 7 - $sday;
$output .= " <TD COLSPAN=\"$end\">&nbsp;</TD>\n </TR>\n";
}
$output .= "</TABLE>\n\n";
### Return calendar:
return $output;
}
}
?>
<?
function cron_add($name, $help, $code, $scheduled, $message = "") {
if (empty($name) || empty($code) || empty($scheduled)) {
include "includes/theme.inc";
function cron_set($module, $scheduled, $message = "") {
if (empty($module) || empty($scheduled)) {
$message = "failed: information missing";
}
else if (db_fetch_object(db_query("SELECT * FROM cron WHERE module = '$module'"))) {
db_query("UPDATE cron SET scheduled = $scheduled WHERE module = '$module'");
}
else {
$result = db_query("INSERT INTO cron (name, help, code, scheduled) VALUES ('". check_input($name) ."', '". check_input($help) ."', '". check_code($code) ."', '". check_input($scheduled) ."')");
db_query("INSERT INTO cron (module, scheduled, timestamp) VALUES ('". check_input($module) ."', '". check_input($scheduled) ."', '42')");
}
}
function cron_delete($id) {
$result = db_query("DELETE FROM cron WHERE id = $id");
function cron_get($module) {
return db_fetch_object(db_query("SELECT * FROM cron WHERE module = '$module'"), 0);
}
function cron_delete($module) {
$result = db_query("DELETE FROM cron WHERE module = '$module'");
}
function cron_execute($cron) {
eval($cron->code);
function cron_run($cron) {
$time = time();
db_query("UPDATE cron SET timestamp = '". time() ."' WHERE id = $cron->id");
$result = db_query("SELECT * FROM cron WHERE $time - timestamp > scheduled");
while ($task = db_fetch_object($result)) {
include "modules/". $task->module .".module";
if ($function = $module["cron"]) {
watchdog("message", "cron: executed '". $task->module ."_cron()'");
$function();
}
}
watchdog("message", "cron: executed '$cron->name'");
db_query("UPDATE cron SET timestamp = $time WHERE $time - timestamp > scheduled");
}
?>
......@@ -61,6 +61,25 @@ function format_plural($count, $singular, $plural) {
return ($count == 1) ? "$count $singular" : "$count $plural";
}
function format_interval($timestamp) {
if ($timestamp > 86400) {
$output .= format_plural(floor($timestamp / 86400), "day ", "days ");
$timestamp = $timestamp % 86400;
}
if ($timestamp > 3600) {
$output .= format_plural(floor($timestamp / 3600), "hour ", "hours ");
$timestamp = $timestamp % 3600;
}
if ($timestamp > 60) {
$output .= floor($timestamp / 60) ." min ";
$timestamp = $timestamp % 60;
}
if ($timestamp > 0) {
$output .= floor($timestamp / 86400) ." sec";
}
return $output;
}
function format_date($timestamp, $type = "medium") {
global $user;
......
......@@ -4,23 +4,12 @@
# Database settings:
#
### host: "http://www.drop.org/":
$db_host = "zind.net";
$db_name = "droporg";
$db_pass = "DropIes";
$db_name = "droporg";
### host: "http://beta.drop.org/":
#$db_host = "zind.net";
#$db_name = "dries";
#$db_pass = "Abc123";
#$db_name = "dries";
### host: "http://localhost/":
#$db_host = "localhost";
#$db_name = "drop";
#$db_pass = "drop";
#$db_name = "drop";
$db_host = "localhost";
$db_name = "name";
$db_pass = "pass";
$db_name = "name";
#
# Administrative information
......@@ -37,7 +26,6 @@
# represent the mathematical calculation to be performed
# to update a comment's value.
#
$comment_votes = array("none" => "none",
"-1" => "- 1",
"0" => "+ 0",
......@@ -78,18 +66,15 @@
# the first theme listed in this associative array will
# automatically become the default theme.
#
$themes = array("Marvin" => array(
$themes = array("UnConeD" => array(
"themes/unconed/unconed.theme",
"modern theme, gray and blue, high coolness factor"),
"Marvin" => array(
"themes/marvin/marvin.theme",
"classic theme, white, basic design with a fresh look"),
"Zaphod" => array(
"themes/zaphod/zaphod.theme",
"classic theme, yellow, structured, advanced navigation"),
"Trillian" => array(
"themes/trillian/trillian.theme",
"simple, easy, black background"),
"UnConeD" => array(
"themes/unconed/unconed.theme",
"modern theme, gray and blue, high coolness factor"));
"classic theme, yellow, structured, advanced navigation"));
#
# Submission moderation votes:
......@@ -112,7 +97,7 @@
# story is pushed over the threshold and up it goes on the public
# page. On the other hand, when too many people voted to drop a
# story, the story will get trashed.
$submission_post_threshold = "3";
$submission_post_threshold = "5";
$submission_dump_threshold = "-2";
#
......
......@@ -80,9 +80,9 @@ function display_new_diaries($theme, $num = 20) {
$content .= "<P><B>". date("l, M jS", $diary->timestamp) ."</B></P>\n";
$time = date("F jS", $diary->timestamp);
}
$content .= "<LI><A HREF=\"diary.php?op=view&name=$diary->userid\">$diary->userid</A></LI>\n";
$content .= "<LI><A HREF=\"module.php?mod=diary&op=view&name=$diary->userid\">$diary->userid</A></LI>\n";
}
$content .= "<P ALIGN=\"right\">[ <A HREF=\"diary.php\"><FONT COLOR=\"$theme->hlcolor2\">more</FONT></A> ]</P>";
$content .= "<P ALIGN=\"right\">[ <A HREF=\"module.php?mod=diary\"><FONT COLOR=\"$theme->hlcolor2\">more</FONT></A> ]</P>";
$theme->box("Recent diary entries", $content);
}
......@@ -96,12 +96,6 @@ function display_new_headlines($theme, $num = 10) {
$theme->box("Latest headlines", $content);
}
function display_calendar($theme, $date) {
include "includes/calendar.inc";
$calendar = new Calendar($date);
$theme->box("Browse archives", $calendar->display());
}
function display_account($theme) {
global $user, $site_name;
......
<?
$module = array("admin" => "account_admin");
$module = array("cron" => "account_cron",
"admin" => "account_admin");
function account_cron() {
// clean-up user database
}
function account_display($order = "username") {
$sort = array("ID" => "id", "fake e-mail address" => "fake_email", "homepage" => "url", "hostname" => "last_host", "last access date" => "last_access", "real e-mail address" => "real_email", "real name" => "name", "status" => "status", "theme" => "theme", "timezone" => "timezone", "username" => "userid");
......@@ -122,4 +127,4 @@ function account_admin() {
}
}
?>
\ No newline at end of file
?>
<?
$module = array("page" => "backend_page",
"cron" => "backend_cron",
"admin" => "backend_admin");
include "includes/theme.inc";
......@@ -42,6 +43,9 @@ function backend_page() {
$theme->footer();
}
function backend_cron() {
// update backends
}
function backend_admin_main() {
global $theme;
......@@ -50,7 +54,7 @@ function backend_admin_main() {
$result = db_query("SELECT * FROM channel ORDER BY id");
$output .= "<TABLE BORDER=\"1\" CELLSPADDING=\"2\" CELLSPACING=\"2\">\n";
$output .= " <TH>Site</TH><TH>Contact</TH><TH>Last updated</TH><TH COLSPAN=\"2\">Operations</TH></TR>\n";
$output .= " <TH>site</TH><TH>contact</TH><TH>last updated</TH><TH COLSPAN=\"2\">operations</TH></TR>\n";
while ($channel = db_fetch_object($result)) {
// Load backend from database:
......
......@@ -2,23 +2,37 @@
$module = array("admin" => "cron_admin");
function cron_admin() {
include_once "includes/function.inc";
function cron_reset($name) {
cron_delete($name);
}
function cron_display() {
// Perform query:
$result = db_query("SELECT * FROM cron");
// Generate output:
$output .= "<TABLE BORDER=\"1\" CELLPADDING=\"2\" CELLSPACING=\"2\">\n";
$output .= " <TR><TH>module</TH><TH>interval</TH><TH>last exection</TH><TH COLSPAN=\"2\">operations</TH></TR>\n";
while ($cron = db_fetch_object($result)) {
$output .= "<TABLE BORDER=\"1\" CELLPADDING=\"2\" CELLSPACING=\"2\">\n";
$output .= " <TR><TH VALIGN=\"top\">Name:</TH><TD>". check_output($cron->name) ."</TD></TR>\n";
$output .= " <TR><TH VALIGN=\"top\">Help:</TH><TD>". check_output($cron->help) ."</TD></TR>\n";
$output .= " <TR><TH VALIGN=\"top\">Code:</TH><TD><CODE>". nl2br($cron->code) ."</CODE></TD></TR>\n";
$output .= " <TR><TH VALIGN=\"top\">Last run:</TH><TD>". format_date($cron->timestamp) ."</TD></TR>\n";
$output .= " <TR><TH VALIGN=\"top\">Scheduled:</TH><TD>every $cron->scheduled seconds</TD></TR>\n";
$output .= "</TABLE>\n";
$output .= "<BR><BR>\n";
$output .= " <TR><TD>". check_output($cron->module) ."</TD><TD>every ". format_interval($cron->scheduled) ."</TD><TD>". format_interval(time() - $cron->timestamp) ." ago</TD><TD ALIGN=\"center\"><A HREF=\"cron.php\">execute</A></TD><TD><A HREF=\"admin.php?mod=cron&op=reset&name=$cron->module\">reset</A></TD></TR>\n";
}
$output .= "</TABLE>\n";
print $output;
}
function cron_admin() {
global $op, $name;
switch($op) {
case "reset":
cron_reset($name);
break;
}
cron_display();
}
?>
<?
function diary_edit($id) {
$module = array("page" => "diary_page",
"admin" => "diary_admin");
include "includes/theme.inc";
function diary_page_overview($num = 20) {
global $theme, $user;
$result = db_query("SELECT d.*, u.userid FROM diaries d LEFT JOIN users u ON d.author = u.id ORDER BY d.timestamp DESC LIMIT $num");
$output .= "<P>This part of the website is dedicated to providing easy to write and easy to read online diaries or journals filled with daily thoughts, poetry, boneless blather, spiritual theories, intimate details, valuable experiences, cynical rants, semi-coherent comments, writing experiments, artistic babblings, critics on actuality, fresh insights, diverse dreams, chronicles and general madness available for general human consumption.</P>";
while ($diary = db_fetch_object($result)) {
if ($time != date("F jS", $diary->timestamp)) {
$output .= "<B>". date("l, F jS", $diary->timestamp) ."</B>\n";
$time = date("F jS", $diary->timestamp);
}
$output .= "<DL>\n";
$output .= " <DD><P><B>$diary->userid wrote:</B></P></DD>\n";
$output .= " <DL>\n";
$output .= " <DD><P>". check_output($diary->text, 1) ."</P><P>[ <A HREF=\"module.php?mod=diary&op=view&name=$diary->userid\">more</A> ]</P></DD>\n";
$output .= " </DL>\n";
$output .= "</DL>\n";
}
$theme->header();
$theme->box("Online diary", $output);
$theme->footer();
}
function diary_page_entry($timestamp, $text, $id = 0) {
if ($id) {
$output .= "<DL>\n";
$output .= " <DT><B>". date("l, F jS", $timestamp) .":</B> </DT>\n";
$output .= " <DD><P>[ <A HREF=\"module.php?mod=diary&op=edit&id=$id\">edit</A> ]</P><P>". check_output($text, 1) ."</P></DD>\n";
$output .= "</DL>\n";
}
else {
$output .= "<DL>\n";
$output .= " <DT><B>". date("l, F jS", $timestamp) .":</B></DT>\n";
$output .= " <DD><P>". check_output($text, 1) ."</P></DD>\n";
$output .= "</DL>\n";
}