## 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/
/g; Utils::errorpage("Error","Some problem occurred while connecting to your personal drive. Please check your account name and retype your password carefully. If the problem persists, please turn to the helpdesk. The following information might help to identify the source of the problem:

User name:
$uname
Context:
$login
Volume:
$vol
Error Message:
$err
"); return; } ## SPECIAL CASE: get rid of old leftover data if( $exam_type ne "first" ){ FileTest::purge_test($examdir,Utils::generate_seed( "$uname+$attempt+fchk") ); } ## Check for enough free space my $ok = 0; mkdir "$novell/.FTEST"; if( -d "$novell/.FTEST" ) { my $testfile="$novell/.FTEST/dummy"; Utils::write_file( $testfile," " x 4096 ); if( -e $testfile && (stat($testfile))[7] == 4096 ) { $ok = 1; } `/bin/rm -rf "$novell/.FTEST" >/dev/null 2>/dev/null`; } if( !$ok ){ Utils::unmount($examdir); Utils::errorpage("Error","Your persional drive is full.
You can store up to 20 megbytes on your drive; and you is over that limit. Before continuing your exam, please delete some files."); return; } $attempt++; Utils::create_file("$examdir/startexam"); Utils::write_file("$examdir/attempt","$attempt\n"); my $datenow=localtime; Utils::append_file("$examdir/data","Email:$email\n") if ($attempt == 1); Utils::append_file("$examdir/data","Attempt:$attempt,\nDate: $datenow\n"); ## now what if the typing/choice test was passed ? $id = "qa_general" if( -f "$examdir/typing" ); $id = "offline" if( -f "$examdir/choice" ); Utils::unmount($examdir) if( $id ne "file" ); $info->{uname} = $uname; $info->{attempt} = $attempt; $info->{examdir} = $examdir; $info->{elapsed} = 0; return Page::make_page($id,"new",$session,$r,$info);