#!/usr/bin/perl # # Master Board V2 # Version 2.12-s # # Master Board version 1.0 completed January 2001 # Master Board V2 version 2.12 completed June 22, 2003 # # MasterBoard.cgi # (Master Board V2 Posts and Replies Handling) # # Author: William Bontrager # Email: william@willmaster.com # Site: http://www.willmaster.com/ # # Copyright 2001 William and Mari Bontrager. # Copyright 2002,2003 Bontrager Connection, LLC # # Before installing and/or using Master Board V2, # you must agree to the complete license agreement, # linked from http://willmaster.com/master # # Tech support: http://willmaster.com/support/cgi-bin/forum/MasterBoard.cgi # # MasterBoardManual.html has installation instructions. # #################################################### use LWP::Simple; $DataDirectory = 'MBdata'; $MBdatafile = 'MBposts'; $ArchiveDirectory = 'Archive'; $GlobalData = $DataDirectory . '/GlobalData.txt'; $EmailTemplate = $DataDirectory . '/emailtemplate.txt'; $ME = $0; $ME =~ s!.*[\\/]!!; unless(&GetGlobals) { ErrorHTML('Sorry, I can\'t find the global data file.'); } #if ($G{archive_it} eq $G{delete_it} ){&ErrorHTML ('Please choose EITHER "archive" or "delete" old files before you install this program')} &ArchiveOldThreads; &Parse; &HelpFile if $In{H}; &PostOpEntry if $In{opost}; &ReplyDisplay if $In{postlink}; &PostReEntry if $In{rpost}; &GetFirstPage; ########## ## Here are the subroutines ## #Read in the initial html page sub GetFirstPage { my $page = get $G{TemplatePosts} or &ErrorHTML("To retrieve the template for the first page —",$!,$G{TemplatePosts}); #do the search and replace stuff my $insert1= &InitialInsertOne; my $insert2= &InitialInsertTwo; my $insert3= &InitialInsertThree; my $biginsert = "$insert1 $insert2 $insert3"; $page =~ s/\[MasterBoard Here\]/$biginsert/sig; print "Content-Type: text/html\n\n"; print $page; goto BOTTOM; } #end sub GetFirstPage #looks up and displays initial (current) page insert part one sub InitialInsertOne { $insert1=< From SubjectResponses HTML return $insert1; }# end sub InitialInsertOne #looks up and displays initial (current) page insert part two sub InitialInsertTwo { my $line; my @file; open(R, "$DataDirectory\/$MBdatafile"); @file = ; chomp @file; foreach $line (reverse@file) { @pagedata = split (/\t/, $line); $insert2 .=< $pagedata[1] $pagedata[2] $pagedata[3] HTML2 } return $insert2; }# end sub InitialInsertTwo #looks up and displays initial (current) page insert part three sub InitialInsertThree { $insert3 = <
Help


Post a new message:
Name:
Email:
Notify me when my post has a reply:
Yes No
 
Subject:
Your message:
Powered by Master Board V2

