Приглашаем посетить
BBS_FORUM
#!/usr/local/bin/perl
############################################################
# BBS_FORUM.CGI
#
# This script was written by Gunther Birznieks
# Date Created: 4-18-96
#
# You may copy this under the terms of the GNU General Public
# License or the Artistic License which is distributed with
# copies of Perl v5.x for UNIX
#
# Purpose: To provide routines for all BBS Forum activities including
# Posting, Replying, Reading Messages, Deleting old messages, Filtering
# Messages, and Filtering HTML based on Authentication Scripts.
#
# Main Procedures:
# &PrintPostOrReplyPage = Prints Post/Reply Data EntryScreen
# &CreatePosting = Posts a Message
# &ReadMessage = Reads a message
# &PrintForumPage = Lists all the posts in a forum
#
# Inputs:
# Form Variables:
# forum = Forum name
# setup = Setup file identifier. Default is "bbs".
# session = Session code for authentication
# post_op = is this a post
# reply_op = is this a reply
# create_message_op = is this a create message
# read = message to read
#
# Form Variables for pruning List of Messages displayed:
# first_date = First date in range to view messages
# last_date = Last date in range to view messages
# first_days_old = earliest number of days old to view msgs
# last_days_old = latest number of days old to view msgs
# keywords = keywords to search for
# exact_match = "on" if the search is exact rather than pattern
# match based
#
# use_last_read = "on" if $display_new_messages is on,
# and we want to only see new messages since
# our last read. This only works with
# authentication activated.
#
# last_read = Last message read in the forum.
#
# Outputs:
# Depending on the previous form variables, the output
# will be a list of forum messages, posting screen, or
# reading messages screen.
#
# SPECIAL NOTE:
#
# If you are interested in file attachments, you must
# set that information in the following variables:
# $allow_user_attachments, $maximum_attachment_size,
# $attach_dir, $attach_url. These variables are set below.
#
############################################################
$lib = "./Library";
# Read in core BBS variables
require "./bbs.setup";
require "$lib/cgi-lib.pl";
#$| = 1; # Used for troubleshooting
print &PrintHeader;
if ($allow_user_attachments eq "on") {
$cgi_lib'maxdata = $maximum_attachment_size;
$cgi_lib'writefiles = "$attach_dir";
}
&ReadParse;
# Allow override of bbs.setup variables if a setup
# form variable has been invoked
#
$setup_file = $in{"setup"};
if ($setup_file ne "") {
require "$setup_file.setup";
}
require "$auth_lib/auth-lib.pl";
# the following sets a defualt BBS script if one is not
# defined.
if ($bbs_script eq "") {
$bbs_script = "bbs_forum.cgi";
}
$forum = $in{"forum"};
($forum_name, $forum_dir) = &GetForumInfo($forum);
$session = $in{"session"};
$is_this_a_new_session = "yes" if ($session eq "");
($session, $username, $group,
$firstname, $lastname, $email) =
&GetSessionInfo($session, "$bbs_script", *in);
$reply_op = $in{"reply_op"};
$reply_op = "on" if ($in{"reply_op.x"} ne "");
$post_op = $in{"post_op"};
$post_op = "on" if ($in{"post_op.x"} ne "");
$create_message_op = $in{"create_message_op"};
$read = $in{"read"};
# $first_date and $last_date allow date parameters to be specified for
# looking at messages along with a keyword search of messages and
# exact match keyword searching on/off.
#
$first_date = $in{"first_date"};
$last_date = $in{"last_date"};
$keywords = $in{"keywords"};
$exact_match = $in{"exact_match"};
$first_days_old = $in{"first_days_old"};
$last_days_old = $in{"last_days_old"};
#
# $create_msg_error will print out as part of the print_forum
# listing if a problem occured while posting a message
#
$create_msg_error = "";
# Use_last_read tells us to use the last read value for the
# user if authentication is turned on.
#
$use_last_read = $in{"use_last_read"};
#
# last_read is the actual value of the last read
# message
#
$last_read = $in{"last_read"};
#
# The following is for posting/replying HTML generation
#
if (($reply_op ne "") || ($post_op ne ""))
{
&PrintPostOrReplyPage;
}
#
# The following is for creating the posts
#
elsif ($create_message_op ne "")
{
&CreatePosting;
}
elsif ($read ne "")
{
&ReadMessage($read);
}
elsif ($forum ne "")
{
&PrintForumPage;
}
############################################################
#
# subroutine: ReadMessage
# Usage:
# &ReadMessage($message);
#
# Parameters:
# $message = message filename to read
#
# Output:
# Takes a message and outputs it as HTML
# Dependant on the bbs_html_read_message.pl file
############################################################
sub ReadMessage
{
local($message) = @_;
local($poster_firstname, $poster_lastname,
$poster_email,$post_date_time,
$post_subject, $post_options) =
&GetMessageHeader("$forum_dir/$message");
open (MESSAGEFILE, "$forum_dir/$message") ||
&CgiDie("Could Not Open Message File\n");
for (1 .. 6) { <MESSAGEFILE>; } # Throwaway header
$post_message = "";
while (<MESSAGEFILE>)
{
$post_message .= $_;
}
close (MESSAGEFILE);
if ($no_html_images eq "on")
{
$post_message =~ s/<(IMG\s*SRC.*)>/<$1>/ig;
$post_subject =~ s/<(IMG\s*SRC.*)>/<$1>/ig;
} # End of parsing out no images
if ($no_html eq "on")
{
$post_message =~ s/<([^>]+)>/\<$1>/ig;
$post_subject =~ s/<([^>]+)>/\<$1>/ig;
} # End of No html
$post_message =~ s/\n\r\n/<p>/g;
$post_message =~ s/\n/<br>/g;
opendir(FORUMDIR, "$forum_dir") ||
&CgiDie("Could not open $forum_dir directory\n");
$message_number = substr($message,0,6);
@files = sort(grep(/.......$message_number\.msg$/,
readdir(FORUMDIR)));
closedir(FORUMDIR);
$message_url = &ReadMessageFields;
$post_replies = "";
foreach (@files) {
($reply_firstname, $reply_lastname, $reply_email,
$reply_date_time, $reply_subject,
$reply_options) =
&GetMessageHeader("$forum_dir/$_");
$post_replies .=
qq!<A HREF="$bbs_script?forum=$forum!;
$post_replies .=
qq!&read=$_&$message_url">!;
$post_replies .=
" $reply_subject " .
"(Modified: $reply_date_time)</A><BR>\n";
}
$attach_file = substr($message,0,13) . ".attach";
$post_attach_html = "";
if (-e "$forum_dir/$attach_file") {
open(ATTACHFILE, "$forum_dir/$attach_file") ||
&CgiDie("Could Not Open $forum_dir/$attach_file\n");
chop($attach_info = <ATTACHFILE>);
($post_attachment, $post_attachment_filename) =
split(/\|/, $attach_info);
$post_attach_html =
qq!<BR><B>Attached File:</B> ! .
qq!<A HREF="$attach_url/$post_attachment">
$post_attachment_filename</A><BR>!;
close (ATTACHFILE);
}
require "bbs_html_read_message.pl";
} # End of ReadMessage
############################################################
#
# subroutine: PrintForumPage
# Usage:
# &PrintForumPage;
#
# Parameters:
# None, but CGI Form Variables below affect
# the list of information that comes up
# first_date = Date To Start Reading Messages From
# last_date = Date To Last Reading
# keywords = Keywords To Search On
# exact_match= Keyword Search Exact_match
# first_days_old= Start Reading Messages From
# This Days old
# last_days_old =Finish Reading Messages From
# This Days Old
#
# Output:
# Prints the message list in a forum based on
# last read for the user, date ranges, and keyword
# search if the program is configured for that.
#
############################################################
sub PrintForumPage
{
local($x);
opendir(FORUMDIR, "$forum_dir") ||
&CgiDie("Could Not Open Forum Directory\n");
@files = sort(grep(/.*msg$/,readdir(FORUMDIR)));
closedir(FORUMDIR);
$high_number = substr($files[@files - 1],0,6);
$low_number = substr($files[0],0,6);
#
# Here we delete old messages based on the global variables if we
# are starting a new session.
#
&PruneOldMessages($forum_dir, *files);
#
# If $last_read = something then we have read the forum before
#
# if this is a new session, we update the $last_read, if it is an
# old session, we open the user file to get the last read to compare
# against
#
if ($display_only_new_messages eq "on"
&& $last_read eq ""
&& $use_last_read eq "on") {
$last_read =
&GetUserLastRead($forum_dir,
$username, $session, $high_number);
}
$last_read = 0 if ($last_read eq "");
#
# Pruning the file list narrows down what displays to the
# user. $last_read is the default parameter,
#
&PruneFileList(*files, $last_read, $first_date,
$last_date, $first_days_old,
$last_days_old, $keywords,
$exact_match, $forum_dir);
# if @files < 1 then we have no messages
# otherwise we need to process them as a tree.
$message_html = "";
@threads = ();
while (@files > 0)
{
push(@threads,&MakeThreadList(*files));
}
$ul_count = 0;
$prev_level = -1;
foreach $x (@threads) {
($level,$messagefile, $thread_date) =
split(/\|/,$x);
if ($level > $prev_level &&
$level > $display_thread_depth) {
$level = $prev_level;
}
if ($level > $prev_level) {
$ul_count++;
$message_html .= "<UL>\n";
} elsif ($level < $prev_level) {
for (1 .. ($prev_level - $level)) {
$ul_count--;
$message_html .= "</UL>\n";
}
}
if ($level == $prev_level) {
if ($use_list_element ne "on"
|| $level == 1) {
$message_html .= "<br>";
}
$message_html .= "\n";
}
if ($level > 1 && $use_list_element eq "on") {
$message_html .= "<LI>";
}
($poster_firstname, $poster_lastname, $poster_email,
$post_date, $post_subject, $post_options) =
&GetMessageHeader("$forum_dir/$messagefile");
$message_url = &ReadMessageFields;
$message_html .=
qq!<A HREF="$bbs_script?forum=$forum!;
$message_html .=
qq!&read=$messagefile&$message_url">\n!;
$message_html .=
" $post_subject ($post_date)";
if ($level == 1 && $thread_date ne $post_date)
{
$message_html .=
" (Thread Modified:$thread_date)";
}
$message_html .= "</A>";
$prev_level = $level;
} # End of foreach thread
$message_html .= "\n";
for (1..$ul_count) {
$message_html .= "</UL>\n";
}
require "bbs_html_forum.pl";
} # end of PrintForumPage
############################################################
#
# subroutine: PrintPostOrReplyPage
# Usage:
# &PrintPostOrReplyPage;
#
# Parameters:
# None, but CGI Form Variables below affect
# the form that comes up if the action that
# is being taken is a reply to a message instead
# of a fresh post.
# reply_to_message = Message # We are replying to
# email_reply = email to notify that a reply has
# occured
# post_subject = Subject of message we are
# replying to.
#
# Output:
# HTML Output for the Create Post (or Reply) Page
#
############################################################
sub PrintPostOrReplyPage
{
local($options, $previous_message);
local($reply_to_message, $email_reply);
local($title, $header);
local($email_tag, $reply_to_email);
$previous_message = "";
$reply_to_message = "";
$email_reply = "";
$title = "Post A Message";
$header = "Posting Message To $forum_name";
if ($reply_op ne "")
{
$reply_to_message = $in{"reply_to_message"};
$email_reply = $in{"email_reply"};
$title = "Reply To A Message";
$header =
"Replying To A Message In $forum_name";
$post_message = "";
open (REPLYFILE,
"$forum_dir/$reply_to_message") ||
&CgiDie("Could not open reply message");
chop($post_first_name = <REPLYFILE>);
chop($post_last_name = <REPLYFILE>);
<REPLYFILE>;
chop($post_date = <REPLYFILE>);
<REPLYFILE>;
chop($options = <REPLYFILE>);
if ($options =~ /^options:/) {
$options = substr($options,8);
($email_tag,$reply_to_email) =
split(/:/,$options);
}
while (<REPLYFILE>) {
$post_message .= $_;
}
$post_message =~ s/^/>>/g;
$post_message =~ s/\r/\r>>/g;
$post_message =~ s/\n/\n>>/g;
$post_message =
"$post_first_name $post_last_name" .
" on $post_date said:\n\n"
. $post_message;
close (REPLYFILE);
$post_subject = $in{"post_subject"};
$post_subject = "Re: $post_subject"
if !($post_subject =~ /^Re:/i);
}
$post_date_time = &GetDateAndTime;
$post_first_name_field = qq!<INPUT TYPE=text
NAME=form_firstname VALUE="$firstname"
SIZE=40 MAXLENGTH=50>!;
$post_last_name_field = qq!<INPUT TYPE=text
NAME=form_lastname VALUE="$lastname"
SIZE=40 MAXLENGTH=50>!;
$post_email_field = qq!<INPUT TYPE=text
NAME=form_email VALUE="$email"
SIZE=40 MAXLENGTH=50>!;
if ($force_first_name eq "on"
&& $firstname ne "") {
$post_first_name_field =
qq!<INPUT TYPE=hidden
NAME=form_firstname VALUE="$firstname">!;
$post_first_name_field .= "$firstname";
}
if ($force_last_name eq "on"
&& $lastname ne "") {
$post_last_name_field =
qq!<INPUT TYPE=hidden
NAME=form_lastname VALUE="$lastname">!;
$post_last_name_field .= "$lastname";
}
if ($force_email eq "on"
&& $email ne "") {
$post_email_field =
qq!<INPUT TYPE=hidden
NAME=form_email VALUE="$email">!;
$post_email_field .= "$email";
}
$post_want_email = "";
if ($allow_reply_email eq "on") {
$post_want_email =
"<BR><INPUT TYPE=CHECKBOX" .
" NAME=post_want_email>" .
"Check Here If You Want Replies " .
"Emailed To You Automatically<BR>";
}
$post_attachment = "";
if ($allow_user_attachments eq "on") {
$post_attachment =
"<P>Attach A File Here:
<INPUT TYPE=FILE NAME=post_attachment><BR>";
}
require "bbs_html_create_message.pl";
} # End of PostOrReply
############################################################
#
# subroutine: CreatePosting
# Usage:
# &CreatePosting;
#
# Parameters:
# None, but CGI Form Variables below affect
# how the message is posted.
# form_firstname = firstname of poster
# form_lastname = lastname of poster
# form_email = email of poster
# form_subject = subject of the post
# form_message = body of the post
# reply_to_message = message we are replying to
# reply_to_email = email address of user we are
# replying to
# post_want_email = "on" if we want email replies
# post_attachment = file upload attachment
#
# Output:
# Posts the message to a file and then prints the
# list of forum messages.
#
############################################################
sub CreatePosting
{
local ($create_error);
$form_firstname = $in{"form_firstname"};
$form_lastname = $in{"form_lastname"};
$form_email = $in{"form_email"};
$form_subject = $in{"form_subject"};
$form_firstname =~ s/\n//g;
$form_lastname =~ s/\n//g;
$form_email =~ s/\n//g;
$form_subject =~ s/\n//g;
$form_message = $in{"form_message"};
$reply_to_message = $in{"reply_to_message"};
if ($reply_to_message < 1)
{
$reply_to_message = "000000";
} else {
$reply_to_message =
substr($reply_to_message,0,6);
}
$reply_to_email = $in{"reply_to_email"};
$post_date_time = &GetDateAndTime;
$form_options = "";
$post_want_email = $in{"post_want_email"};
if ($post_want_email eq "on"
|| $force_reply_email eq "on") {
$form_options = "email:$form_email";
}
$create_error = 0;
if ($require_subject eq "on" &&
$form_subject eq "") {
$create_error = 1;
$create_msg_error .=
"You Did Not Enter A Subject.</H2>";
}
if ($require_first_name eq "on" &&
$form_firstname eq "") {
$create_error = 1;
$create_msg_error .=
"You Did Not Enter Your First name.</H2>";
}
if ($require_last_name eq "on" &&
$form_lastname eq "") {
$create_error = 1;
$create_msg_error .=
"You Did Not Enter Your Last Name.</H2>";
}
if ($require_email eq "on" &&
$form_email eq "") {
$create_error = 1;
$create_msg_error .=
"You Did Not Enter An Email Address.</H2>";
}
if ($create_error == 1) {
$create_msg_error = "<HR><H2>Error Posting To BBS. " .
$create_msg_error;
}
if ($create_error != 1) {
$whole_msg = "";
$whole_msg .= "$form_firstname\n";
$whole_msg .= "$form_lastname\n";
$whole_msg .= "$form_email\n";
$whole_msg .= "$post_date_time\n";
$whole_msg .= "$form_subject\n";
$whole_msg .= "options:$form_options\n";
$whole_msg .= "$form_message\n";
opendir(FORUMDIR, "$forum_dir") ||
&CgiDie("Couldn't Open $forum_dir");
@files = sort(grep(/.*msg$/,readdir(FORUMDIR)));
closedir(FORUMDIR);
$high_number = substr($files[@files - 1],0,6);
@files = ();
$high_number++;
$high_number = sprintf("%6d",$high_number);
$high_number =~ tr/ /0/;
$high_number = "000001"
if ($high_number eq "000000");
$message_name = "$high_number-$reply_to_message";
open(WRITEMSG, ">$forum_dir/$message_name.msg") ||
&CgiDie("Could't open $message_name.msg for writing");
print WRITEMSG $whole_msg;
close (WRITEMSG);
$post_attachment = $in{"post_attachment"};
$post_attachment_filename =
$incfn{"post_attachment"};
#
# Parse out the %Hex symbols and make it into alphanumeric
#
$post_attachment_filename =~
s/%([A-Fa-f0-9]{2})/pack("c",hex($1))/ge;
if ($post_attachment_filename ne "") {
rename($post_attachment,
"$attach_dir/$forum-$message_name.bin");
open(WRITEATTACH,
">$forum_dir/$message_name.attach") ||
&CgiDie("Could Not Open Attachment\n");
print WRITEATTACH
"$forum-$message_name.bin" .
"|$post_attachment_filename\n";
close(WRITEATTACH);
} else {
unlink("$post_attachment");
}
#
# The following handles the email system
#
$reply_to_email = $in{"reply_to_email"};
if ($reply_to_email ne "" &&
$send_reply_email eq "on") {
require "$lib/mail-lib.pl";
$reply_subject =
"Reply to your $forum_name message.";
&send_mail($from_email, $reply_to_email,
$reply_subject,
"The Message:\n\n" . $form_message);
} # End of reply_to_email
} # end of if $create_error == 1
&PrintForumPage;
} # End of CreatePosting
############################################################
#
# subroutine: PruneFileList
# Usage:
# &PruneFileList(*files, $last_read, $first_date,
# $last_date, $first_days_old, $last_days_old,
# $keywords, $exact_match, $forum_dir);
#
# Parameters:
# The non-filename related parameters are criteria
# used to prune the file list down so that not all
# the messages show up in the forum message list.
#
# *files = reference to a list of message filenames
# in the forum for pruning.
# $last_read = last read message number for the user
# so that only new messages are read
# $first_days_old= Start Reading Messages From
# This Days old
# $last_days_old =Finish Reading Messages From
# This Days Old
# $first_date = Date To Start Reading Messages From
# $last_date = Date To Last Reading
# $keywords = Keywords To Search On
# $exact_match= Keyword Search Exact_match
#
# Output:
# Prunes a list of messages that do not satisfy the
# criteria being passed to the routine (Such as a
# date range) from the *files reference to an array
# of message filenames.
#
############################################################
sub PruneFileList
{
local(*files, $last_read, $first_date, $last_date,
$first_days_old, $last_days_old, $keywords,
$exact_match, $forum_dir) = @_;
local($x, $filename);
local($month, $day, $year, $comp_date);
local($file_date);
@keyword_list = split(/\s+/,$keywords);
for ($x = @files; $x > 0; $x--)
{
#
# CASE 1: Prune becauase we've read this already
#
if ($last_read > 0
&& substr($files[$x-1],0,6) <= $last_read
&& $display_only_new_messages eq "on")
{
&RemoveElement(*files,$x-1);
next;
}
$filename = "$forum_dir/$files[$x - 1]";
#
# CASE 2: Prune because it does not fit range of days old
#
if (($first_days_old ne "")
&& ((-M $filename) > $first_days_old)) {
&RemoveElement(*files,$x-1);
next;
}
if (($last_days_old ne "")
&& ((-M $filename) < $last_days_old)) {
&RemoveElement(*files, $x-1);
next;
}
#
# CASE 3: Prune because it does not fit date range
#
# If we are comparing the files by date, we need to get
# date statistics
if ($first_date ne ""
|| $last_date ne "") {
($month, $day, $year) =
split(/\//, $first_date);
# We need to pad the month and day to be two digits for
# date comparison
$month = "0" . $month
if (length($month) < 2);
$day = "0" . $day
if (length($day) < 2);
# if the year was entered as two digits, we should convert it
# to a 4 digit year. Years from 51-99 are taken to be 1951 and
# 1999. Years from 00-50 are 2000 to 2050.
if ($year > 50 && $year < 1900) {
$year += 1900;
}
if ($year < 1900) {
$year += 2000;
}
# We order the date in order of year, month, and day. This allows
# us to use a normal numeric comparison between days to see which is
# greater than another one.
#
# Since days make up months and months make up years, putting them
# in this order works for normal >,< comparisons.
#
# eg 19960115 is numerically greater than 19951230.
#
$comp_first_date = $year . $month . $day;
($month, $day, $year) =
split(/\//, $last_date);
$month = "0" . $month
if (length($month) < 2);
$day = "0" . $day if (length($day) < 2);
if ($year > 50 && $year < 1900) {
$year += 1900;
}
if ($year < 1900) {
$year += 2000;
}
$comp_last_date = $year . $month . $day;
#$filedate = (-M $filename);
$file_date = (stat($filename))[9];
($day, $month, $year) =
(localtime($file_date))[3,4,5];
$month++;
$month = "0" . $month
if (length($month) < 2);
$day = "0" . $day if (length($day) < 2);
if ($year > 50 && $year < 1900) {
$year += 1900;
}
if ($year < 1900) {
$year += 2000;
}
$file_date = $year . $month . $day;
if ($first_date ne "") {
if ($file_date < $comp_first_date) {
&RemoveElement(*files, $x-1);
next;
}
} # End of first date
if ($last_date ne "") {
if ($file_date > $comp_last_date) {
&RemoveElement(*files, $x-1);
next;
}
} # End of last date
} # End of First or Last Date
#
# CASE 4: Prune because keywords not found in file
#
if ($keywords ne "") {
@not_found_words = @keyword_list;
open(SEARCHFILE, $filename);
while(<SEARCHFILE>) {
$line = $_;
&FindKeywords($exact_match, $line,
*not_found_words);
} # End of SEARCHFILE
close (SEARCHFILE);
# If any keywords were not found prune the file
if (@not_found_words > 0) {
&RemoveElement(*files, $x - 1);
next;
}
} # End of keywords
} # End of for loop
} # End of PruneFileList
############################################################
#
# subroutine: FindKeywords
# Usage:
# &FindKeywords($exact_match, $line,
# *not_found_words);
#
# Parameters:
# $exact_match = 'on' if keyword search is exact match
# $line = line to search
# *not_found_words = array of words we have not
# found yet.
#
# Output:
# *not_found_words array gets elements deleted as the
# keywords get found in the $line.
#
############################################################
sub FindKeywords
{
local($exact_match, $line, *not_found_words) = @_;
local($x, $match_word);
if ($exact_match eq "on") {
for ($x = @not_found_words; $x > 0; $x--) {
# \b matches on word boundary
$match_word = $not_found_words[$x - 1];
if ($line =~ /\b$match_word\b/i) {
splice(@not_found_words,$x - 1, 1);
} # End of If
} # End of For Loop
} else {
for ($x = @not_found_words; $x > 0; $x--) {
$match_word = $not_found_words[$x - 1];
if ($line =~ /$match_word/i) {
splice(@not_found_words,$x - 1, 1);
} # End of If
} # End of For Loop
} # End of ELSE
} # End of FindKeywords
############################################################
#
# subroutine: GetUserLastRead
# Usage:
# &GetUserLastRead($forum_dir, $username, $high_number);
#
# Parameters:
# $forum_dir = directory path for the forum
# $username = username dirived from authentications
# $session = session id
# $high_number = the highest message number
#
# Output:
# Returns $last_read = last read message number.
# $last_read is written over with the highest message
# number IF the session id is different from the session
# from the last_read
#
############################################################
sub GetUserLastRead
{
local($forum_dir, $username,
$session, $high_number) = @_;
local($last_read, $old_session);
unless (-e "$forum_dir/$username.dat")
{
$last_read = 0;
}
else
{
open (USERFILE, "$forum_dir/$username.dat") ||
&CgiDie("Error Opening Userfile $username\n");
$last_read = <USERFILE>;
$old_session = <USERFILE>;
chop ($last_read);
chop($old_session);
close (USERFILE);
}
if ($session ne $old_session) {
open (USERFILE, ">$forum_dir/$username.dat") ||
&CgiDie("Error Opening Userfile $username\n");
print USERFILE "$high_number\n";
print USERFILE "$session\n";
close (USERFILE);
}
$last_read;
} #End of GetUserLastRead
############################################################
#
# subroutine: GetDateAndTime
# Usage:
# &GetDateAndTime(;
#
# Parameters:
# None.
#
# Output:
# Returns a string of the current date and time.
#
############################################################
sub GetDateAndTime
{
local ($sec, $min, $hour, $mday, $mon);
local($year, $wday, $yday, $isdst);
local ($ampm, $currentdatetime);
($sec, $min, $hour, $mday, $mon,
$year, $wday, $yday, $isdst) =
localtime(time);
$mon++;
$ampm = "AM";
$ampm = "PM" if ($hour > 11);
$hour = $hour - 12 if ($hour > 12);
if (length($min) == 1)
{
$min = "0" . $min;
}
"$mon/$mday/$year $hour:$min $ampm";
} # End of GetDateAndTime
############################################################
#
# subroutine: GetMessageHeader
# Usage:
# &GetMessageHeader($filename);
#
# Parameters:
# $filename = message filename to read header from
#
# Output:
# Returns an array of the items in the message header.
#
# $poster_firstname = first name
# $poster_lastnamne = last name
# $poster_email = email address of poster
# $post_date = date/time of the posting
# $post_subject = subject of the post
# $post_options = post options
#
############################################################
sub GetMessageHeader
{
local($filename) = @_;
local($poster_firstname, $poster_lastname,
$poster_email, $post_date,
$post_subject, $post_options);
open (MESSAGEFILE, "$filename") ||
&CgiDie("Could Not Open $filename hdr\n");
chop($poster_firstname = <MESSAGEFILE>);
chop($poster_lastname = <MESSAGEFILE>);
chop($poster_email = <MESSAGEFILE>);
chop($post_date = <MESSAGEFILE>);
chop($post_subject = <MESSAGEFILE>);
chop($post_options = <MESSAGEFILE>);
if ($post_options =~ /^options:/) {
$post_options = substr($post_options,8);
}
close(MESSAGEFILE);
($poster_firstname, $poster_lastname, $poster_email,
$post_date, $post_subject, $post_options);
} # End of GetMessageHeader
############################################################
#
# subroutine: MakeThreadList
# Usage:
# &MakeThreadList(*file_list);
#
# Parameters:
# *file_list = array of message file names to make
# a threaded, hierarchical message
# listing out of.
#
# Output:
# @threads = an array containing the threaded,
# hierarchical message structure.
#
#
############################################################
sub MakeThreadList
{
local(*file_list) = @_;
local(@threads,$seq_ptr);
local($sequence,$previous);
$seq_ptr = @file_list - 1;
if ($seq_ptr > -1)
{
($poster_firstname, $poster_lastname, $poster_email,
$post_date, $post_subject, $post_options) =
&GetMessageHeader("$forum_dir/@file_list[$seq_ptr]");
while(1)
{
@file_list[$seq_ptr] .= "|$post_date";
$sequence = @file_list[$seq_ptr];
$previous = substr($sequence,7,6);
$previous_pointer =
&GetPointer(*file_list, $previous);
if (($previous eq "000000") ||
($previous_pointer == -1))
{
last;
}
$seq_ptr = $previous_pointer;
} #End of while loop
# $sequencepoint is now the top of the thread for the highest sequence #
@seq_stack = ($seq_ptr);
$cur_stack_size = 1;
push(@threads, "$cur_stack_size|$sequence");
while(@file_list > 0)
{
$next_seq = substr($sequence,0,6);
$next_ptr =
&GetNextThread(*file_list, $next_seq, $seq_ptr);
if ($next_ptr > -1)
{
$cur_stack_size++;
push(@seq_stack, $next_ptr);
$sequence = $file_list[$next_ptr];
$seq_ptr = $next_ptr;
push(@threads, "$cur_stack_size|$sequence");
}
else
{
@file_list =
&RemoveElement(*file_list, $seq_ptr);
$cur_stack_size--;
pop(@seq_stack);
if (@seq_stack > 0)
{
$seq_ptr =
$seq_stack[@seq_stack - 1];
$sequence = $file_list[$seq_ptr];
}
else
{
last;
}
}
} # End of While Loop
@threads;
} # End of if seq_ptr > 0
else {
# if there are no sequence numbers, return nothing for a thread
();
} # End of IF Seq_ptr > 0
} # end of MakeThreadList
############################################################
#
# subroutine: GetPointer
# Usage:
# &GetPointer(*file_list, $seq);
#
# Parameters:
# *file_list = list of files
# $seq = sequence number
#
# Output:
# Returns a numerical pointer into the array of
# files where the sequence number appears as the
# message number. Remember, messages appear as
# [MESSAGE NUMBER]-[REPLY TO NUMBER].MSG format.
# where the message number and reply to number
# are a fixed 6 digits.
#
############################################################
sub GetPointer
{
local(*file_list, $seq) = @_;
local($pointer,$x);
$pointer = -1;
for ($x = 0;$x < @file_list; $x++)
{
if (substr($file_list[$x],0,6) eq $seq)
{
$pointer = $x;
last;
}
}
$pointer;
} # End of GetPointer
############################################################
#
# subroutine: GetNextThread
# Usage:
# &GetNextThread(*file_list, $seq, $start);
#
# Parameters:
# *file_list = list of message filenames
# $seq = sequence/message # to search for
# $start = pointer into array to start searching from
#
# Output:
# Returns the pointer into the array of message
# filenames where the next reply to the message # is.
#
############################################################
sub GetNextThread
{
local(*file_list, $seq, $start) = @_;
local($pointer, $x);
$pointer = -1;
for ($x = $start; $x < @file_list; $x++)
{
if (substr($file_list[$x],7,6) eq $seq)
{
$pointer = $x;
last;
}
}
$pointer;
} # End of GetNextThread
############################################################
#
# subroutine: RemoveElement
# Usage:
# &RemoveElement;
#
# Parameters:
# *file_list = array of message numbers
# $number = pointer into the array of the
# element to remove
#
# Output:
# *file_list without the $number element.
#
############################################################
sub RemoveElement
{
local(*file_list, $number) = @_;
if ($number > @file_list)
{
die "Number was higher than " .
"number of elements in file list";
}
splice(@file_list,$number,1);
@file_list;
} # End of RemoveElement
############################################################
#
# subroutine: GetForumInfo
# Usage:
# &GetForumInfo($forum);
#
# Parameters:
# $forum = abbreviated forum identifier
#
# Output:
# Returns an array of the forum name and forum
# directory.
#
############################################################
sub GetForumInfo
{
local($forum) = @_;
local($forum_name, $forum_dir, $x);
local($forum_number);
$forum_number = -1;
for ($x = 1; $x <= @forum_variable; $x++)
{
if ($forum_variable[$x - 1] eq $forum)
{
$forum_number = $x - 1;
last;
}
} # End of FOR forum_variables
if ($forum_number > -1)
{
$forum_name = @forums[$forum_number];
$forum_dir = @forum_directories[$forum_number];
} else
{
$forum_name="";
$forum_dir = "";
if ($forum eq "") {
$forum = "Forum Not Entered";
}
$error =
"<strong>Forum '$forum' Not Found</strong>";
require "bbs_html_error.pl";
die;
}
($forum_name, $forum_dir);
} # end of GetForumInfo
############################################################
#
# subroutine: PruneOldMessages
# Usage:
# &PruneOldMessages($forum_dir, *files);
#
# Parameters:
# $forum_dir = directory of forum
# *files = filename list in forum
#
# Output:
# Unlinks (deletes) messages and attachments in the
# forum directory based on age or sequence number
# of the post.
#
############################################################
sub PruneOldMessages {
local($forum_dir, *files) = @_;
local($x);
local($prunefile, $attachfile, $attachfile2);
#
# We prune on the basis of
#
# AGE IN DAYS:
# $prune_how_many_days
#
# AGE BY SEQUENCE NUMBER
# $prune_how_many_sequences
#
for ($x = @files; $x >= 1; $x--) {
$prunefile = "$forum_dir/$files[$x - 1]";
# $attachfile is the descriptive attachment file in the
# forum directory. $attachfile2 = is the real uploaded
# attachment
$attachfile = "$forum_dir/" .
substr($files[$x - 1],0,14) .
"attach";
$attachfile2 = "$attach_dir/" .
"$forum-" .
substr($files[$x - 1],0,14) .
"bin";
# First we check the age in days
if ((-M "$prunefile" > $prune_how_many_days) &&
($prune_how_many_days > 0)) {
unlink("$prunefile");
unlink($attachfile);
unlink($attachfile2);
&RemoveElement(*files, $x - 1);
next;
}
#
# Check the sequence and delete if it is too old
#
if (($x <= (@files - $prune_how_many_sequences))
&& ($prune_how_many_sequences != 0)) {
unlink("$prunefile");
unlink($attachfile);
unlink($attachfile2);
&RemoveElement(*files, $x - 1);
next;
}
} # End of for all files
} # End of PruneOldMessages
############################################################
#
# subroutine: HiddenFields
# Usage:
# &HiddenFields;
#
# Parameters:
# None.
#
# Output:
# Returns a buffer containing the HTML code for
# hidden fields that should be passed from screen to
# screen in the BBS Forum.
#
############################################################
sub HiddenFields {
local ($buf);
local ($h);
$h = "<INPUT TYPE=HIDDEN NAME";
$buf = qq!$h=session VALUE="$session">\n!;
if ($first_date ne "") {
$buf .=
qq!$h=first_date VALUE="$first_date">\n!;
}
if ($last_date ne "") {
$buf .=
qq!$h=last_date VALUE="$last_date">\n!;
}
if ($first_days_old ne "") {
$buf .=
qq!$h=first_days_old
VALUE="$first_days_old">\n!;
}
if ($last_days_old ne "") {
$buf .=
qq!$h=last_days_old
VALUE="$last_days_old">\n!;
}
if ($keywords ne "") {
$buf .=
qq!$h=keywords VALUE="$keywords">\n!;
}
if ($exact_match ne "") {
$buf .=
qq!$h=exact_match VALUE="$exact_match">\n!;
}
if ($use_last_read = "on") {
$buf .=
qq!$h=use_last_read VALUE="$use_last_read">\n!;
}
if ($last_read ne "") {
$buf .=
qq!$h=last_read VALUE="$last_read">\n!;
}
if ($setup_file ne "") {
$buf .=
qq!$h=setup VALUE="$setup_file">\n!;
}
$buf;
} # End of Hidden Fields
############################################################
#
# subroutine: ReadMessageFields
# Usage:
# &ReadMessageFields;
#
# Parameters:
# None.
#
# Output:
# Returns a buffer containing the URL code for
# fields that should be passed from screen to screen
# in the BBS program
#
############################################################
sub ReadMessageFields {
local ($buf);
local ($h);
$buf = qq!session=$session&!;
if ($first_date ne "") {
$buf .=
qq!first_date="$first_date"&!;
}
if ($last_date ne "") {
$buf .=
qq!last_date=$last_date&!;
}
if ($first_days_old ne "") {
$buf .=
qq!first_days_old=$first_days_old&!;
}
if ($last_days_old ne "") {
$buf .=
qq!$last_days_old=$last_days_old&!;
}
if ($keywords ne "") {
$buf .=
qq!keywords=$keywords&!;
}
if ($exact_match ne "") {
$buf .=
qq!exact_match=$exact_match&!;
}
if ($use_last_read = "on") {
$buf .=
qq!use_last_read=$use_last_read&!;
}
if ($last_read ne "") {
$buf .=
qq!last_read=$last_read&!;
}
if ($setup_file ne "") {
$buf .=
qq!setup=$setup_file&!;
}
# We need to filter out some illegal characters
# from the URL.
$buf =~ s/ /%20/;
$buf =~ s/\//%2F/;
chop($buf); # Get rid of last &
$buf;
} # End of ReadMessageFields