#!/usr/ucb/perl # # Ryan J. Shaltry # tech4@msue.msu.edu # Guy Albertelli # albertel@msu.edu # # CAPA Discussion Forum # version 1.3.0 # Copyright (C) 1992-2000 Michigan State University # # The CAPA system is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # The CAPA system is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public # License along with the CAPA system; see the file COPYING. If not, # write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # As a special exception, you have permission to link this program # with the TtH/TtM library and distribute executables, as long as you # follow the requirements of the GNU GPL in regard to all of the # software in the executable aside from TtH/TtM. print "Content-type: text/html\n\n"; use Benchmark; $BenchmarkT0 = new Benchmark; #require "capadiscuss.setup"; require "../capadiscuss_html"; ################################################ ## Configuration - Change these appropriately ## ################################################ $discussurl = "capadiscuss"; $capasbin = "/capa-bin"; use Cwd; $capabin = cwd(); @capabinparts = split /\//, $capabin; $capabin = join "/", @capabinparts[0..$#capabinparts-1]; # capadiscuss.setup $debug = 0; ################################################ ## End Configuration ########################### ################################################ &form_info; $yp = "19"; $validadmin = "unchecked"; # define variables $class = $form{'CLASS'}; $snum = $form{'SNUM'}; $capaid = $form{'CAPAID'}; $setid = $form{'SETID'}; $action = $form{'ACTION'}; $file = $form{'FILE'}; $probnum = $form{'PROBNUM'}; $replynum = $form{'REPLYNUM'}; $psetid = $form{'PSETID'}; if ($snum eq "A12345678") {$debug=1;} if ($snum eq "a12345678") {$debug=1;} $debug=0; if($psetid eq "") { $psetid = $setid; } if ($debug) {print "GetTeacherInfo
";$BenchmarkTa = new Benchmark;} &GetTeacherInfo; if($debug) {$BenchmarkTb = new Benchmark;print "
",timestr(timediff($BenchmarkTb,$BenchmarkTa)),"\n";} # check if student is banned from forum if ($debug) {print "BanUser
";$BenchmarkTa = new Benchmark;} if (&BanUser) {exit;} if($debug) {$BenchmarkTb = new Benchmark;print "
",timestr(timediff($BenchmarkTb,$BenchmarkTa)),"\n";} # check for valid studentnumber/capaid, an exit will occur here if the set wasn't open if ($debug) {print "ValidateUser
";$BenchmarkTa = new Benchmark;} &ValidateUser; if($debug) {$BenchmarkTb = new Benchmark;print "
",timestr(timediff($BenchmarkTb,$BenchmarkTa)),"\n";} # grab username from student number if ($debug) {print "UserInfo
";$BenchmarkTa = new Benchmark;} &UserInfo($snum); if($debug) {$BenchmarkTb = new Benchmark;print "
",timestr(timediff($BenchmarkTb,$BenchmarkTa)),"\n";} if ($debug) {print "GetDateTime
";$BenchmarkTa = new Benchmark;} &GetDateTime; if($debug) {$BenchmarkTb = new Benchmark;print "
",timestr(timediff($BenchmarkTb,$BenchmarkTa)),"\n";} if ($debug) {print $action . "
";$BenchmarkTa = new Benchmark;} # call appropriate sr if($action eq "newset" ) { &NewSet; } if($action eq "viewset" || $action eq "" ) { &ViewSet; } if($action eq "viewproblem" ) { &ViewProblem; } if($action eq "post" ) { &Post; } if($action eq "postsubmit" ) { &PostSubmit; } if($action eq "delmsgpre" ) { &DelMsgPre; } if($action eq "delmsg" ) { &DelMsg; } if($action eq "hidemsgpre" ) { &HideMsgPre; } if($action eq "hidemsg" ) { &HideMsg; } if($action eq "unhidemsgpre" ) { &UnHideMsgPre; } if($action eq "unhidemsg" ) { &UnHideMsg; } if($action eq "admin" ) { &AdminMain; } if($action eq "adminusersearch" ) { &AdminUserSearch; } if($action eq "adminusersearchsubmit" ) { &AdminUserSearchSubmit; } if($action eq "viewinfofile" ) { &ViewInfoFile; } if($action eq "topmsg" ) { &TopMsg("top"); } if($action eq "untopmsg" ) { &TopMsg(""); } if($debug) {$BenchmarkTb = new Benchmark;print "
",timestr(timediff($BenchmarkTb,$BenchmarkTa)),"\n";} $BenchmarkT1 = new Benchmark; if($debug) { print "
",timestr(timediff($BenchmarkT1,$BenchmarkT0)),"\n";} exit; ####################### ## Begin Subroutines ## ####################### sub GetSetList { opendir(DDIR,"$capadir/$class/discussion"); @sets = grep(/^[0-9]+$/,sort(readdir(DDIR))); closedir(DDIR); if ($debug) {print "
Sets:". @sets ."
\n";} } sub SetListHeader { $pdset = "\n"; } sub GetInfoList { local(@temp,@alldir,@setdir); # if ($debug) {print "
GetInfoList
";} opendir(DDIR,"$capadir/$class/discussion"); @alldir = sort(grep(/.info$/,readdir(DDIR))); closedir(DDIR); opendir(FORUM,"$capadir/$class/discussion/$setid"); @setdir = sort(grep(/.info$/,readdir(FORUM))); closedir(FORUM); foreach $file(@setdir) { @setdir2 = (@setdir2,"$setid/$file"); } @infofiles = (@alldir,@setdir2); $infostring = ""; # if ($debug) {print "
GetInfoList" . @infofiles."
";} foreach $infofile(@infofiles) { # if ($debug) {print "
GetInfoList" . $infofile."
";} @temp = reverse split /\//, $infofile; $infodesc = $temp[0]; $infodesc =~ s/.info//g; $infodesc =~ s/_/ /g; $infostring .= &InfoButtonHTML; } if ($infostring ne "") { # $infostring = "" . $infostring; } # if ($debug) {print "
GetInfoList" . $infostring."
";} } sub NewSet { &Log("NewSet"); if($setid <= $psetid) { #grab capaid if ($debug) {print "NewSet
";$BenchmarkTa = new Benchmark;} @allcapaid = `allcapaid -s $setid -e $setid -stu $snum -c $capadir/$class -i`; $capaid = $allcapaid[2]; chop $capaid; chop $capaid; &ViewSet; if($debug) {$BenchmarkTb = new Benchmark;print "
",timestr(timediff($BenchmarkTb,$BenchmarkTa)),"\n";} return; } if ($debug) { print "
GetSetList\n"; } &GetSetList; if ($debug) { print "
EndGetSetList\n"; } &SetListHeader; &NewSetHTML; #exit; } sub ViewSet { local($hidden); if ($debug) {print "InsideViewSet
";$BenchmarkTa = new Benchmark;} &Log("ViewSet"); &CheckAdmin; $adminbutton = ""; if($validadmin eq "yes") { $adminbutton = &AdminButtonHTML; } $capasbin = "$capasbin/$teachdir/capasbin"; &SetJumpBox; $backfunction="viewset"; &GetInfoList; opendir(FORUM,"$capadir/$class/discussion/$setid"); @dir = sort(readdir(FORUM)); closedir(FORUM); foreach $i(@dir) { $probnum = &RemZero(substr($i,0,6)); $found[$probnum]++; } $maxprobs = &MaxProbs($setid); # split table (if more than 15 problems) $bigtable = "no"; if($maxprobs > 5) { $bigtable = "yes"; $col1size = int ($maxprobs / 2); $col2size = $maxprobs - $col1size; if($col1size < $col2size) { $t = $col1size; $col1size = $col2size; $col2size = $t; } } if($debug) {$BenchmarkTb = new Benchmark;print "
2",timestr(timediff($BenchmarkTb,$BenchmarkTa)),"\n";} &ViewSetTitleHTML; if($bigtable eq "no") { &ViewSetTopSmallHTML; } else { &ViewSetTopBigHTML; } $col = 1; for($probnum=1; $probnum<=$maxprobs; $probnum++) { $hidden=0; if($col eq "1" && $probnum > $col1size && $bigtable eq "yes") { $col = 2; &ViewSetEndColHTML; &ViewSetTopSmallHTML; } if($found[$probnum] ne "") { opendir(MSG,"$capadir/$class/discussion/$setid"); @msgs = grep(/.msg/,sort(readdir(MSG))); closedir(MSG); foreach $msg(@msgs) { if(&RemZero(substr($msg,0,6)) eq $probnum) { &OpenMsg("$capadir/$class/discussion/$setid/$msg"); if(!($status eq "hidden" && $validadmin ne "yes")) { push(@good,$msg); } else { $hidden++; } } } $posts = $found[$probnum]-$hidden; if ($posts >0) { &OpenMsg("$capadir/$class/discussion/$setid/$good[$#good]"); $lastpost = "$date at $time"; } else { $lastpost = "--"; } } else { $lastpost = "--"; $posts = "0"; } &ViewSetGutsHTML; } &ViewSetBotHTML; if($debug) {$BenchmarkTb = new Benchmark;print "
3",timestr(timediff($BenchmarkTb,$BenchmarkTa)),"\n";} #exit; } sub ViewProblem { &Log("ViewProblem"); # check if user is administrator (for admin button) &CheckAdmin; if($validadmin eq "yes") { $adminbutton = &AdminButtonHTML; } else { $adminbutton = ""; } opendir (MSGS,"$capadir/$class/discussion/$setid"); @msgs = sort(readdir(MSGS)); closedir(MSGS); # search for top message @top = grep (/top/, @msgs); $topmsg = ""; # print "$#top"; if($#top ne "0") { $pnum = &AddZero($probnum); foreach $entry(@top) { $find = $entry =~ s/\A$pnum/$pnum/o; if($find eq "1") { $topmsg = $entry; @msgs = grep(!/$topmsg/,@msgs); unshift(@msgs,$topmsg); print "$topmsg"; } } } $msgfind = "no"; $msgcount = 0; $capasbin = "$capasbin/$teachdir/capasbin"; foreach $i(@msgs) { $pn = &RemZero(substr($i,0,6)); if($pn eq $probnum) { $msgcount++; $msgfind = "yes"; &OpenMsg("$capadir/$class/discussion/$setid/$i"); if($status eq "hidden" && $validadmin ne "yes") { $msgcount--; $msgfind = "no"; } if($msgcount eq "1") { &GetInfoList; $postbutton = &ReplyButtonHTML; &ProblemJumpBox; &ViewProblemTopHTML; } ($token1,$token2) = split(/\|/,$poster); chop $token2; if($token1 eq "Anonymous") { if($validadmin eq "yes") { $poster = "$token2 (anonymously)"; } else { $poster = "$token1"; $email = ""; } } $topfind = grep(/-top.msg/,$i); if($validadmin eq "yes") { $file = "$i"; $delbutton = &DelButtonHTML; $hidebutton = &HideButtonHTML; $topbutton = &TopButtonHTML; if($topfind eq "1") { $topbutton = &UnTopButtonHTML; } } $subjectbgcolor = "#92D1D0"; if($topfind eq "1") { $subjectbgcolor = "blue"; } $messagenote = ""; if($validadmin eq "yes" || $status eq "public") { if($status eq "hidden") { $subjectbgcolor = "red"; $hidebutton = &UnHideButtonHTML; $messagenote = "Hidden by $hiddenuser on $hiddendate at $hiddentime from $hiddenaddr"; } # $message =~ s//>/g; &ViewProblemGutsHTML; } } } if($msgfind eq "no") { &GetInfoList; $postbutton = &PostNewButtonHTML; &ProblemJumpBox; &ViewProblemTopHTML; &ViewProblemNoneHTML; &ViewProblemBotHTML; } else { &ViewProblemBotHTML; } #exit; } sub ViewInfoFile { &Log("InfoFile"); open(INFOFILE,"$capadir/$class/discussion/$file"); @file = ; closedir(INFOFILE); print ""; $backfunction = $form{'BACKFUNCTION'}; &InfoBackButtonHTML; foreach $line(@file) { print "$line"; } #exit; } sub Post { local(@msgs,$pn,$msg); # grab last message in thread opendir(MSGS,"$capadir/$class/discussion/$setid"); @msgs = grep(/.msg/,sort(readdir(MSGS))); closedir(MSGS); foreach $msg(@msgs) { $pn = &RemZero(substr($msg,0,6)); if($pn eq $probnum) { $lastfile = $msg; } } $PostType = "New Message"; if($lastfile ne "") { &OpenMsg("$capadir/$class/discussion/$setid/$lastfile"); if($status eq "public" || $validadmin eq "yes") { ($poster,$rposter) = split(/\|/,$poster); $inreplyto = &InReplyToHTML; $PostType = "Reply"; } } &PostHTML; #exit; } sub PostSubmit { local($message,$subject,$date); $message = $form{'message'}; $subject = $form{'subject'}; if($message eq "" || $subject eq "") { &MFPostReplyHTML; } &Log("Post"); # find last message in thread opendir(FORUM,"$capadir/$class/discussion/$setid"); @dir = sort(readdir(FORUM)); closedir(FORUM); $probnum = &AddZero($probnum); $replynum = "000000"; foreach $msg(@dir) { if(substr($msg,0,6) eq $probnum) { $replynum = &AddZero(&RemZero(substr($msg,7,6)) + 1); } } $date = substr($RunonDate,0,4) . $yp . substr($RunonDate,4,2); &WriteMsg("$capadir/$class/discussion/$setid/$probnum-$replynum-$date-000000.msg"); $probnum = &RemZero($probnum); &PostDoneHTML; #exit; } sub DelMsgPre { &CheckAdmin('kill'); &OpenMsg("$capadir/$class/discussion/$setid/$file"); &DelMsgPreHTML; #exit; } sub DelMsg { &CheckAdmin('kill'); unlink("$capadir/$class/discussion/$setid/$file"); &DelMsgDoneHTML; #exit; } sub HideMsgPre { &CheckAdmin('kill'); &OpenMsg("$capadir/$class/discussion/$setid/$file"); &HideMsgPreHTML; #exit; } sub HideMsg { &CheckAdmin('kill'); open(MSG,"$capadir/$class/discussion/$setid/$file"); @msg = ; close(MSG); unlink("$capadir/$class/discussion/$setid/$file"); open(MSG,">$capadir/$class/discussion/$setid/$file"); for($i=0;$i<=5;$i++) { print MSG "$msg[$i]"; } print MSG "hidden|$username|$HyphenDate|$Time|$ENV{'REMOTE_ADDR'}\n"; close(MSG); &HideMsgDoneHTML; } sub UnHideMsgPre { &CheckAdmin('kill'); &OpenMsg("$capadir/$class/discussion/$setid/$file"); &UnHideMsgPreHTML; #exit; } sub UnHideMsg { &CheckAdmin('kill'); open(MSG,"$capadir/$class/discussion/$setid/$file"); @msg = ; close(MSG); unlink("$capadir/$class/discussion/$setid/$file"); open(MSG,">$capadir/$class/discussion/$setid/$file"); for($i=0;$i<=5;$i++) { print MSG "$msg[$i]"; } print MSG "public||||}\n"; close(MSG); &UnHideMsgDoneHTML; } sub TopMsg { &CheckAdmin('kill'); $ext = shift(@_); open(MSG,"$capadir/$class/discussion/$setid/$file"); @msg = ; close(MSG); unlink("$capadir/$class/discussion/$setid/$file"); ($filename, $extension) = split(/\./,$file); $filename = "$filename-$ext.msg"; open(MSG,">$capadir/$class/discussion/$setid/$filename"); for($i=0;$i<=6;$i++) { print MSG "$msg[$i]"; } close(MSG); if($ext eq "") { $function = "restored to its original position in the thread."; } else { $function = "moved to the top of the thread list."; } &TopMsgDoneHTML; } ############################### ## Administrator Subroutines ## ############################### sub AdminMain { &CheckAdmin('kill'); &AdminMainHTML; #exit; } sub AdminUserSearch { &CheckAdmin('kill'); &AdminUserSearchHTML; #exit; } sub AdminUserSearchSubmit { local($sname,$semail,$saction,$sset,$sprob,$sdate,$stime); &CheckAdmin('kill'); $query = $form{'usersearch'}; open(LOG,"$capadir/$class/discussion/logs/access.log"); @log = ; close(LOG); @linematches = grep /$query/, @log; foreach $line(@linematches) { print $line; } #exit; } ###################### ## Misc Subroutines ## ###################### sub OpenMsg { local($filename,$statusl); $filename = shift(@_); open (MSG,"$filename"); @msg = ; close(MSG); $poster = $msg[0]; $date = $msg[1]; $time = $msg[2]; $subject = $msg[3]; $email = $msg[4]; $message = $msg[5]; $statusl = $msg[6]; ($status, $hiddenuser, $hiddendate, $hiddentime, $hiddenaddr) = split(/\|/,$statusl); } sub WriteMsg { local($filename,$message); $filename = shift(@_); # add sr to grab e-mail address of user #


      • %html=(B=>1, I=>1, P=>1, A=>1, LI=>1, OL=>1, UL=>1, EM=>1, BR=>1, TT=>1, STRONG=>1, BLOCKQUOTE=>1, DIV=>1, IMG=>1); $message = $form{'message'}; $message =~ s/((\n\r)|(\n))\n/

        /g; $message =~ s/\n/
        /g; $message =~ s/\<(\/?\s*(\w+)[^\>\<]*)/ {($html{uc($2)}&(length($1)<1000))?"\<$1":"\<$1"}/ge; $message =~ s/(\]*)\>/ {($html{uc($2)}&(length($1)<1000))?"$1\>":"$1\>"}/ge; # $message =~ s//>/g; # check if posted anonymously if($form{'ANONYMOUS'} eq "yes") { $username = "Anonymous|$username"; } open (MSG,">$filename"); print MSG "$username\n"; print MSG "$HyphenDate\n"; print MSG "$Time\n"; print MSG "$subject\n"; print MSG "$email\n"; print MSG "$message\n"; print MSG "public||||\n"; close(MSG); } sub GetTeacherInfo { local($capa5dir,$classname,$tdir,@classconf); # open/read class.conf file open (CLASSCONF,"$capabin/class.conf"); @classconf = ; close(CLASSCONF); $found eq "no"; foreach $line(@classconf) { ($classname,$capa5dir,$tdir) = split(/[\t\ ]+/,$line); if($classname eq $class) { $teachdir = $tdir; $capadir = $capa5dir; $found = "yes"; $cgidirurl = join "/", $capasbin,$teachdir; } } if($found eq "no") { &InvalidVarsHTML; } } sub CheckAdmin { local($asection,@adminsections,$line,@capaconfig,$command,$value, $adminsection,@classl,$course,$coursenum,$section,$stunum,$a); $mode = shift(@_); if ($validadmin eq "unchecked") { $validadmin = "no"; # open 'capa.config' file (for admin section read) open(CAPACONFIG,"$capadir/$class/capa.config"); @capaconfig = ; close(CAPACONFIG); foreach $line(@capaconfig) { chop $line; ($command,$value) = split(/\ =\ /,$line); if($command eq "admin_section") { $adminsection = $value; last; } } if ($debug) { print "Admin Sections: ".$adminsection;} @adminsections = split(/\,/,$adminsection); for ($asection=0; $asection <= $#adminsections; $asection++) { $adminsections[$asection]=&RemZero($adminsections[$asection]) } # open 'classl' file open(CLASSL,"$capadir/$class/classl"); @classl = ; close(CLASSL); $snum =~ tr/a-z/A-Z/; LINE: foreach $line(@classl) { $section= substr $line, 10, 3; $stunum= substr $line, 14, 9; $stunum =~ tr/a-z/A-Z/; if ( $stunum ne $snum ) { next LINE;} $section = &RemZero($section); if ($debug) {print "
        ".$stunum."Is in section:".$section."
        ";} foreach $asection(@adminsections) { if($section eq $asection ) { $validadmin = "yes"; last LINE; } } } } if($validadmin eq "no" && $mode eq "kill") { &NotAdminHTML; } } sub BanUser { local (@capaconfig,$line,$command,$value,$ban,@banned,$result); $result = 0; open(CAPACONFIG,"$capadir/$class/capa.config"); @capaconfig = ; close(CAPACONFIG); foreach $line(@capaconfig) { chop $line; ($command,$value) = split(/\ =\ /,$line); if($command eq "banned_users") { $ban = $value; last; } } if ($debug) { print "Banned Users: ".$ban } @banned = split(/\,/,$ban); $snum =~ tr/a-x/A-Z/; foreach $ban (@banned) { if ($debug) {print $ban . "is Banned
        ";} $ban =~ tr/a-z/A-Z/; $ban =~ tr/\ //d; if ( $ban eq $snum) { &BannedMessageHTML; $result=1 } } return $result } sub ValidateUser { local(@allcapaid,@classl,$line); open (CLASSL,"$capadir/$class/classl"); @classl = ; close(CLASSL); $valid = "no"; foreach $line(@classl) { if(substr($line,15,8) eq substr($snum,1,8)) { $valid = yes; } } if($valid eq "no") { &InvalidVarsHTML; } # check w/ allcapaid program @allcapaid = `allcapaid -s $setid -e $setid -stu $snum -c $capadir/$class -i -checkopen`; chop $allcapaid[2]; chop $allcapaid[2]; if ($debug) {print "capaid:" . $allcapaid[2] . "
        \n";} if($allcapaid[2] ne $capaid) { if ($allcapaid[2] =~ /Open/) { &NotOpen; exit; } if($action ne "newset") { &BadPassHTML; exit; } #&NewSet; } } sub NotOpen { &GetSetList; &SetListHeader; &ViewSetTitleHTML; print < NotOpen2 } sub UserInfo { local($line,@classl,$last,$first,$middle); open (CLASSL,"$capadir/$class/classl"); @classl = ; close(CLASSL); foreach $line(@classl) { if(substr($line,15,8) eq substr($snum,1,8)) { $username = substr($line,24,36); $email = substr($line,60,45); } } ($last, $first, $middle) = split(/\ +/,$username); chop $last; $username = "$first $last"; $email =~ s/\ //g; chop $email; } sub MaxProbs { open (SETRECORD,"$capadir/$class/records/set$setid.db"); $setrecord = ; close(SETRECORD); chop $setrecord; return $setrecord; } sub ProblemJumpBox { $pdprob = ""; } sub SetJumpBox { &GetSetList; &SetListHeader; } sub AddZero { $string = shift(@_); while(length($string) < 6) { $string = "0$string"; } return $string; } sub RemZero { $string = shift(@_); $string =~ s/^0*//g; return $string; } sub FormatDate { $string = shift(@_); $month = substr($string,0,2); $day = substr($string,2,2); $year = substr($string,4,4); $string = "$month-$day-$year"; return $string; } #################### ## Get SubRoutine ## #################### sub form_info { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); # Split the name-value pairs @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); if ($name eq "message") {$allow_html=1;} else {$allow_html=0;} # Un-Webify plus signs and %-encoding $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $value =~ s///g; if ($allow_html != 1) { $value =~ s/<([^>]|\n)*>//g; } $form{$name} = $value; } } ################## ## Date/Time sr ## ################## sub GetDateTime { ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime (time); $mon++; $year=$year+1900; if ($hour < 12) { $AMPM = "AM"; } if ($hour > 12) { $hour = $hour - 12; $AMPM = "PM"; } if ($hour == 12) { $AMPM = "PM"; } if ($hour == 0) { $hour = "12"; } $min = sprintf ("%2d", $min); $min =~tr/ /0/; $mon = sprintf ("%2d", $mon); $mon =~tr/ /0/; $mday = sprintf ("%2d", $mday); $mday =~tr/ /0/; $HyphenDate = ("$mon" . "-" . "$mday" . "-" . "$year"); $RunonDate = ("$mon$mday$year"); $Time = ("$hour" . ":" . "$min" . " " . "$AMPM"); } ######################## ## Logging Subroutine ## ######################## sub Log { $logmsg = shift(@_); &GetDateTime; &Lock("lock.file"); open(LOG,">>$capadir/$class/discussion/logs/access.log"); print LOG "$snum|$capaid|$username|$email|$logmsg|$setid|$probnum|$HyphenDate|$Time|$file\n"; close(LOG); &Unlock("lock.file"); } ############################ ## Lock/Unlock Subroutine ## ############################ sub Lock { local ($lockname) = @_; local ($endtime); $endtime = 15; $endtime = time + $endtime; while (-e $lockname && time < $endtime) { open (LOCKFILE, ">$lockname"); } sub Unlock { local ($lockname) = @_; close (LOCKFILE); unlink ($lockname); } } ###################### ## HTML Subroutines ## ###################### ## CapaDiscuss HTML Subroutines # capadiscuss_html ## end capadiscuss