HTML3 return $insert3; }# end sub InitialInsertThree # Displays desired error code sub ErrorHTML { my $s = join("\n
  • ",@_); print "Content-type: text/html\n\n"; print <Error message

    Notice:

    • $s
    HTML goto BOTTOM; } # end sub ErrorHTML # Parses input sub RB { my $s = shift; $s =~ /\&\#(\d{1,3})\;/; return $s unless chr($1) =~ /[et]/i; return '&' . substr($s,1); } # sub RB sub Parse { my $buffer; if ($ENV{REQUEST_METHOD} eq 'GET') { $buffer = $ENV{QUERY_STRING}; } else { read(STDIN,$buffer,$ENV{CONTENT_LENGTH}); } my @p = split(/&/,$buffer); foreach(@p) { $_ =~ tr/+/ /; my ($n,$v) = split(/=/,$_,2); $n =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/ge; $v =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/ges; $v =~ s/(\&\#\d{1,3}\;)/RB($1)/ges; $v =~ s/(\<.*?)(embed|object|script|applet)(.*?\>)/$1$3/gis; if($In{$n}) { $In{$n} .= "\t$v"; } else { $In{$n} = $v; } } $In{postlink} =~ s/[^\w\.]//gs; $In{linkclicked} =~ s/[^\w\.]//gs; } # end sub Parse #Add an original post. sub PostOpEntry { unless ($In{name} =~ /\w/) { &ErrorHTML('Please enter your screen name.') } if ($In{email}) { &ValidEmail($In{email}) or &ErrorHTML('Your email address is invalid. Please click the back button and correct it.') } unless ($In{subject} =~ /\w/) { &ErrorHTML('Please provide a subject line.') } unless ($In{opentry} =~ /\w/) { &ErrorHTML('Please enter your question or comment.') } if ($In{NotifyMe} eq 'yes') {unless ($In{email}) {&ErrorHTML('We need your email address in order to notify you of new posts to this thread.') } } $In{name} = &AdjustForHTMLdisplay($In{name}); $In{email} = &AdjustForHTMLdisplay($In{email}); $In{email} =~s/\@/\*/; $In{subject} = &AdjustForHTMLdisplay($In{subject}); $In{opentry} = &AdjustForHTMLdisplay($In{opentry}); my $t=time; my $file = "$DataDirectory\/$t"; &LockFile($file); open W,">$file" or &ErrorHTML("The file could not be opened.\n"); print W "$In{name}\n"; print W "$In{email}\n"; print W " Notify Me - $In{NotifyMe}\n"; print W "$In{subject}\n"; print W "$In{opentry}\n"; close W; &UnLockFile($file); my $datafile = "$DataDirectory\/$MBdatafile"; &LockFile($datafile); open W,">>$datafile"; print W join("\t",$t,$In{name},$In{subject},'0'); print W "\n"; close W; &UnLockFile($datafile); &MaintainerMailOPost($In{name},$In{email},$In{subject},$In{opentry}); &GetFirstPage; } # end sub PostOpEntry ######################## #Display posts and any replies sub ReplyDisplay { my $newpage = get $G{TemplateReplies} or &ErrorHTML("To display a reply —",$!,$G{TemplateReplies}); #do the search and replace stuff $reinsert1= &ReplyInsertOne; $reinsert2= &ReplyInsertTwo; $reinsert3= &ReplyInsertThree; $reinsert4= &ReplyInsertFour; my $biginsert = "$reinsert1 $reinsert2 $reinsert3 $reinsert4"; $newpage =~ s/\[MasterBoard Here\]/$biginsert/sig; print "Content-Type: text/html\n\n"; print $newpage; goto BOTTOM; }#end sub ReplyDisplay #prints the top of the table sub ReplyInsertOne { $reinsert1 = < From Message HTML return $reinsert1; } #END sub ReplyInsertOne #prints the initial post sub ReplyInsertTwo { my $file = "$DataDirectory\/$In{postlink}"; open(R, "$file")or &ErrorHTML ("To find a reply —",$!,$file); my $message; $name=; $email= ; $notifyme = ; $subject = ; $flag = 0; while () { if (index ($_, "\t") == 0) { $flag = 1; last} { $message .= $_; } } return < $name Subject: $subject

    $message HTML2 } #end sub ReplyInsertTwo #prints responses if any sub ReplyInsertThree { my $message; if ($flag == 0) { $reinsert3 = ''; return} { while () { $name=$_; $email= ; $notifyme = ; $subject .= ; $message = ''; while () { if (index ($_, "\t")==0) { $flag = 1; last} else { $message .= $_; } } $subject =~ s/\n*//; $reinsert3 .= <<3HTML; $name In response to: $subject

    $message 3HTML } } return $reinsert3; } #end sub ReplyInsertThree #prints rest of page sub ReplyInsertFour { return <
    -Back to forum-

    Help


    Reply to this thread:
    Name:
    Email:
    Notify me when this thread has another reply:
    Yes No
    Your message:
    Powered by Master Board V2

    HTML4 } #end sub ReplyInsertFour sub ValidEmail { return 0 if $_[0] =~ /(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/; return 0 if $_[0] !~ /^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,}|[0-9])(\]?)$/; return 1; } # end sub ValidEmail sub AdjustForHTMLdisplay { $s = shift; $s =~s/\r//g; $s =~ s/\&/\&\;/g; $s =~ s/\"/\"\;/g; $s =~ s/\/\>\;/g; $s =~ s/\n\n+/

    /g; $s =~ s/\n/
    /g; return $s; } # end sub AdjustForHTMLdisplay #Add REPLY to an original post. sub PostReEntry { unless ($In{rname} =~ /\w/) { &ErrorHTML('Please enter your screen name.') } if ($In{remail}) { &ValidEmail($In{remail}) or &ErrorHTML('Your email address is invalid. Please click the back button and correct it.') } unless ($In{rentry} =~ /\w/) { &ErrorHTML('Please enter your reply to the original post.') } if ($In{NotifyMe} eq 'yes') {unless ($In{remail}) {&ErrorHTML('We need your email address in order to notify you of new posts to this thread.') } } $In{rname} = &AdjustForHTMLdisplay($In{rname}); $In{remail} = &AdjustForHTMLdisplay($In{remail}); $In{email} =~s/\@/\*/; $In{rentry} = &AdjustForHTMLdisplay($In{rentry}); &NotifyMe; my $t= time; my $file = "$DataDirectory\/$In{linkclicked}"; &LockFile($file); open A,">>$file" or &ErrorHTML("The file $In{linkclicked}could not be opened to append at $t.\n"); print A "\t$t\n"; print A "$In{rname}\n"; print A "$In{remail}\n"; print A " Notify Me - $In{NotifyMe}\n"; print A "\n"; print A "$In{rentry}\n"; close A; &UnLockFile($file); open R,"$DataDirectory\/$MBdatafile" or &ErrorHTML("The file $MBdatafile could not be opened to read.\n"); my @F = ; close R; my $s; for $s (@F) { my @line = split(/\t/,$s); if($line[0] eq $In{linkclicked}) { chomp $line[3]; $line[3]++; $s = join("\t",@line); $s .= "\n"; last; } } my $datafile ="$DataDirectory\/$MBdatafile"; &LockFile($datafile); open W,">$datafile" or &ErrorHTML("The file $MBdatafile could not be opened to rewrite.\n"); for(@F) { print W $_; } close W; &UnLockFile($datafile); &MaintainerMailRePost($In{rname}, $In{remail}, $subject, $In{rentry}); &GetFirstPage; } # end sub PostReEntry sub HelpFile { if ($In{H} eq 'help') {print "Content-Type: text/html\n\n"; print <Help File

    Hints for using Master Board V2

    The opening page of the bulletin board lists the subject of each post, who it is from and the number of responses the post has received. To see the complete message and/or any responses, click on the subject line.


    To post a new question or observation on the Board, fill out the form titled "Post a new message"- (below the board on the initial page).

    • A name is required. You may use a screen name if you wish.

    • Email address is not required unless you wish to be notified of any responses to your post.

    • A subject is required.

    • Type your message in the message box and click the "Post" button.

    To contribute a response to any post, click on the subject line, if you haven't done so already, and you will be taken to a page containing the complete original post plus any responses already posted. Fill out the form below the board titled "Reply to this thread".

    • A name is required. You may use a screen name if you wish.

    • Email address is not required unless you wish to be notified of any other responses to the thread.

    • Type your response in the message box and click the "Post Response" button. HTML }; goto BOTTOM; } #end sub HelpFile sub NotifyMe { open (R, "$DataDirectory\/$In{linkclicked}") or ErrroHTML("To find link clicked —",$!,"$DataDirectory\/$In{linkclicked}"); my @File ; while () { push (@File, $_); my $line = ; push (@File, $line); $line = ; push (@File, $line); $subject .= ; while () { if (index ($_, "\t")==0) {last} } chomp @File; if ($File[2] eq " Notify Me - yes") { &Mail($File[0], $File[1], $subject) } @File = (); } }# end sub NotifyMe #do the send mail bit sub Mail { $G{MailPrograml} .= ' -t' if $G{MailPrograml} =~ /sendmail\Z/; chomp @_; while (@_) { my $name = shift(@_); my $email = shift(@_); my $subject = shift(@_); $subject =~ s/\n*//gs; $email =~s/\*/\@/; if ($SentMail{$email}) {last} open (MESSAGE, $EmailTemplate) or ErrorHTML("To read email template —",$!,$EmailTemplate); my @message = ; close (MESSAGE); my $message = join ("", @message); $message =~ s/\[name\]/$name/gs; $message =~ s/\[URL\]/$G{URL}/gs; $message =~ s/\[subject\]/$subject/gs; $message =~ s/\[forumname\]/$G{forum_name} /gs; open MAIL,"|$G{MailProgram}"; print MAIL < 0; unless (&TimeToArchive) {return} opendir(READIN,$DataDirectory); @allfiles = readdir(READIN); closedir(READIN); for $file (@allfiles) { if($file =~ /^\D/){next}; if(-M "$DataDirectory\/$file" >= $G{daystobump}) { if ($G{archive_it} eq 'yes') # archive the file { open (R, "$DataDirectory\/$file"); open (W,">$ArchiveDirectory\/a$file"); print W ; close (R); close (W) } unlink "$DataDirectory\/$file"; } elsif (-M $file < $G{daystobump}) { push (@timelydata, $file); } } #EDIT THE FLAT FILE my $datafile = "$DataDirectory\/$MBdatafile"; &LockFile($datafile); rename ($datafile, "$datafile\.tmp"); open (R, "$datafile\.tmp"); open (W, ">$datafile"); my $line; while ($line = ) { for(@timelydata) { if(index($line,$_) == 0) { print W $line; } } } close (R); close(W); &UnLockFile($datafile); }#end sub ArchiveOldThreads sub TimeToArchive { ($Second, $Minute, $Hour, $DayofMonth, $Month, $Year, $WeekDay, $DayofYear, $IsDST) = localtime(time); open (R,"<${DataDirectory}/archive_flag"); $flag = ; close R; if ($flag eq $DayofYear){return 0} elsif ($flag ne $DayofYear) { &LockFile("${DataDirectory}/archive_flag"); open (W, ">${DataDirectory}/archive_flag"); print W "$DayofYear"; close (W); &UnLockFile("${DataDirectory}/archive_flag"); return 1; } } sub LockFile { my $f = "$_[0]\.lock"; my $tm = time; while((time - $tm) < 12) { last unless -e "$f"; sleep 2; } open(LOCKFILE,">$f"); close(LOCKFILE); } # end sub LockFile sub UnLockFile { unlink "$_[0]\.lock"; } sub MaintainerMailOPost { $G{MailPrograml} .= ' -t' if $G{MailPrograml} =~ /sendmail\Z/; chomp @_; my $name = shift(@_); my $email = shift(@_); my $subject = shift(@_); my $message =shift(@_); $subject =~ s/\n*//gs; $email =~s/\*/\@/; my $thisemail; if ($email){$thisemail = $email} else {$thisemail = $G{webmaster_email}} open MAIL,"|$G{MailProgram}"; print MAIL <) { chomp; my($k,$v) = split /\t/,$_,2; $G{$k} = $v; } close R; open R,$EmailTemplate; $E = join '',; close R; return 0 unless $G{TemplatePosts} =~ /\w/; return 1; } # sub GetGlobals BOTTOM: