\n");
+
+ // Get the start and end messages in the group...
+ $status = nntp_command($stream, "GROUP $group", 211);
+ if ((int)$status != 211)
+ {
+ nntp_error("We were unable to open the forum '$group' for the following "
+ ."reason:", $status, $group);
+ return (NULL);
+ }
+
+ // Read the messages in the group...
+ $fields = explode(" ", $status);
+ $status = nntp_command($stream, "XOVER $fields[2]-$fields[3]", 224);
+ if ((int)$status != 224)
+ {
+ nntp_error("We were unable to search the forum '$group' for the following "
+ ."reason:", $status, $group);
+ return (NULL);
+ }
+
+ $words = html_search_words($search);
+ $num_matches = 0;
+ $matches = NULL;
+
+ while ($line = fgets($stream, 1024))
+ {
+ $line = rtrim($line);
+
+ if ($line == ".")
+ break;
+
+// print("
" . htmlspecialchars($line) . "
\n");
+
+ if ($search == "")
+ {
+ // Return all matches...
+ $matches[$num_matches] = $line;
+ $num_matches ++;
+ }
+ else
+ {
+ // Search for words...
+ reset($words);
+
+ $fields = explode("\t", $line);
+
+ foreach ($words as $word)
+ {
+ if (stristr($fields[1], $word) || stristr($fields[2], $word))
+ {
+ $matches[$num_matches] = $line;
+ $num_matches ++;
+ break;
+ }
+ }
+ }
+ }
+
+ if ($threaded)
+ {
+ // Thread the articles...
+ $threads = array();
+ $parents = array();
+
+ for ($i = 0; $i < sizeof($matches); $i ++)
+ {
+ $fields = explode("\t", $matches[$i]);
+ $subject = eregi_replace("(re:|\\[[a-z]+\\.[a-z]+\\]) ", "", $fields[1]);
+
+ if (array_key_exists($subject, $parents))
+ $threads[$i] = sprintf("%06d%06d", $parents[$subject], $i);
+ else
+ {
+ $parents["$subject"] = $i;
+ $threads[$i] = sprintf("%06d%06d", $i, $i);
+ }
+ }
+
+ array_multisort($threads, SORT_NUMERIC, $matches);
+ }
+
+ // Return the matches...
+ return ($matches);
+}
+
+
+//
+// 'show_prevnext_page()' - Show the prev/next links for the messages list...
+//
+
+function
+show_prevnext_page($group, // I - Group
+ $group_filter, // I - Group filter
+ $start, // I - Start message
+ $end, // I - End message
+ $count, // I - Number of messages
+ $threaded) // I - Thread messages?
+{
+ global $PHP_SELF, $PAGE_MAX, $options;
+
+
+ print("
");
+ html_end_row();
+ html_end_table();
+
+ nntp_close($stream);
+
+ html_footer();
+}
+
+
+//
+// 'show_prevnext_msg()' - Show the prev/next links for the messages list...
+//
+
+function
+show_prevnext_msg($group, // I - Group
+ $group_filter, // I - Group filter
+ $start, // I - Start message
+ $count, // I - Number of messages
+ $msg, // I - Current message
+ $threaded) // I - Thread messages?
+{
+ global $PHP_SELF, $options;
+
+
+ print("
");
+ html_end_row();
+ html_end_table();
+
+ show_prevnext_msg($group, $group_filter, $start, $count, $msg, $threaded);
+
+ html_footer();
+}
+
+
+//
+// 'post_message()' - Post a message...
+//
+
+function
+post_message($group, // I - Group
+ $group_filter, // I - Group filter
+ $start, // I - Start message
+ $msg, // I - Current message
+ $search, // I - Search string
+ $threaded) // I - Thread messages?
+{
+ global $LOGIN_USER, $PHP_SELF, $PROJECT_URL, $_POST, $options;
+
+
+ // Get form data...
+ if (array_key_exists("FROM", $_POST))
+ $from = $_POST["FROM"];
+ else
+ $from = "";
+
+ if (array_key_exists("SUBJECT", $_POST))
+ $subject = $_POST["SUBJECT"];
+ else
+ $subject = "";
+
+ if (array_key_exists("BODY", $_POST))
+ $body = $_POST["BODY"];
+ else
+ $body = "";
+
+ // Validate form data...
+ if (!validate_email($from) || $subject == "" || $body == "")
+ {
+ new_message($group, $group_filter, $start, $from, $subject, $body);
+ return;
+ }
+
+ // Connect to the news server and get the reply-to message ID...
+ $stream = nntp_connect();
+ if (!$stream)
+ {
+ return;
+ }
+
+ $id = "";
+
+ if ($msg > 0)
+ {
+ $matches = nntp_search($stream, $group, $search, $threaded);
+ $count = count($matches);
+
+ if ($msg <= $count)
+ {
+ $fields = explode("\t", $matches[$msg - 1]);
+ $id = $fields[4];
+ }
+ }
+
+ // Create the message body...
+ $message = "From: $from\r\n"
+ ."Subject: $subject\r\n"
+ ."Newsgroups: $group\r\n";
+
+ if ($id != "")
+ $message .= "In-Reply-To: $id\r\n";
+
+ $message .= "X-Login-Name: $LOGIN_USER\r\n"
+ ."X-Site-URL: $PROJECT_URL\r\n"
+ ."\r\n";
+
+ $lines = explode("\n", $body);
+ $count = count($lines);
+
+ for ($i = 0; $i < $count; $i ++)
+ {
+ $line = rtrim($lines[$i]);
+
+ if ($line == ".")
+ $message .= ". \r\n";
+ else
+ $message .= "$line\r\n";
+ }
+
+ // Run the message by spamc to see if it thinks the message is
+ // spam...
+ $p = popen("spamc -c >/dev/null", "w");
+ if ($p)
+ {
+ fwrite($p, $message);
+ if (pclose($p))
+ {
+ // Message is spam...
+ nntp_header("$group Error",
+ array("All Forums" => "forums.php?g$options",
+ "Back to $group" => "forums.php?g$group+s$start$options"));
+
+ print("
Your message could not be posted for the following reason:
\n"
+ ."
The anti-spam filters determined that your message "
+ ."is most likely an unsolicited commercial message that is not "
+ ."allowed on this group. If this is not the case, please press your "
+ ."browser's Back button and check that the message does "
+ ."not contain common spam phrases like 'an offer for you' and so "
+ ."forth.
\n");
+
+ html_footer();
+ return;
+ }
+ }
+
+ // Post the message...
+ $status = nntp_command($stream, "POST", 340);
+
+ if ((int)$status != 340)
+ {
+ nntp_close($stream);
+ nntp_error("We were unable to post the requested message for the following "
+ ."reason:", $status, $group);
+ return;
+ }
+
+ fwrite($stream, $message);
+
+ // Get the posting status...
+ $status = nntp_command($stream, ".", 240);
+
+ if ((int)$status == 240)
+ {
+ if ($msg == 0)
+ header("Location: $PHP_SELF?s$start+g$group$options");
+ else
+ header("Location: $PHP_SELF?s$start+g$group+v$msg$options");
+ }
+ else
+ nntp_error("We were unable to post the requested message for the following "
+ ."reason:", $status, $group);
+
+ nntp_close($stream);
+}
+
+
+//
+// 'reply_message()' - Reply to a message...
+//
+
+function
+reply_message($group, // I - Group to reply to
+ $group_filter, // I - Group filter
+ $start, // I - First message in the display
+ $msg, // I - Message to reply to
+ $search, // I - Search string
+ $threaded, // I - Thread messages?
+ $sender) // I - Sender address
+{
+ // Figure out which messages to show...
+ $stream = nntp_connect();
+ $matches = nntp_search($stream, $group, $search, $threaded);
+ $count = count($matches);
+
+ if ($msg < 1 || $msg > $count)
+ {
+ nntp_close($stream);
+ return;
+ }
+
+ $fields = explode("\t", $matches[$msg - 1]);
+ $msgnum = (int)$fields[0];
+ $subject = eregi_replace("\\[[a-z]+\\.[a-z]+\\] ", "", $fields[1]);
+ $author = sanitize_email($fields[2]);
+ $date = htmlspecialchars($fields[3], ENT_QUOTES);
+
+ if (strncasecmp($subject, "re:", 3))
+ $subject = "Re: " . $subject;
+
+ $status = nntp_command($stream, "BODY $msgnum", 222);
+ if ((int)$status != 222)
+ {
+ nntp_close($stream);
+ nntp_error("We were unable to reply to the requested message for the following "
+ ."reason:", $status, $group);
+ return;
+ }
+
+ $body = "";
+ while ($line = fgets($stream, 1024))
+ {
+ $line = rtrim($line);
+
+ if ($line == ".")
+ break;
+
+ $body = $body . "> " . $line . "\n";
+ }
+
+ nntp_close($stream);
+
+ new_message($group, $group_filter, $start, $subject, $sender, $body);
+}
+
+
+//
+// 'new_message()' - Post a new message...
+//
+
+function
+new_message($group, // I - Group to post to
+ $group_filter, // I - Group filter
+ $start, // I - First message
+ $subject, // I - Subject of message
+ $sender, // I - Sender address
+ $body) // I - Message body
+{
+ global $PHP_SELF, $NNTPSPEC, $options;
+
+
+ $subject = htmlspecialchars($subject, ENT_QUOTES);
+ $sender = htmlspecialchars($sender, ENT_QUOTES);
+ $body = htmlspecialchars($body, ENT_QUOTES);
+
+ nntp_header("Post Message to $group",
+ array("All Forums" => "forums.php?g$options",
+ "Back to $group" => "forums.php?g$group+s$start$options"));
+
+ print("
");
}
@@ -188,8 +191,8 @@ function
html_footer()
{
print("
\n"
- ."
"
- ."Copyright 2003-2007 by Michael Sweet. This library is free "
+ ."
"
+ ."Copyright 2003-2008 by Michael Sweet. This library is free "
."software; you can redistribute it and/or modify it "
."under the terms of the GNU Library General Public "
."License as published by the Free Software Foundation; "