#!/usr/bin/perl ################################################################### # SCRIPT PARAMETERS (CHANGE HERE). ################################################################### ### URL path where this script resides (+gifies for smilies). ### (can also be a relative url) $SCRIPTDIR="/board"; ### Where are the datafiles stored in ? $DATADIR="./data"; ### URL path where gif's are stored. $GIFDIR="/board"; ### background color of table headers $BGCOLORTBLHEAD="33CCFF"; ### title of all boards page $ALLBOARDS="Michael's Message Board"; ### style of fonts (is put into body tag of all generated files. $FONTSTYLE= "style='font-family:verdana,helvetica,ariel;font-size:11pt'"; ### How many subjects are listed in one page $SUBJECTSPAGESIZE=20; ### encoding meta tag $ENCODING=""; ################################################################### ### HTTP Header string for HTML result $HTTPHEADER = "Content-type: text/html\n\n"; $STARTTIME=time; ### read POST parameters into global $CgiParam{$name} &parse_form; $BOARDID = $CgiParam{"id"}; $THREADID = $CgiParam{"tid"}; $STYLE = $CgiParam{"style"}; $DO = $CgiParam{"do"}; $BOARDTITLE = "KuKu";###$CgiParam{"title"}; ### show one message board if ($DO eq "brd"){ ($STYLE == 1) ? &Subjects : &TheBoard; } ### listing of discussions for one message board. elsif ($DO eq "subj"){ &Subjects; } ### Show one thread elsif ($DO eq "thrd"){ &Thread; } ### returns static html (if in Frames mode) ### trade off speed for ease of setup elsif ($DO eq "nothread"){ &NoThread; } ### returns HTML with a entry form for new message elsif ($DO eq "addmsgform"){ &AddMsgForm; &TimeComment; } ### add a reply for one message board elsif ($DO eq "addmsg"){ &AddMsg($DATADIR,$BOARDID,$THREADID,$CgiParam{'message'},$CgiParam{'subj'},$CgiParam{'mail'},$CgiParam{'auth'},$CgiParam{'smile'},$CgiParam{'msg'}); } ### Display form for 'search messages' elsif ($DO eq "searchform"){ &ShowSearchForm; &TimeComment; } ### perform search of messages elsif ($DO eq "dosearch"){ &DoSearch; } ### no parameters - show listof message boards. else { &BoardList; } ### read POST parameters into global $CgiParam{$name} sub parse_form { local($name,$value,$meth,$in,$len,$got,@pairs,$pair); $meth = $ENV{'REQUEST_METHOD'}; # Get the request data if (!defined $meth || $meth eq '' || $meth eq 'GET' || $meth eq 'HEAD') { $in = $ENV{'QUERY_STRING'}; } elsif ($meth eq 'POST') { $len = $ENV{'CONTENT_LENGTH'}; $got = read(STDIN, $in, $len); ($got==$len) || die "$HTTPHEADER Can't read POST data $got $len\n"; } else { die "$HTTPHEADER Unknown request method: $meth\n"; } # Split the name-value pairs @pairs = split(/&/, $in); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); # Un-Webify plus signs and %-encoding $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; # Remove any NULL characters, Server Side Includes $value =~ s/\0//g; $value =~ s///g; $CgiParam{$name} = $value; } } ### Show subject list of a board. sub Subjects { local($pos,$cnt,$line,@lines,$offset,$prevlink); $filename="$DATADIR/board_$BOARDID.data"; if (open(BOARD,"$filename")) { flock(BOARD,1); ## shared read lock $offset=$CgiParam{"offs"}; $cnt=$SUBJECTSPAGESIZE; if ($offset>0){ $pos=$offset-$SUBJECTSPAGESIZE; $pos<0 ? $pos=0 : 1; $prevlink=" << "; } $BOARDTITLE=; chop($BOARDTITLE); $pos=0; while() { if ($pos>=$offset) { if ($cnt>0) { push @lines, $_; $cnt--; } else { $pos = $offset+$SUBJECTSPAGESIZE; $nextlink=" >> "; break; } } $pos++; } close(BOARD); } $dirs = "$prevlink$nextlink"; if ($dirs ne "") { $dirs = "[$dirs] "; } ###page + table header print <$ENCODING$BOARDTITLE
$BOARDTITLE $dirs [ All Boards]  [ Search this Board]  [ Start a new Discussion ]
ENDOFTEXT foreach $line (@lines) { ($tid, $pic, $nmsg, $date, $author, $subject) = split(/##/, $line); print < ENDOFTEXT } ####page footer print "
 Subject of the Discussion ByTimeMessagesID
$subject $author$date($nmsg)$tid
"; &TimeComment; } ### Show contents of one discussion thread sub Thread { print "$HTTPHEADER"; $threadfile = "$DATADIR/thread_$CgiParam{'id'}_$THREADID.htm"; open(THREAD,$threadfile) || die "

No messages for this thread

"; flock(THREAD,1); ## shared read lock while() { print $_; } close(THREAD); &TimeComment; } ### Show one message board (with frames) sub TheBoard { print <$ALLBOARDS <a href="$SCRIPTDIR/board.pl?do=subj&id=$BOARDID">For a page without frames</a> <br>Sorry, this page works with frame enabled browsers only. ENDOFTEXT } ### no thread sub NoThread { print <$ENCODING

Please chose a forum

... by clicking on the subject line of a discussion. ENDOFTEXT } ### list of message boards sub BoardList { print <$ENCODING$ALLBOARDS


$ALLBOARDS



ENDOFTEXT if (open(BOARD,"$DATADIR/allboards.data")) { flock(BOARD,1); ## shared read lock while() { chop($_); ($tid, $subject, $comment, $nummsg, $date_time) = split(/##/, $_); #$save_sbj = $subject; #$save_sbj =~ s/ /%20/g; print < ENDOFTEXT } close(BOARD); } print "
[ Search All Messages]
Subject Comments Last message Messages
$subject$comment$date_time($nummsg)
"; &TimeComment; } ### writes a HTML Form for entering a new message. sub AddMsgForm { $title=$CgiParam{"title"}; if ($title ne "" && index(lc($title),"re:")!=0) { $title="Re: ".$title; } print <
Subject
Author
e-mail (Optional)
Message





ENDOFTEXT } ### Add message to the system ############################################ # # $_[0] - data directory # $_[1] - board id # $_[2] - argument thread id (if message added to existing thread) # # $_[3] - message # $_[4] - subject # $_[5] - mail address # $_[6] - Author # $_[7] - smiley # $_[8] - message id # ######################################################################### sub AddMsg { local($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst,$script); ### form a date string ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $datestr = sprintf("%02d/%02d/%02d %02d:%02d %s",$mday,($mon+1),($year>=100?$year-100:$year),$hour%12,$min,$isdst?"AM":"PM"); ### add message to thread file &AddToThreadFile($_[0],$_[1],$_[2],$_[3],$_[4],$_[5],$_[6],$_[7],$_[8],$datestr); ### add message count to list-of-boards file &AddToBoardList($_[0],$_[1],$datestr,1); ### ok message $script=$STYLE==0 ? "onload=\"top.subj.window.location='$SCRIPTDIR/board.pl?do=subj&id=$_[1]';\"" : ""; print <

your message has been added to the board

Thank you for your comments. ENDOFTEXT } ### add message to existing thread file # # $_[0] - data directory # $_[1] - board id # $_[2] - argument thread id (if message added to existing thread) # # $_[3] - message # $_[4] - subject # $_[5] - mail address # $_[6] - Author # $_[7] - smiley # $_[8] - message id # # $_[9] - date string # ### sub AddToThreadFile { local(@threadlines,$threadfile,$line,$previndent,$width,$followup); local($body,$subj,$mail,$author,$TID,$NEWMSGNUM,$urltitle); ### prepare form parameters (values of the new message). $body = $_[3]; &CheckTextParam($body); if ($_[4]) { $subj = $_[4]; $subj =~ s/\&/\&\;/g; $subj =~ s/"/\"\;/g; &CheckTextParam($subj); } if ($subj eq "") { $subj = "NoSubject"; } ### check if email address looks valid $mail = ($_[5] =~ /.*\@.*\..*/) ? $_[5] : ""; &CheckTextParam($mail); ### author line (make link if email is present) $author = $mail eq "" ? $_[6] : "$_[6]"; &CheckTextParam($author); ### create a new thread id (if a new thread is opened) $TID = ($_[2]!=0) ? $_[2] : get_number("$DATADIR/board_$_[1].num"); ### get new unique message number for this thread $threadfile = "$_[0]/thread_$_[1]_$TID"; $NEWMSGNUM=get_number("$threadfile.num"); ### if new message - create thread file. if ($_[8]==0) { open(THREAD,">$threadfile.htm") || die "$HTTPHEADER Can't open file $threadfile for writing"; print THREAD "$ENCODING$_[4]\n"; print THREAD "\n\n"; close(THREAD); } CreateIfNotThere("$threadfile.htm"); open(THREAD,"+<$threadfile.htm") || die "$HTTPHEADER Can't open file $threadfile"; flock(THREAD,2); ## exclusive write lock @threadlines = ; seek(THREAD,0,0); foreach $line (@threadlines) { print THREAD "$line"; if ($line =~ /\/ && $1==$_[8]) { $width=$2*5; $width=45 unless $width<45; $followup=$2+1; ### title to appear in reply form. ### make a safe string $urltitle = $subj; $urltitle =~ s/([^\w])/'%'.unpack('H',$&).unpack('h',$&)/eg; print THREAD <
 $subj
