From 9559f61fcab156477dd45f4926664b74c3c2d65d Mon Sep 17 00:00:00 2001 From: Dries Buytaert <dries@buytaert.net> Date: Mon, 13 Nov 2000 08:17:45 +0000 Subject: [PATCH] Another batch with a lot of internal updates, yet no visual changes to the site: - watchdog (rewrite): + the collected information provides more details and insights for post-mortem research + input limitation - database abstraction layer: + mysql errors are now verbose and is no longer displayed in a browser - fixes a possible security risk - admin.php: + updated watchdog page + fixed security flaw - diary.php: + fixed nl2br problem - themes: + fixed comment bug in all 3 themes. - misc: + renamed some global variables for sake of consistency: $sitename --> $site_name $siteurl --> $site_url + added input check where (a) exploitable and (b) possible + added input size check + various small improvements + fixed various typoes ... and much, much more in fact. --- account.php | 30 +++++++----- admin.php | 16 +++--- diary.php | 13 +++-- discussion.php | 17 +++++-- error.php | 2 +- faq.php | 21 ++++---- includes/admin.inc | 8 +-- includes/ban.inc | 4 +- includes/config.inc | 94 ++++++++++++++++++++---------------- includes/database.inc | 25 ++++------ includes/function.inc | 4 +- includes/submission.inc | 6 +-- includes/user.inc | 4 -- includes/watchdog.inc | 27 ++++++++--- index.php | 6 +++ search.php | 2 +- submission.php | 9 +++- submit.php | 19 +++----- themes/marvin/marvin.theme | 6 +-- themes/unconed/unconed.theme | 10 ++-- 20 files changed, 182 insertions(+), 141 deletions(-) diff --git a/account.php b/account.php index b3851e6cbb3b..e155f316eaff 100644 --- a/account.php +++ b/account.php @@ -27,16 +27,16 @@ function account_session_start($userid, $passwd) { if ($user->id) { session_start(); session_register("user"); - watchdog(1, "session opened for user `$user->userid'"); + watchdog("message", "session opened for user `$user->userid'"); } else { - watchdog(2, "failed login for user `$userid'"); + watchdog("warning", "failed login for user `$userid'"); } } function account_session_close() { global $user; - watchdog(1, "session closed for user `$user->userid'"); + watchdog("message", "session closed for user `$user->userid'"); session_unset(); session_destroy(); unset($user); @@ -281,7 +281,7 @@ function account_register_enter($user = "", $error = "") { } function account_register_submit($new) { - global $theme, $mail, $sitename, $siteurl; + global $theme, $mail, $site_name, $site_url; if ($rval = account_validate($new)) { account_register_enter($new, "$rval"); @@ -293,12 +293,12 @@ function account_register_submit($new) { user_save($new); - $link = $siteurl ."account.php?op=confirm&name=$new[userid]&hash=$new[hash]"; - $message = "$new[userid],\n\n\nsomeone signed up for a user account on $sitename and supplied this email address as their contact. If it wasn't you, don't get your panties in a knot and simply ignore this mail.\n\nIf this was you, you have to activate your account first before you can login. You can do so simply by visiting the URL below:\n\n $link\n\nVisiting this URL will automatically activate your account. Once activated you can login using the following information:\n\n username: $new[userid]\n password: $new[passwd]\n\n\n-- $sitename crew\n"; + $link = $site_url ."account.php?op=confirm&name=$new[userid]&hash=$new[hash]"; + $message = "$new[userid],\n\n\nsomeone signed up for a user account on $site_name and supplied this email address as their contact. If it wasn't you, don't get your panties in a knot and simply ignore this mail.\n\nIf this was you, you have to activate your account first before you can login. You can do so simply by visiting the URL below:\n\n $link\n\nVisiting this URL will automatically activate your account. Once activated you can login using the following information:\n\n username: $new[userid]\n password: $new[passwd]\n\n\n-- $site_name crew\n"; - mail($new[real_email], "Account details for $sitename", $message, "From: noreply@$sitename"); + mail($new[real_email], "Account details for $site_name", $message, "From: noreply@$site_url"); - watchdog(1, "new user `$new[userid]' <$new[real_email]>"); + watchdog("message", "new user `$new[userid]' <$new[real_email]>"); $theme->header(); $theme->box("Account details", "Congratulations! Your member account has been sucessfully created and further instructions on how to activate your account have been sent to your e-mail address."); @@ -316,21 +316,21 @@ function account_register_confirm($name, $hash) { if ($account->hash == $hash) { db_query("UPDATE users SET status = 2, hash = '' WHERE userid = '$name'"); $output .= "Your account has been sucessfully confirmed. You can click <A HREF=\"account.php?op=login\">here</A> to login.\n"; - watchdog(1, "$name: account confirmation sucessful"); + watchdog("message", "$name: account confirmation sucessful"); } else { $output .= "Confirmation failed: invalid confirmation hash.\n"; - watchdog(3, "$name: invalid confirmation hash"); + watchdog("error", "$name: invalid confirmation hash"); } } else { $output .= "Confirmation failed: your account has already been confirmed. You can click <A HREF=\"account.php?op=login\">here</A> to login.\n"; - watchdog(3, "$name: attempt to re-confirm account"); + watchdog("error", "$name: attempt to re-confirm account"); } } else { $output .= "Confirmation failed: no such account found.<BR>"; - watchdog(3, "$name: attempt to confirm non-existing account"); + watchdog("error", "$name: attempt to confirm non-existing account"); } $theme->header(); @@ -370,6 +370,12 @@ function account_comments() { $theme->footer(); } +### Security check: +if (strstr($name, " ") || strstr($hash, " ")) { + watchdog("error", "account: attempt to provide malicious input through URI"); + exit(); +} + switch ($op) { case "Login": account_session_start($userid, $passwd); diff --git a/admin.php b/admin.php index 105d9645a391..0cf8bbf88715 100644 --- a/admin.php +++ b/admin.php @@ -1,7 +1,7 @@ <? - // TEMPORARY SOLUTION: - if ($user->id > 4) exit; +// TEMPORARY SOLUTION: +if (!$user->id || $user->id > 4) exit(); /* * Account administration: @@ -115,7 +115,7 @@ function account_view($name) { * Watchdog administration: */ function watchdog_display($order = "date") { - $colors = array("#FFFFFF", "#FFFFFF", "#90EE90", "#CD5C5C"); + $colors = array("#D8BFD8", "#6495ED", "#6A5ADF", "#FFFFFF", "#FFA500", "#FF3C3C"); $fields = array("date" => "id DESC", "username" => "user", "location" => "location", "message" => "message DESC", "level" => "level DESC"); ### Perform query: @@ -288,7 +288,7 @@ function comment_edit($id) { function comment_save($id, $subject, $comment) { db_query("UPDATE comments SET subject = '". check_input($subject) ."', comment = '". check_input($comment) ."' WHERE cid = $id"); - watchdog(1, "modified comment `$subject'."); + watchdog("message", "modified comment `$subject'."); } function comment_display($order = "date") { @@ -391,7 +391,7 @@ function diary_edit($id) { function diary_save($id, $text) { db_query("UPDATE diaries SET text = '". check_input($text) ."' WHERE id = $id"); - watchdog(1, "modified diary entry #$id."); + watchdog("message", "modified diary entry #$id."); } function diary_display($order = "date") { @@ -516,7 +516,7 @@ function story_edit($id) { 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"); - watchdog(1, "modified story `$subject'."); + watchdog("message", "modified story `$subject'."); } function story_display($order = "date") { @@ -562,7 +562,7 @@ function story_display($order = "date") { function info_display() { include "includes/config.inc"; - $output .= "sitename: $sitename<BR>\n"; + $output .= "sitename: $site_name<BR>\n"; $output .= "e-mail address: $contact_email<BR>\n"; $output .= "send e-mail notifications: $notify<BR>\n"; $output .= "allowed HTML tags: <I>". htmlspecialchars($allowed_html) ."</I><BR>\n"; @@ -570,7 +570,7 @@ function info_display() { $output .= "submission post threshold: $submission_post_threshold<BR>\n"; $output .= "submission dump threshold: $submission_dump_threshold<BR>\n"; - admin_box("$sitename settings", $output); + admin_box("$site_name settings", $output); } include "includes/config.inc"; diff --git a/diary.php b/diary.php index d3745990ecab..47b870e3ad67 100644 --- a/diary.php +++ b/diary.php @@ -32,7 +32,7 @@ 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) ."</P></DD>\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 { @@ -144,16 +144,21 @@ 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"); - watchdog(1, "old diary entry updated"); } else { + watchdog("diary", "new diary entry added"); db_query("INSERT INTO diaries (author, text, timestamp) VALUES ('$user->id', '". check_input($text) ."', '". time() ."')"); - watchdog(1, "new diary entry added"); } 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": @@ -177,4 +182,4 @@ function diary_submit($text, $id = 0) { diary_overview(); } -?> \ No newline at end of file +?> diff --git a/discussion.php b/discussion.php index 53476a27ea38..6501874e0aa9 100644 --- a/discussion.php +++ b/discussion.php @@ -255,20 +255,23 @@ function comment_post($pid, $sid, $subject, $comment) { $duplicate = db_result(db_query("SELECT COUNT(*) FROM comments WHERE pid = '$pid' AND sid = '$sid' AND subject = '". check_input($subject) ."' AND comment = '". check_input($comment) ."'"), 0); if ($fake != 1) { - watchdog(3, "attemp to insert fake comment"); + watchdog("error", "discussion: attempt to insert fake comment"); $theme->box("fake comment", "fake comment: $fake"); } elseif ($duplicate != 0) { - watchdog(3, "attemp to insert duplicate comment"); + watchdog("error", "discussion: attempt to insert duplicate comment"); $theme->box("duplicate comment", "duplicate comment: $duplicate"); } else { ### Validate subject: $subject = ($subject) ? $subject : substr($comment, 0, 29); - ### Add comment to database: - db_insert("INSERT INTO comments (pid, sid, author, subject, comment, hostname, timestamp) VALUES ($pid, $sid, '$user->id', '". check_input($subject) ."', '". check_input($comment) ."', '". getenv("REMOTE_ADDR") ."', '". time() ."')"); + ### Add watchdog entry: + watchdog("comment", "added new comment with subject '$subject'"); + ### Add comment to database: + db_query("INSERT INTO comments (pid, sid, author, subject, comment, hostname, timestamp) VALUES ($pid, $sid, '$user->id', '". check_input($subject) ."', '". check_input($comment) ."', '". getenv("REMOTE_ADDR") ."', '". time() ."')"); + ### Compose header: header("Location: discussion.php?id=$sid"); } @@ -277,6 +280,12 @@ function comment_post($pid, $sid, $subject, $comment) { include "includes/theme.inc"; include "includes/comment.inc"; +### Security check: +if (strstr($id, " ") || strstr($pid, " ") || strstr($sid, " ") || strstr($mode, " ") || strstr($order, " ") || strstr($threshold, " ")) { + watchdog("error", "discussion: attempt to provide malicious input through URI"); + exit(); +} + switch($op) { case "Preview comment": $theme->header(); diff --git a/error.php b/error.php index 2ae17e4e8b18..df888452c7c5 100644 --- a/error.php +++ b/error.php @@ -31,7 +31,7 @@ include "includes/database.inc"; include "includes/watchdog.inc"; - watchdog(3, "message: `$message' - requested url: $REDIRECT_URL - referring url: $HTTP_REFERER"); + watchdog("error", "message: `$message' - requested url: $REDIRECT_URL - referring url: $HTTP_REFERER"); ?> <B>Processed output:</B><BR> diff --git a/faq.php b/faq.php index 28367e9caf70..24aba17d4aa1 100644 --- a/faq.php +++ b/faq.php @@ -1,4 +1,5 @@ <? + include "includes/theme.inc"; $output = " @@ -12,14 +13,14 @@ <P><B>User</B> n.<BR>1. Someone doing `real work' with the computer, using it as a means rather than an end. Someone who pays to use a computer. 2. A programmer who will believe anything you tell him. One who asks silly questions. [GLS observes: This is slightly unfair. It is true that users ask questions (of necessity). Sometimes they are thoughtful or deep. Very often they are annoying or downright stupid, apparently because the user failed to think for two seconds or look in the documentation before bothering the maintainer.] 3. Someone who uses a program from the outside, however skillfully, without getting into the internals of the program. One who reports bugs instead of just going ahead and fixing them.</P> </DD> - <DT><B>What is $sitename all about?</B></DT> - <DD>$sitename is a news and discussion forum. It is a <I>tool</I>. And as a tool, it aims to create an environment to make discussions possible. $sitename is not an organization, but a non-profit hobby project instead.<P>People log in to the site, read the news, select one or more items and start to discuss and post their reactions. $sitename is a community site that relies solely on reader-contributed content.<P>First off, we strive towards discussion rather then to deliver news on its own: discussion can really make a story considerably better as user comments frequently `upstage' the story itself.<P>Secondly, we aim towards a high quality of content and content posters by using and experimenting with several techniques and systems such as trust metrics, scoring, moderation and collaborative filtering.<P></DD> + <DT><B>What is $site_name all about?</B></DT> + <DD>$site_name is a news and discussion forum. It is a <I>tool</I>. And as a tool, it aims to create an environment to make discussions possible. $site_name is not an organization, but a non-profit hobby project instead.<P>People log in to the site, read the news, select one or more items and start to discuss and post their reactions. $site_name is a community site that relies solely on reader-contributed content.<P>First off, we strive towards discussion rather then to deliver news on its own: discussion can really make a story considerably better as user comments frequently `upstage' the story itself.<P>Secondly, we aim towards a high quality of content and content posters by using and experimenting with several techniques and systems such as trust metrics, scoring, moderation and collaborative filtering.<P></DD> - <DT><B>Isn't $sitename similar to slashdot.org and kuro5hin.org?</B></DT> - <DD>To some extend, yes. Credit where credit is due: we borrowed many ideas (like the interface and moderation) from <A HREF=\"http://slashdot.org/\">slashdot.org</A> and <A HREF=\"http://kuro5hin.org/\">kuro5hin.org</A> because they have many good ideas about discussion forums. We do not use their code or any permutation thereof as $sitename has been written entirely from scratch. Our goal was to create a similar base initially, and to go from there and to transform $sitename into something different by adding new and unique features.<P></DD> + <DT><B>Isn't $site_name similar to slashdot.org and kuro5hin.org?</B></DT> + <DD>To some extend, yes. Credit where credit is due: we borrowed many ideas (like the interface and moderation) from <A HREF=\"http://slashdot.org/\">slashdot.org</A> and <A HREF=\"http://kuro5hin.org/\">kuro5hin.org</A> because they have many good ideas about discussion forums. We do not use their code or any permutation thereof as $site_name has been written entirely from scratch. Our goal was to create a similar base initially, and to go from there and to transform $site_name into something different by adding new and unique features.<P></DD> <DT><B><A NAME=\"moderation\">Why moderatiom, trust metrics and collaborative filtering?</A></B></DT> - <DD>To help individuals and communities address the challenges of information overload.<P>As each new piece of information competes for attention, people quickly tend to become overwhelmed and seek assistance in identifying the most interesting, worthwhile, valuable or enteraining items. Not to mention the fact, reader-contributed content and other levels of interactivity tend to become chaotic, bloated and disreputable.<P>Therefore, we decided to develop a public system powered by a community that aims to bring quality content to everyone's attention and to filter out all junk: to <I>sort the wheat from the chaff</I>. The output should be something clean and homogenized featuring quality content, and should slide down the gullet far more easily. Another objective is to provide a customized service according to public and individual preferences, whether expressed or inferred.<P>Yes, you are right. It all sounds a bit idealistic, not to mention hypothetical. However, don't get this wrong: this isn't a new concept, various such systems exist nowadays (like <A HREF=\"http://slashdot.org/\">slashdot.org</A> or <A HREF=\"http://www.kuro5hin.org/\">kuro5hin.org</A>). We just happen to want our own system.<P>Last but not least we, the $sitename team, don't want the responsibility to manually review each post and to select the ones worthy. Systematic editing by individual editors is nice and dandy, if you get paid for it or if you have some time to kill. Afterall, we are not writers, critics nor reviewers for that matter; we are programmers, designers and technicians.<P></DD> + <DD>To help individuals and communities address the challenges of information overload.<P>As each new piece of information competes for attention, people quickly tend to become overwhelmed and seek assistance in identifying the most interesting, worthwhile, valuable or enteraining items. Not to mention the fact, reader-contributed content and other levels of interactivity tend to become chaotic, bloated and disreputable.<P>Therefore, we decided to develop a public system powered by a community that aims to bring quality content to everyone's attention and to filter out all junk: to <I>sort the wheat from the chaff</I>. The output should be something clean and homogenized featuring quality content, and should slide down the gullet far more easily. Another objective is to provide a customized service according to public and individual preferences, whether expressed or inferred.<P>Yes, you are right. It all sounds a bit idealistic, not to mention hypothetical. However, don't get this wrong: this isn't a new concept, various such systems exist nowadays (like <A HREF=\"http://slashdot.org/\">slashdot.org</A> or <A HREF=\"http://www.kuro5hin.org/\">kuro5hin.org</A>). We just happen to want our own system.<P>Last but not least we, the $site_name team, don't want the responsibility to manually review each post and to select the ones worthy. Systematic editing by individual editors is nice and dandy, if you get paid for it or if you have some time to kill. Afterall, we are not writers, critics nor reviewers for that matter; we are programmers, designers and technicians.<P></DD> <DT><B>How does submission moderation work?</B></DT> <DD>Anyone who happens by, and has some news or some thoughts they'd like to share, can submit new content for consideration. After someone has submitted something, their story is added to a queue. All registered users can access this list of pending stories, that is, stories that have been submitted, but do not yet appear on the public front page. Those registered users can vote whether they think the story should be posted or not. When enough people vote to post a story, the 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.<P></DD> @@ -28,7 +29,7 @@ <DD>If you create an account and log in, you will be able to moderate comments. This lets you assign a score to a comment on how good you think the comment was or how visible you think it should be. When more then one person rates a comment, the overall rating is just a simple average of all ratings. Comments with a high ratings are more visible then comments with a lower rating. Like that, comments that gain the approbation of participants will gradually move up through statistical effects and pointless comments will sink into oblivion.<P>Hence, the purpose of comment moderation is two-fold: <UL><LI>To bring the really good comments to everyone's attention.</LI><LI>To hide or get get rid of spam, flamebait and trolls.</LI></UL>In the latter, comment moderation provides a technical solution to a social problem.<P></DD> <DT><B>Why would I want to create a user account?</B></DT> - <DD>No $sitename participant can use his own name or handle to post comments until they sign up and submit their e-mail address. Those who do not may participate as `$anonymous', but they will suffer numerous disadvantages, not the least that their posts begin at a lower score.<P>In contrast, those with a user account can use their own name or handle and are granted various priveleges: the most important is probably the ability to moderate new submissions and to rate comments. Also, registered users can tune the site to their personal needs. For instance: they can select one of the available themes to alter the look-and-feel of the site or they can fine-tune the values of various settings to their likings.<P></DD> + <DD>No $site_name participant can use his own name or handle to post comments until they sign up and submit their e-mail address. Those who do not may participate as `$anonymous', but they will suffer numerous disadvantages, not the least that their posts begin at a lower score.<P>In contrast, those with a user account can use their own name or handle and are granted various priveleges: the most important is probably the ability to moderate new submissions and to rate comments. Also, registered users can tune the site to their personal needs. For instance: they can select one of the available themes to alter the look-and-feel of the site or they can fine-tune the values of various settings to their likings.<P></DD> <DT><B>I forgot my password, what do I do?</B></DT> <DD>--- under construction ---<P></DD> @@ -64,13 +65,13 @@ </DD> <DT><B>What is your disclaimer?</B></DT> - <DD>All messages made available (including any discussion goups and bulletin boards) and any opinions, advice, statements or other information contained in any messages posted or transmitted by any third party are the responsibility of the author of that message and not of $sitename. The fact that a particular message is posted on or transmitted using this website does not mean that $sitename has endorsed that message in any way or verified the accuracy, completeness or usefulness of any message.<P>Furthermore, all persons who use $sitename are advised not to use them for solicitations or any other commercial purposes. We make no representation regarding the merchantability or fitness for any particular purpose of any message posted by any third party. Users are encouraged to seek the advice of their appropriate professional advisors, when evaluating the information contained in any message. $sitename is not responsible for any defamatory, offensive or illegal conduct of any user.<P></DD> + <DD>All messages made available (including any discussion goups and bulletin boards) and any opinions, advice, statements or other information contained in any messages posted or transmitted by any third party are the responsibility of the author of that message and not of $site_name. The fact that a particular message is posted on or transmitted using this website does not mean that $site_name has endorsed that message in any way or verified the accuracy, completeness or usefulness of any message.<P>Furthermore, all persons who use $site_name are advised not to use them for solicitations or any other commercial purposes. We make no representation regarding the merchantability or fitness for any particular purpose of any message posted by any third party. Users are encouraged to seek the advice of their appropriate professional advisors, when evaluating the information contained in any message. $site_name is not responsible for any defamatory, offensive or illegal conduct of any user.<P></DD> <DT><B>What are your terms and conditions?</B></DT> <DD> - This website includes threaded discussion groups and discussion forums which allow feedback to $sitename and real-time interaction between the persons who use this service. The responsibility for any opinions, advice, statements or other information contained in any messages posted or transmitted by any third party on this website resides solely with the author.<P> + This website includes threaded discussion groups and discussion forums which allow feedback to $site_name and real-time interaction between the persons who use this service. The responsibility for any opinions, advice, statements or other information contained in any messages posted or transmitted by any third party on this website resides solely with the author.<P> <U>1. When using the discussion forums, you may NOT:</U><UL><LI>Keep any other person from using and enjoying the discussion forums.</LI><LI>Post or transmit any messages (or content in general) that would constitute or encourage conduct that would constitute a criminal offense, give rise to civil liability or otherwise violate any local, state, national or international law, including any threatening, abusive libelous, defamatory, obscene, vulgar, pornographic, profane or indecent messages of any kind.</LI><LI>Post or transmit any information, software or other materials which violate or infringe upon the rights of others, including their privacy or publicity rights, or which is protected by copyright, trademark or other proprietary rights, without first obtaining permission from the person who owns or holds that right.</LI><LI>Use the discussion forum in any way for solicitations or other commercial purposes.</LI></UL><P> - <U>2. $sitename's right to monitor the discussion forums:</U><BR>You understand that $sitename has no obligation to monitor the discussion forum. However $sitename reserves the right at all times to edit, refuse to post or to remove any information or materials, in whole or in part, that in $sitename's sole discretion are objectionable or in violation of these terms and conditions and to disclose any information necessary to satisfy or governmental request.<P> + <U>2. $site_name's right to monitor the discussion forums:</U><BR>You understand that $site_name has no obligation to monitor the discussion forum. However $site_name reserves the right at all times to edit, refuse to post or to remove any information or materials, in whole or in part, that in $site_name's sole discretion are objectionable or in violation of these terms and conditions and to disclose any information necessary to satisfy or governmental request.<P> </DD> </DL>"; @@ -78,4 +79,4 @@ $theme->box("Frequently Asked Questions", $output); $theme->footer(); -?> \ No newline at end of file +?> diff --git a/includes/admin.inc b/includes/admin.inc index 08c8642c4ddf..2d13c7c17890 100644 --- a/includes/admin.inc +++ b/includes/admin.inc @@ -8,12 +8,12 @@ function admin_icon($name) { } function admin_header() { - global $sitename, $section; + global $site_name, $section; ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> - <HEAD><TITLE><? echo $sitename; ?> administration center</TITLE></HEAD> + <HEAD><TITLE><? echo $site_name; ?> administration center</TITLE></HEAD> <STYLE> body { font-family: helvetica, arial; } h1 { font-size: 14pt; font-weight: bold; color: #006699; } @@ -24,7 +24,7 @@ function admin_header() { </STYLE> <BODY BGCOLOR="#FFFFFF" LINK="#006699" VLINK="#004499" ALINK="#FF0000"> <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="2" WIDTH="780"> - <TR><TD COLSPAN="10"><H1><? echo "$sitename"; ?> administration center</H1></TD></TR> + <TR><TD COLSPAN="10"><H1><? echo "$site_name"; ?> administration center</H1></TD></TR> <TR><TD BGCOLOR="#000000" COLSPAN="10" WIDTH="100%"><IMG SRC="images/pixel.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR> <TR> <? @@ -67,4 +67,4 @@ function admin_footer() { <? } -?> \ No newline at end of file +?> diff --git a/includes/ban.inc b/includes/ban.inc index 1d9fa095ed72..8a40459451c9 100644 --- a/includes/ban.inc +++ b/includes/ban.inc @@ -31,7 +31,7 @@ function ban_add($mask, $category, $reason, $message = "") { $message = "Added new ban with mask `$mask'.<P>\n"; ### Add log entry: - watchdog(1, "added new ban `$mask' to category `". $index2type[$category] ."' with reason `$reason'."); + watchdog("message", "added new ban `$mask' to category `". $index2type[$category] ."' with reason `$reason'."); } } @@ -45,7 +45,7 @@ function ban_delete($id) { $result = db_query("DELETE FROM bans WHERE id = $id"); ### Deleted log entry: - watchdog(1, "removed ban `$ban->mask' from category `". $index2type[$ban->type] ."'."); + watchdog("message", "removed ban `$ban->mask' from category `". $index2type[$ban->type] ."'."); } } diff --git a/includes/config.inc b/includes/config.inc index 15b1c719aa78..80ee2dc74b60 100644 --- a/includes/config.inc +++ b/includes/config.inc @@ -1,45 +1,33 @@ <? # -# MySQL settings: +# Database settings: # -### http://www.drop.org/: -#$dbhost = "zind.net"; -#$dbuname = "droporg"; -#$dbpass = "DropIes"; -#$dbname = "droporg"; +### host: "http://www.drop.org/": +#$db_host = "zind.net"; +#$db_uname = "droporg"; +#$db_pass = "DropIes"; +#$db_name = "droporg"; -### http://beta.drop.org/: -$dbhost = "zind.net"; -$dbuname = "dries"; -$dbpass = "Abc123"; -$dbname = "dries"; +### host: "http://beta.drop.org/": +#$db_host = "zind.net"; +#$db_uname = "dries"; +#$db_pass = "Abc123"; +#$db_name = "dries"; -### http://dione/: -#$dbhost = ""; -#$dbuname = "dries"; -#$dbpass = "oakley"; -#$dbname = "dries"; +### host: "http://localhost/": +$db_host = ""; +$db_uname = "dries"; +$db_pass = "oakley"; +$db_name = "dries"; # -# Name of the site +# Administrative information # -$sitename = "drop.org"; -$siteurl = "http://www.drop.org/"; - -# -# Contact information: -# The contact information will be used to send out automated mails -# to users, account holders or visitors. -$contact_email = "droppies@drop.org"; - -# -# Notify: -# Set to '1' to receive an e-mail when news has been submitted -# through submit.php -# -$notify = 0; +$site_name = "drop.org"; +$site_url = "http://www.drop.org/"; +$site_email = "droppies@drop.org"; # # Notify information: @@ -55,13 +43,13 @@ # Comment meta reasons: # $comment_votes = array("none" => "none", - "-1" => "- 1", - "0" => "+ 0", - "+1" => "+ 1", - "+2" => "+ 2", - "+3" => "+ 3", - "+4" => "+ 4", - "+5" => "+ 5"); + "-1" => "- 1", + "0" => "+ 0", + "+1" => "+ 1", + "+2" => "+ 2", + "+3" => "+ 3", + "+4" => "+ 4", + "+5" => "+ 5"); # # Categories: @@ -94,10 +82,10 @@ # the first theme listed in the associative array `$themes' will # automatically become the default theme. # -$themes = array("Marvin" => array( +$themes = array("Marvin" => array( "themes/marvin/marvin.theme", "classic theme, white, basic design with a fresh look"), - "Zaphod" => array( + "Zaphod" => array( "themes/zaphod/zaphod.theme", "classis theme, yellow, structured, advanced navigation"), "UnConeD" => array( @@ -117,8 +105,30 @@ # # Submission moderation thresholds: -# +# registered users can vote whether they think the story should +# be posted or not. When enough people vote to post a story, the +# 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_dump_threshold = "-2"; +# +# Submission rate: +# +$submission_rate = array("comment" => "60", // 60 seconds = 1 minute + "diary" => "300", // 300 seconds = 5 minutes + "story" => "300"); // 300 seconds = 5 minutes +# +# Submission size: +# the maximum length in characters a submission (story, diary, +# comment) is allowed to be. +# +$submission_size = 6000; + +# +# Watchdog history: +# +$watchdog_history = 604800; // 604800 seconds = 1 week + ?> diff --git a/includes/database.inc b/includes/database.inc index 843cb270af95..6a81b003abc8 100644 --- a/includes/database.inc +++ b/includes/database.inc @@ -8,28 +8,21 @@ */ function db_connect() { - global $dbhost, $dbuname, $dbpass, $dbname; - mysql_pconnect($dbhost, $dbuname, $dbpass) or die(mysql_Error()); - mysql_select_db($dbname) or die ("Unable to select database"); + global $db_host, $db_uname, $db_pass, $db_name; + mysql_pconnect($db_host, $db_uname, $db_pass) or die(mysql_Error()); + mysql_select_db($db_name) or die ("Unable to select database"); // NOTE: we are using a persistent connection! } -function db_insert($query, $debug = false) { - // NOTE: - // add spam- and/or flood-checks - - db_query($query, $debug); -} - function db_query($query, $debug = false) { - ### perform query: + // perform query: $qid = mysql_query($query); - ### debug output (if required): - if ($debug || empty($qid)) print "<PRE>query: ". htmlspecialchars($query) ."<BR>error message: ". mysql_error() ."</PRE>"; - if (empty($qid)) watchdog(3, "error: ". mysql_error() ."<BR>query: ". htmlspecialchars($query) .""); + // debug output (if required): + if ($debug) print "<PRE>query: ". htmlspecialchars($query) ."<BR>error message: ". mysql_error() ."</PRE>"; + if (!$qid) watchdog("error", "database: ". mysql_error() ."<BR>query: ". htmlspecialchars($query) .""); - ### return result from query: + // return result from query: return $qid; } @@ -58,4 +51,4 @@ function db_result($qid, $field) { # db_connect(); -?> \ No newline at end of file +?> diff --git a/includes/function.inc b/includes/function.inc index 0215955d076b..3c3cd3afed52 100644 --- a/includes/function.inc +++ b/includes/function.inc @@ -23,8 +23,8 @@ function check_field($message) { } function check_input($message) { - global $allowed_html; - return strip_tags(addslashes($message), $allowed_html); + global $allowed_html, $submission_size; + return strip_tags(addslashes(substr($message, 0, $submission_size)), $allowed_html); } function check_output($message, $nl2br = 0) { diff --git a/includes/submission.inc b/includes/submission.inc index 23f608f7d70c..297bb0294df7 100644 --- a/includes/submission.inc +++ b/includes/submission.inc @@ -28,14 +28,14 @@ function submission_vote($id, $vote, $comment) { if ($submission = db_fetch_object($result)) { if ($submission->score >= $submission_post_threshold) { db_query("UPDATE stories SET status = 2, timestamp = '". time() ."' WHERE id = $id"); - watchdog(1, "posted story `$submission->subject'"); + watchdog("message", "posted story `$submission->subject'"); } if ($submission->score <= $submission_dump_threshold) { db_query("UPDATE stories SET status = 0, timestamp = '". time() ."' WHERE id = $id"); - watchdog(1, "dumped story `$submission->subject'"); + watchdog("message", "dumped story `$submission->subject'"); } } } } -?> \ No newline at end of file +?> diff --git a/includes/user.inc b/includes/user.inc index 62e5547bedb1..0db5821210c3 100644 --- a/includes/user.inc +++ b/includes/user.inc @@ -1,9 +1,5 @@ <? -$permissions = array("Administrator" => 0x00000001, - "User manager" => 0x00000002, - "News manager" => 0x00000004); - class User { function User($userid, $passwd = "") { $result = db_query("SELECT * FROM users WHERE LOWER(userid) = LOWER('$userid') && passwd = PASSWORD('$passwd') && STATUS = 2"); diff --git a/includes/watchdog.inc b/includes/watchdog.inc index efc4b461893b..78e481fd9d41 100644 --- a/includes/watchdog.inc +++ b/includes/watchdog.inc @@ -1,15 +1,30 @@ <? +$watchdog = array("comment" => array("0", $submission_rate["comment"]), + "diary" => array("1", $submission_rate["diary"]), + "story" => array("2", $submission_rate["story"]), + "message" => array("3", "0"), + "warning" => array("4", "0"), + "error" => array("5", "0")); -function watchdog($level, $message) { - global $user; +function watchdog($id, $message) { + global $user, $watchdog, $watchdog_history; - ### Perform query to add new log entry: - db_query("INSERT INTO watchdog (level, timestamp, user, message, location, hostname) VALUES ($level, '". time() ."', '". addslashes($user->id) ."', '". addslashes($message) ."', '". getenv("SCRIPT_NAME") ."', '". getenv("REMOTE_ADDR") ."')"); + if ($watchdog[$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"); + // header("Location: error.php"); + } + } + } + + // Perform query to add new watchdog entry: + db_query("INSERT INTO watchdog (level, timestamp, user, message, location, hostname) VALUES ('". $watchdog[$id][0] ."', '". time() ."', '". check_input($user->id) ."', '". check_input($message) ."', '". check_input(getenv("REQUEST_URI")) ."', '". check_input(getenv("REMOTE_ADDR")) ."')"); - ### Periodically remove old log entries: + // Periodically remove old watchdog entries: if (time() % 20 == 0) { - $timestamp = time() - 1209600; // 2 weeks + $timestamp = time() - $watchdog_history; db_query("DELETE FROM watchdog WHERE timestamp < $timestamp"); } } diff --git a/index.php b/index.php index 1790d8ab077c..041fd7ef5b67 100644 --- a/index.php +++ b/index.php @@ -2,6 +2,12 @@ include "includes/theme.inc"; +### Security check: +if (strstr($number, " ") || strstr($date, " ")) { + watchdog("error", "main page: attempt to provide malicious input through URI"); + exit(); +} + ### Initialize/pre-process variables: $number = ($user->stories) ? $user->stories : 10; $date = ($date) ? $date : time(); diff --git a/search.php b/search.php index 1ea6defc1573..d11331684a65 100644 --- a/search.php +++ b/search.php @@ -4,7 +4,7 @@ $theme->header(); - $terms = stripslashes($terms); + $terms = check_input($terms); $output .= "<TABLE WIDTH=\"100%\" BORDER=\"0\">\n"; $output .= " <TR VALIGN=\"center\">\n"; diff --git a/submission.php b/submission.php index cff39dc6ca52..ad1767ed07c9 100644 --- a/submission.php +++ b/submission.php @@ -1,4 +1,5 @@ <? + include "includes/submission.inc"; include "includes/theme.inc"; @@ -57,6 +58,12 @@ function submission_displayItem($id) { $theme->footer(); } +### Security check: +if (strstr($id, " ")) { + watchdog("error", "submission: attempt to provide malicious input through URI"); + exit(); +} + if ($user->id) { switch($op) { case "view": @@ -72,4 +79,4 @@ function submission_displayItem($id) { } } -?> \ No newline at end of file +?> diff --git a/submit.php b/submit.php index 121e9385f311..2d8309cdcf14 100644 --- a/submit.php +++ b/submit.php @@ -113,7 +113,8 @@ function submit_preview($subject, $abstract, $article, $category) { } else { $output .= "<P>\n"; - $output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Preview submission\"> <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Submit submission\">\n"; + $output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Preview submission\">\n"; + $output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Submit submission\">\n"; $output .= "</P>\n"; } @@ -128,22 +129,16 @@ function submit_preview($subject, $abstract, $article, $category) { function submit_submit($subject, $abstract, $article, $category) { global $user, $theme; + ### Add log entry: + watchdog("story", "added new story with subject `$subject'"); + ### Add submission to SQL table: - db_insert("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() ."')"); + 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() ."')"); ### Display confirmation message: $theme->header(); - $theme->box("Thanks for your submission.", "Thanks for your submission. The submission moderators in our basement will frown at it, poke at it, and vote for it!"); + $theme->box("Thank you for your submission.", "Thank you for your submission. The submission moderators in our basement will frown at it, poke at it, and vote for it!"); $theme->footer(); - - ### Send e-mail notification (if enabled): - if ($notify) { - $message = "New submission:\n\nsubject...: $subject\nauthor....: $user->userid <$user->real_email>\ncategory..: $category\nabstract..:\n$abstract\n\narticle...:\n$article"; - mail($notify_email, "$notify_subject $subject", $message, "From: $notify_from\nX-Mailer: PHP/" . phpversion()); - } - - ### Add log entry: - watchdog(1, "added new submission with subject `$subject'."); } include "includes/theme.inc"; diff --git a/themes/marvin/marvin.theme b/themes/marvin/marvin.theme index 916aab3828c6..c2e3631e4499 100644 --- a/themes/marvin/marvin.theme +++ b/themes/marvin/marvin.theme @@ -20,12 +20,12 @@ class Theme { # Syntax.......: header($title); # Description..: a function to draw the page header. function header($title) { - global $sitename; + global $site_name; ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <HTML> <HEAD> - <TITLE><? print $sitename; ?></TITLE> + <TITLE><? print $site_name; ?></TITLE> <META NAME="description" CONTENT="drop.org"> <META NAME="keywords" CONTENT="drop, weblog, portal, community, news, article, announcements, stories, story, computer, science, space, hype, cult, geek, nerd, foo, bar"> </HEAD> @@ -189,7 +189,7 @@ function comment($comment, $link, $thread = "") { ### Moderation: print " <TD ALIGN=\"right\" ROWSPAN=\"3\" VALIGN=\"middle\" WIDTH=\"15%\">\n"; - display_comment_moderation($comment->cid, $comment->poster, $comment->score, $comment->votes); + display_comment_moderation($comment->cid, $comment->userid, $comment->score, $comment->votes); print " </TD>\n"; print " </TR>\n"; diff --git a/themes/unconed/unconed.theme b/themes/unconed/unconed.theme index 2d6029b5725a..201a8c0a093c 100644 --- a/themes/unconed/unconed.theme +++ b/themes/unconed/unconed.theme @@ -31,12 +31,12 @@ class Theme { # Syntax.......: header($title); # Description..: a function to draw the page header. function header($title) { - global $sitename; + global $site_name; srand((double)microtime()*1000000); ?> <HTML> <HEAD> - <TITLE><? echo $sitename; ?></TITLE> + <TITLE><? echo $site_name; ?></TITLE> <META NAME="description" CONTENT="drop.org"> <META NAME="keywords" CONTENT="drop, weblog, portal, community, news, article, announcements, stories, story, computer, science, space, hype, cult, geek, nerd, foo, bar"> </HEAD> @@ -220,9 +220,7 @@ function commentControl($sid, $title, $threshold, $mode, $order) { function comment($comment, $link, $thread = "") { print "<A NAME=\"$comment->cid\"></A>\n"; - $timestamp = format_date($timestamp); - - print "\n<!-- Comment: \"$subject\" by $poster -->\n"; + print "\n<!-- Comment: \"$comment->subject\" by $comment->userid -->\n"; ?> <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0" BGCOLOR="<? echo $this->brcolor1; ?>" WIDTH="100%"> @@ -243,7 +241,7 @@ function comment($comment, $link, $thread = "") { ### Moderation: echo " <TD ALIGN=\"right\" ROWSPAN=\"3\" VALIGN=\"middle\" WIDTH=\"15%\">"; - display_comment_moderation($comment->cid, $comment->poster, $comment->score, $comment->votes); + display_comment_moderation($comment->cid, $comment->userid, $comment->score, $comment->votes); echo " </TD>"; echo " </TR>"; -- GitLab