#!/usr/bin/perl
use CGI qw/:standard/;
use CGI::Carp(fatalsToBrowser);
$cgi = new CGI;
for($cgi->param()) { $F{$_} = $cgi->param($_); }
my ($html); # holds html template
# bootcha out if'n ya ain't lookin for no raffle
if(param('forum') ne 'paragraph') { print "Location:http://www.nationalgeographic.com/ngforkids/\n\n"; }
print header;
# get url and script name
my $url = url();
my $script_name = script_name();
# read params
my $forum = param('forum'); # forum name
my $op = param('op'); # operation
my $start |= param('start'); # starting message
# these a'bee defin-ed here so's ya don't gotta type 'em out so many gauldurn times
# but can, instead, loop over them as such: for(@fields) { print "$_
\n"; }
# or wateva joo wana do wif dem
@fields = ('name', 'lastinitial', 'grade', 'email', 'essaytext');
# make 'post' el action-o default-o
$op='post' if not $op;
# where's the template that has the form in it?! where is it?! huh?!!!1
my $post_template = 'post.html';
# oh.
# read common config file
require 'common.conf';
# gimmie dat forum config jonx
# if'n it's 'round these hear parts!
if(-e "$forum/$forum.conf") { require "$forum/$forum.conf"; }
# noconffileforyougoaway!
else { &no_forum;exit; }
my $mail_program = "/usr/lib/sendmail -i -t";
# max msg per page
$max = 10;
# messages directory for this forum
my $message_dir = "$forum/entries";
if($op eq 'post'){
# are all required fields are filled in?
if(all_required()) { # yes: create entry file on server, print 'thanks' page
&create_message;
$template = 'thanks2.html';
$html = &slurp($template);
} else { # no: pout, sulk, and return user to entry form
$template = "$forum/$post_template";
$html = &slurp($template);
$html = &post_page($html);
}
} elsif($op eq 'edit'){
my $username = param('username');
my $password = param('password');
if(&authenticate($username,$password)){
if($message = param('message')){
if(param('action') eq 'Edit'){
$html = &slurp("$forum/edit.html");
$html = &message_edit_page($html,$message,$username,$password);
} elsif(param('action') eq 'Delete'){
&delete_message($message);
} elsif(param('action') =~ /^Update/){
if(param('action') =~ /Live/) { &update_message($message,1); }
else { &update_message($message,0); }
} elsif(param('action') eq 'Unpost'){
&unpost_message($message);
}
}
if(param('action') ne 'Edit') {
$html = &slurp("$forum/edit_list.html");
$html = &edit_page($html,$username,$password);
}
} else { $html = &slurp("$forum/password.html"); }
}
$html =~ s//$script_name/g;
$html =~ s//$forum/g;
print $html;
#### SUBROUTINES ####
# returns contents of file $filename
sub slurp{
my $filename = shift;
local $/;
open FH, "< $filename";
my $text = ;
close FH;
return $text;
}
# read in and print out post template
# used to insert timestamp in served page
# timestamp is now set to time server recieves form (in &create_message)
# so this sub does basically nothing...
# (since and aren't in the post template)
sub post_page {
my ($html) = @_;
# get current time and date
for(@fields) { $$_ = param($_); $html =~ s/<$_>/$$_/g; }
if($fields_missing) {
$html =~ s///g if $fields_missing;
$html =~ s/<\/tr error\-\->/<\/tr>/g if $fields_missing;
}
if($t_grade = param('t_grade')) { $html =~ s/$t_grade t_grade/selected/ge; }
if($t_subject = param('t_subject')) { $html =~ s/$t_subject t_subject/selected/ge; }
if($schoolstate = param('schoolstate')) { $html =~ s/$schoolstate schoolstate/selected/ge; }
$post_date_time = &get_date_time;
$format_date_time = &format_date_time($post_date_time);
$html =~ s//$post_date_time/g;
$html =~ s//$format_date_time/g;
return $html;
}
# prints list of messages, filtered based on user input (ALL, UM, UP, LIVE)
sub edit_page {
my ($html,$username,$password) = @_;
my $message_loop;
# make sure values required to keep state are present in all forms
$html =~ s//$username/g;
$html =~ s//$password/g;
$html =~ s//$script_name/g;
$html =~ s//$start/;
$html =~ s//$forum/g;
$html =~ m@(.*)@s;
my $loop_template = $1;
$edit_mode |= param('edit_mode');
$html =~ s//$edit_mode/g;
print <
Edit Page
JS_HACK
# edit modes: ALL, UM, UP, LIVE
# filtering
# @msg = `ls $message_dir/*.msg`;
if($edit_mode eq 'UM') {
@files = `ls $message_dir/UM*.msg`;
} elsif($edit_mode eq 'UP') {
@files = `ls $message_dir/UP*.msg`;
} elsif($edit_mode eq 'LIVE') {
@files = `ls $message_dir/*.msg | grep -v U`;
} else {
@files = `ls $message_dir/*.msg`;
}
foreach(@files) {
chomp($_);
s/$message_dir\///eg;
}
# custom sort alg. so unmoderated message numbers don't get
# sorted down to the end and re-used, then overwritten
@files = reverse sort fn_cmp @files;
# loop over correct set of message filenames
if(param('start')) { $q = param('start'); }
else { $q = 0; }
for($q;$q<($start+$max);$q++) {
last if($q>$#files);
&get_message_data("$message_dir/$files[$q]");
my ($message_id,$ext) = split /\./,$files[$q];
if($message_id =~ /^[A-Z]/) { $message_id = substr($message_id,0,8); }
else { $message_id = substr($message_id,0,6); }
my $tmp = $loop_template;
my @l_fields = ('status','name', 'lastinitial', 'grade', 'email', 'essaytext');
$tmp =~ s//$files[$q]/g;
if($files[$q] =~ /^[A-Z]/) { $status = "NOT Live"; }
else { $status = "Live"; }
for(@l_fields) { $tmp =~ s/<$_>/$$_/ge; };
$tmp =~ s//$message_id/g;
$tmp =~ s/\]\-\->/
teaches grade \[$t_grade\]<\/b>/g if $t_grade;
$tmp =~ s/\]\-\->/
teaches subject \[$t_subject\]<\/b>/g if $t_subject;
$tmp =~ s/\]\-\->/
email \[$t_email\] \(Okay to contact\)<\/b>/g if $t_email and $wantupdates ne 'no';
$message_loop .= $tmp;
}
$html =~ s@(.*)@$message_loop@s;
# deal with navigation
$start = param('start'); $prev = $start - $max; $next = $start + $max;
if ($prev < 0){ $html =~ s/.*/ /s; }
else { $html =~ s//$prev/; }
if ($next >= $#files){ $html =~ s/.*/ /s; }
else { $html =~ s//$next/; }
return $html;
}
# prints info for message $message.msg
sub message_edit_page {
my ($html,$message,$username,$password) = @_;
if($message =~ /^UM/) { $msg_status = 'UnModerated (NOT Live)'; }
elsif($message =~ /^UP/) { $msg_status = 'UnPosted (NOT Live)'; }
elsif($message =~ /^[^A-Z]*/) { $msg_status = 'Live Message'; }
$html =~ s//$username/g;
$html =~ s//$password/g;
$html =~ s//$script_name/g;
$html =~ s//$forum/g;
$html =~ s//$start/;
$html =~ s//$message/g;
$html =~ s//$msg_status<\/h3>/g;
&get_message_data("$message_dir/$message.msg");
my @l_fields = ('name', 'lastinitial', 'grade', 'email', 'essaytext');
for(@l_fields) { $html =~ s/<$_>/$$_/ge; }
$html =~ s//$message/g;
$html =~ s//$message_date_time/g;
$html =~ s//$fname $lname/g;
return $html;
}
# load values for message $filename into appropriate global vars
sub get_message_data {
local($filename) = @_;
open (MESSAGEFILE, "$filename") || die "Could not open $filename\n: $!";
# set all globals for access by calling function
for(@fields) { $$_ = '';chomp($$_ = ); }
$message_date_time = ;
close(MESSAGEFILE);
}
# return formatted date and, uh, time
# given $date_time in format returned from &get_date_time
sub format_date_time {
my ($date_time) = @_;
my (@long_month) = ("Bad month", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
my ($year, $mon, $mday, $hour, $min, $sec) = split(/:/, $date_time);
my $date = "$long_month[$mon] $mday, $year";
my $ampm = "AM";
$ampm = "PM" if ($hour > 11);
if ($hour > 12) {$hour -= 12}
else {$hour =~ s/^0//g;}
my $time = "$hour:$min $ampm";
$dt = "$date $time";
return $dt;
}
# what time is it?
sub get_date_time {
my ($sec, $min, $hour, $mday, $mon);
my ($year, $wday, $yday, $isdst);
my ($ampm, $currentdatetime, $dateTime);
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
$year = 1900 + $year;
$mon++;
if ($min < 10) { $min = "0" . $min; }
if ($sec < 10) { $sec = "0" . $sec; }
$dateTime = "$year:$mon:$mday:$hour:$min:$sec";
return $dateTime;
}
# return 1 for valid or 0 for invalid login
sub authenticate{
my ($username,$password) = @_;
my $mod_flag = 0;
my $fb_flag = 0;
my $flag = 0;
foreach (@moderator_email){ $mod_flag = 1 if $_ eq $username; }
foreach (@feedback_email){ $fb_flag = 1 if $_ eq $username; }
$flag = 1 if ($mod_flag || $fb_flag) && $password eq $moderator_password;
return $flag;
}
# make a new message
sub create_message {
my $msg = '';
# $whatever = &taint_check(param('whatever'));
for(@fields) { &taint_check(param($_)); }
# build $msg, which is what gets fed directly to the flat file storing this info
for(@fields) { $msg .= param($_)."\n"; }
$message_date_time = format_date_time(get_date_time());
$msg .= "$message_date_time\n";
@files = `ls $message_dir/*.msg`;
foreach(@files) { chomp;s/$message_dir\///e; }
foreach(@files) {
s/^[A-Z]*//;
}
@files = sort @files;
# make new filename
$highNumber = substr($files[@files - 1],0,6);
$highNumber++;
$highNumber = sprintf("%6d",$highNumber);
$highNumber =~ tr/ /0/;
$highNumber = "000001" if ($highNumber eq "000000");
$messageName = "$highNumber" . ".msg";
if($email_moderator eq 'on') { } else { $messageName = 'UM'.$messageName; }
open(WRITEMSG, ">$message_dir/$messageName") || die("Could't open $messageName for writing");
print WRITEMSG $msg;
close (WRITEMSG);
if ($email_moderator eq 'on'){
my $from = ' ';
my $to = join ',',@moderator_email;
my $subject = qq(New forum message);
my $message = qq($msg\n);
$message .= qq(To edit message click below and enter your email and password:\n);
$message .= qq($url?forum=$forum&op=edit);
&send_mail($from, $to, $subject, $message);
}
}
# update changes to message $message.msg
sub update_message {
$message = shift;
my $put_live = shift;
$message_file = "$message_dir/$message.msg";
if($put_live && $message =~ /^[A-Z]+/) {
unlink $message_file || die "Couldn't delete $message: $!\n";
$message =~ s/^[A-Z]+//;
$message_file = "$message_dir/$message.msg";
}
my @l_fields = ('message_date_time','name', 'lastinitial', 'grade', 'email', 'essaytext');
for(@l_fields) { $$_ = param($_); $$_ =~ s/\r|\n//g; }
($fname,$lname) = split ' ',$name;
# build $msg, which is what gets fed directly to the flat file storing this info
$msg = "$fname\n$lname\n";
for(@fields) { $msg .= param($_)."\n" unless $_ eq 'fname' or $_ eq 'lname'; }
$msg .= "$message_date_time\n";
open(WRITEMSG, ">$message_file") || die("Could't open $message_file for writing");
print WRITEMSG $msg;
close (WRITEMSG);
}
# update changes to message $message.msg and add prefix 'UP' to message if live
sub unpost_message {
$message = shift;
$message_file = "$message_dir/$message.msg";
if($message !~ /^UP/) {
unlink $message_file || die "Couldn't delete $message: $!\n";
$message = "UP".$message;
$message_file = "$message_dir/$message.msg";
}
my @l_fields = ('message_date_time','name', 'lastinitial', 'grade', 'email', 'essaytext');
for(@l_fields) { $$_ = param($_); $$_ =~ s/\r|\n//g; }
($fname,$lname) = split ' ',$name;
# build $msg, which is what gets fed directly to the flat file storing this info
$msg = "$fname\n$lname\n";
for(@fields) { $msg .= param($_)."\n" unless $_ eq 'fname' or $_ eq 'lname'; }
$msg .= "$message_date_time\n";
open(WRITEMSG, ">$message_file") || die("Could't open $message_file for writing");
print WRITEMSG $msg;
close (WRITEMSG);
}
# makes the message go bye-bye
sub delete_message{
$message = shift;
$message_file = "$message_dir/$message.msg";
unlink "$message_file" || die "Couldn't delete $message_file: $!";
}
# remove suspicious characters from message input fields
sub taint_check{
my $str = shift;
$str =~ s/javascript://g;
$str =~ s/\|//g;
$str =~ s/\*/\&\#042\;/g;
$str =~ s/\!/\&\#033\;/g;
$str =~ s/\\&\#060\;/g;
$str =~ s/\>/\&\#062\;/g;
$str =~ s/\?/\&\#063\;/g;
$str =~ s/\$/\&\#036\;/g;
$str =~ s/\r|\n//g;
return $str;
}
###########################################################
#
# subroutine: send_mail
# Usage:
# &send_mail("me@myhouse.com","you@yourhouse.com","them@theirhouse.com","Mysubject", "My message");
#
# Parameters:
# $from = Full Email address of sender
# $to = Full Email address of receiver
# $cc = Full Email address of cc
# $subject = Subject of message
# $messagebody = Body of message including newlines.
#
# Output:
# None
#
############################################################
sub send_mail {
my($from, $to, $subject, $messagebody, $cc) = @_;
# open(SENDMAIL, "|$mail_program ") or die "Can't fork for sendmail: $!\n";
#
# print SENDMAIL qq(From: $from\n);
# print SENDMAIL qq(To: $to\n);
# print SENDMAIL qq(CC: $cc\n) if $cc;
# print SENDMAIL qq(Subject: $subject\n\n);
# print SENDMAIL qq($messagebody\n);
# close(SENDMAIL);
}
###########################################################
#
# subroutine: email_feedback
# Usage:
#
#
# Parameters:
#
#
# Output:
# None
#
############################################################
sub email_feedback {
my $name = param('name');
my $email = param('email');
my $subject = param('subject');
my $from = "$email";
my $to = join ',',@feedback_email;
#my $cc = join ',',@moderator_email;
my $message = qq(forum: $forum\nname: $name\nemail: $email\n\n$message\n);
&send_mail($from, $to, $subject, $message);
}
# returns 1 if all required fields are filled in, 0 if some are missing
sub all_required {
my @req_fields = ('name', 'lastinitial', 'grade', 'email', 'essaytext');
for(@req_fields) {
if(not defined $cgi->param($_) or $cgi->param($_) eq '') { $fields_missing = 1 if param('flag'); return 0; }
}
$fields_missing = 0;
return 1;
}
# custom sort function:
# sorts internal numbers without regard for leading alphabetical characters
# ex: UM000007 and 000003 would normally not be sorted correctly
sub fn_cmp {
my $eval_str = '$a <=> $b';
if(length($a)>10) {
$tmp_a = $a;
$tmp_a =~ s/^[A-Z]+//;
$eval_str =~ s/a/tmp_a/;
}
if(length($b)>10) {
$tmp_b = $b;
$tmp_b =~ s/^[A-Z]+//;
$eval_str =~ s/b/tmp_b/;
}
return eval($eval_str);
}