By: $author On: $_[9] (#$NEWMSGNUM)
[Reply]
$body
ENDOFTEXT } } close(THREAD); ### modify subject listing (new thread-insert entry, known thread-update date) &AddToSubjects($_[0],$_[1],$TID,$_[3],$subj,$mail,$_[6],$_[7],$_[9]); } ### add entry to subject file (keep the subject file sorted by date). # # $_[0] - data directory # $_[1] - board id # $_[2] - argument thread id (if message added to existing thread) # # $_[3] - message # $_[4] - subject # $_[5] - mail address # $_[6] - Author # $_[7] - smiley # # $_[8] - date string # # ### sub AddToSubjects { local(@boardlines,$filename,$line,$newline,$pos,$num,$pic,$nmsg,$date,$author,$subject); local($BOARDTITLE,$TID); $filename="$DATADIR/board_$BOARDID"; CreateIfNotThere("$filename.data"); open(BOARD,"+<$filename.data") || die "Can't open file $filename.data"; flock(BOARD,2); ## exclusive write lock $BOARDTITLE=; @boardlines=; ### new thread created if ($THREADID==0) { $newline=join("##",($_[2], $_[7], 1, $_[8], $_[6], $_[4])); } ### update existing thread else { $pos=0; foreach $line (@boardlines) { ($TID) = split(/##/,$line); if ($TID == $_[2]) { ($TID, $pic, $nmsg, $date, $author, $subject) = split(/##/, $line); $newline=join("##",$TID, $pic, $nmsg+1, $_[8], $author, $subject); chop($newline); splice(@boardlines,$pos,1); break; } ++$pos; } } ### write changes back. seek(BOARD,0,0); print BOARD $BOARDTITLE; chomp($newline); print BOARD $newline; $num = @boardlines; if ($num != 0) { print BOARD "\n"; } foreach $line (@boardlines) { print BOARD $line; } close(BOARD); } ### Update count of messages and date of last message # # $_[0] - data directory # $_[1] - board id # # $_[2] - date string # # $_[3] - increment. # ### sub AddToBoardList { local(@boardlines,$filename,$line,$tid, $subject, $comment, $nummsg ,$date_time); $filename="$_[0]/allboards.data"; CreateIfNotThere("$filename"); open(BOARD,"+<$filename") || die "Can't open file $filename"; flock(BOARD,2); ## exclusive write lock @boardlines=; seek(BOARD,0,0); ### write changes back. foreach $line (@boardlines) { if (!($line=="\n" || $line=="")) { chop($line); ($tid, $subject, $comment, $nummsg, $date_time) = split(/##/, $line); if ($BOARDID == $tid) { $nummsg += $_[3]; $date_time=$_[2]; ### if ($_[2] ne ""); } print BOARD "$tid##$subject##$comment##$nummsg##$date_time\n"; } } truncate(BOARD,tell(BOARD)); close(BOARD); } ### # Checks text parameters for undesired input. ### sub CheckTextParam { $_[0] =~ s/^\s+//; #strip newlines (from start and end) $_[0] =~ s/\s+$//; $_[0] =~ s/]+>//gi; #strip table tags (they could upset the text. $_[0] =~ s-]+>--gi; # $_[0] =~ s//>/g; $_[0] =~ s/\n\n/

/g; #new lines are translated to
tags. $_[0] =~ s/\n/
/g; } ### get a unique number key. sub get_number { local($num); CreateIfNotThere($_[0]); open(NUMBER,"+<$_[0]") || die "$HTTPHEADER Can't open file $_[0]"; flock(NUMBER,2); ## exclusive write lock. $num = ; if ($num == 999999 || $num !~ /^\d+$/) { $num = "1"; } else { $num++; } seek(NUMBER,0,0); print NUMBER "$num"; close(NUMBER); $num; } ### creates a file if it does not exist. sub CreateIfNotThere { if (!open(CHECK,"$_[0]")) { open(CHECK,">$_[0]") || die "$HTTPHEADER Can't create $_[0]"; } close(CHECK); } ############################################################################## ### Show subject list of a board. ############################################################################## sub ShowSearchForm { print <$ENCODINGSearch for messages

Search for messages



Find resultswith all of the words
 
 with the exact phrase
 
 with at least one of the words    



  Search for messages in: Matching case
 
  
ENDOFTEXT } ############################################################################## ### perform search ############################################################################## sub DoSearch { local ($board,@filez,$first); print $HTTPHEADER; $board=$CgiParam{"board"}; if ($board eq "0") { @filez = <$DATADIR/thread\_?\_?.htm>; } else { @filez = <$DATADIR/thread\_$board\_?.htm>; } @AllWorlds = split(/\s+/, $CgiParam{"term1"} ); @OneOfWords = split(/\s+/, $CgiParam{"term3"} ); $Phrase = $CgiParam{"term2"}; $Case = $CgiParam{"case"}; $first = 0; if (0 == scalar @AllWorlds && 0 == scalar @OneOfWords && $Phrase eq "") { print "

Please enter something to search for

"; return; } foreach $ln (@filez) { $header = doSearch($ln,@allwords,$phrase,@oneofword); if ($header ne "") { if ($first==0) { $first=1; print <$ENCODINGSearch results

Search results

Subject of message
ENDOFTEXT } print "$header
"; } } print "

Nothing found

" if ($first==0); &TimeComment; } ############################################################################## ### search one file. ############################################################################## sub doSearch { local ($found,$text,$size); open(FILE,$_[0]); flock(BOARD,1); ## shared read lock $size = (stat(FILE))[7]; read(FILE, $text, $size); close(FILE); #-----------------------------------------------------# if (0 != scalar @AllWorlds) { foreach $term (@AllWorlds) { if ($Case ne "on") { return "" if ($text !~ /$term/i); } else { return "" if ($text !~ /$term/); } } } #-----------------------------------------------------# if (0 != scalar @OneOfWords) { $found=0; foreach $term (@OneOfWords) { if ($Case ne "on") { if ($text =~ /$term/i) { $found=1; break; } } else { if ($text =~ /$term/) { $found=1; break; } } } return "" if ($found==0); } #-----------------------------------------------------# if ($Phrase ne "") { if ($Case ne "on") { $text = lc($text); $Phrase = lc($Phrase); } return "" if (index($text,$Phrase)==-1); } #-----------------------------------------------------# # if we got here - then the file is a match # find the title of the message and return it # # The title of this discussion is the first thing in bold. #-----------------------------------------------------# $pos=index($text,""); $pos1=index($text,"",$pos+1); $pos2=index($text,"",$pos1+1); $pos1 = ($pos2 != -1) ? $pos2 : $pos1; $pos1=$pos+15 if ($pos1==-1 || ($pos1-$pos) > 80); return substr($text,$pos+3,$pos1-$pos-3); } ### sub TimeComment { print ""; }