## start exam, first module, file test ## ## use Session; use Apache::Cookie; use Apache::Request; use Ldap; use Utils; use FileTest; use strict; my $session = new Session; exit( 0 ) unless ( defined $session ); ########### ## retake time constants: my $REFRESH_TIME = 15*60; ## 15 minutes, we refresh the page until that my $RETAKE_TIME = 60*60; ## can retake only after that much time ########### ########### ## novell parameters my $NOVELL_IP="123.123.123.123"; my $NOVELL_SERVER="novell_server_name"; ########### ## ## This stage: filetest ## next stage: fchk ## my $r = $session->{request}; my $apr = $session->{apr}; my $uname=$apr->param('uname'); my $passwd=$apr->param('passwd'); my $pcook = $session->{cookies}->{'ID'}->value; my $id = "file"; ## my $next_stage = "fchk"; my $info = {}; $r->content_type("text/html"); ## This part sets ut the exam environment, and checks for eligibility; ## also checks the password if(! defined($uname) || !defined($passwd) || ! $uname || ! $passwd ){ Utils::errorpage("Incomplete","Plase fill out both Login name and Password fields."); return; } if( $uname =~ /[^a-zA-z0-9\.%\-]/ ){ ## there could be NO + sign in uname Utils::errorpage("Incomplete","The username you supplied is invalid."); return; } $uname = lc($uname); #convert to lowercase if( $passwd =~ /mouse/i ){ Utils::errorpage("Incomplete","Please change your password as it is too easy to guess."); return; } if( $passwd =~ /[\x00-\x1F \x7F-\xFF\'\"\\]/ ){ Utils::errorpage("Incomplete","The password you entered contains space, national character, or characters not allowed in passwords. Please change your password before taking the exam."); return; } my ($login,$vol,$email,$err) = Ldap::ldap_query($uname); if(defined $err){ Utils::errorpage("Incomplete","There were problems identifying \"$uname\". Please check the user name, and try again. If the problem persist, please turn to the Helpdesk.
The following error message was returned:
$err
"); return; } ## Now we try to set up the exam environment: ## Check if it is the first trial. If the directory /exam/$uname ## exists, then it is NOT the first attempt. ## files in /exam/$uname: ## o novell - directory, the mount point for $uname ## o mount - empty file, if not there ./novell can be unmounted ## mount is deleted regularly, and at the next swap, if no ## mount file, then ./novell is unmounted. ## this is used for cron to umount the novell dir ## o data - file containing the attempt number in lines as ## "Attempt:8,\n" also contains log of exam ## o startexam - used to measure elapsed time ## o attempt - contains the last attempt number only. ## o typing - typetest has been done ## o choice - multiple choice is done, offline part is missing only ## o done - if exists, the exam is done my $attempt = 0; ## which attempt is it my $exam_type = "first"; ## first, again, refresh, denied my $examdir = Utils::examdir($uname); my $novell= "$examdir/novell"; if(! -e "$examdir" ){ mkdir "$examdir"; mkdir "$novell"; } else { ## the user has a directory. Check whether she/he can take the exam, or ## took it. It might be someone else pretending to be that user - we cannot ## tell without mounting $novell first. if( -e "$examdir/done" ){ Utils::errorpage("Congratulations","You have taken the CEU Computer Proficiency Exam successfully; you should not take it again."); return; } if( -e "$examdir/data" ){ ## the elapsed time since $examdir/data has been modified ## if this time is less than $REFRESH_TIME, then refresh the page ## if bigger than $RETAKE_TIME then it is a new trial; otherwise ## we refuse to work at all my $elapsed = time - (stat("$examdir/data"))[9]; $exam_type = "denied"; $exam_type = "again" if($elapsed > $RETAKE_TIME); ## recover the attempt number if( open(DATA,"$examdir/data") ){ while(){ $attempt=$1 if( /Attempt:([0-9]+),/ ); } close (DATA); $attempt = 0+$attempt; $attempt=1 if($attempt<1|| $attempt > 10000); } ## we can have a valid refresh request. Thus we check the cookie; ## if matches then we accept the refresh; otherwise deny it. ## cookie = "seed" + "stage", seed = H(uname+attempt+stage) if( $elapsed < $REFRESH_TIME && defined( $pcook ) && $pcook =~ /^([^+]+)\+([a-z0-9]+)$/ ){ my($cH,$cstage) = ($1,$2); ########## !!!!!!!! ### what if this is a repeated request? - no refresh in that case? ### in that case $cstage ne $next_stage ########## if( defined $cH && Page::is_next_stage($id,$cstage) && $cH == Utils::generate_seed( "$uname+$attempt+$cstage" ) && -f "$examdir/attempt" && -f "$examdir/startexam" ){ ## yes, it is a valid refresh request. Recreate page $info->{uname} = $uname; $info->{attempt} = $attempt; $info->{examdir} = $examdir; $info->{elapsed} = time - (stat("$examdir/startexam"))[9]; return Page::make_page($id,"refresh",$session,$r,$info); } } } } if( $exam_type eq "denied" && ! $session->{retakewait} ){ Utils::errorpage("Sorry","You've made an attempt to complete the Computer Proficiency Exam quite recently. You can retake it only sometimes later."); return; } ## try to mount the novell filesystem: Utils::make_file("$examdir/mount"); `/usr/bin/ncpumount $novell 2>/dev/null 2>/dev/null`; $err = `/usr/bin/ncpmount -A $NOVELL_IP -S $NOVELL_SERVER -U $login -V $vol -P \"$passwd\" $novell 2>&1`; if( $?>>8){ Utils::unmount($examdir); chomp $err; $err =~ s/^ncpmount:\s*//i; $err =~ s/\n/