#!/usr/local/bin/perl # # World Wide Web Treasure Hunt # CGI Safeperl Script v1.10 # (c)1996 Mark Rigby-Jones for mrjsw # # Variable initialisation $huntnum = "III"; # Treasure hunt number $endtime = 847443600; # Time it ends (as returned by perl's time command) $gamelength = 1440; # Game length in minutes $begins = "9am Thursday"; # When the game begins # Read input from form if ($ENV{REQUEST_METHOD} eq "GET") { $data = $ENV{QUERY_STRING}; } elsif ($ENV{REQUEST_METHOD} eq "POST") { for ($i = 0; $i < $ENV{CONTENT_LENGTH}; $i++) { $data .=getc; } } # Process, decode and split input data @data = split(/&/, $data); @data0 = split(/=/, $data[0]); @data1 = split(/=/, $data[1]); @input = (@data0,$data1[1]); foreach $item (0..2) { $input[$item] = substr($input[$item], index($input[$item], '=') + 1); $input[$item] =~ s/\+/ /g; $input[$item] =~ s/%(..)/pack("c",hex($1))/ge; $input[$item] =~ tr/:/;/s; } # Load the teams information open(TEAMS, "out/hunt.t"); $nteams = 0; $tnum = -1; $tchange = 0; while ($team = ) { ($tnum[$nteams],$tname[$nteams],$temail[$nteams],$tans[$nteams],$tpass[$nteams],$tnext[$nteams],$tinc[$nteams]) = split(/:/, $team); if ($input[1] == $tnum[$nteams]) { $tnum = $nteams; } $nteams++; } # Check time $secs = ($endtime - time); $mins = ($secs - ($secs % 60)) / 60; $scoreline = "Scores with $mins Minutes Remaining"; if ($mins > $gamelength) { # Output: Before game has started $scoreline = ''; $startsin = $mins - $gamelength; &header("Not Yet!"); print(<Registation does not begin until $begins!
(In $startsin minutes, to be precise) BACK_TO_PERL &log("Too early warning"); } elsif ($mins < 0) { # Output: After game has ended $scoreline = "Final Scores"; &header("Game Over!"); print(<Game Over!

Final scores are listed below

BACK_TO_PERL &log("Final scores given out"); } elsif ($input[0] eq 'name') { # Output: Team registration &header("Registration"); # Check that this is a new team name and email address $dupemail = 0; $dupname = 0; for ($i = 0; $i < $nteams; $i++) { if ($temail[$i] eq $input[2]) { $dupemail = 1; } elsif ($tname[$i] eq $input[1]) { $dupname = 1; } } if (($input[1] eq '') or ($input[2] eq '')) { print(<Registration Unuccessful!

Please fill in both a team name and an email address!

Register Properly!

BACK_TO_PERL &log("Incomplete registration: '$input[1]' <$input[2]>"); } elsif ($dupemail == 1) { # Previously used email address print(<Registration Unuccessful!

Only one team per email address, please!

Register Properly!

BACK_TO_PERL &log("Multi-Registration: <$input[2]>"); } elsif ($dupname == 1) { # Previously used team name print(<Registration Unuccessful!

Sorry, but a team with this name has already been registered.

Try Another Name

BACK_TO_PERL &log("Multi-Registration: '$input[1]'"); } else { # OK: Register the new team ($tnum[$nteams],$tname[$nteams],$temail[$nteams],$tans[$nteams],$tpass[$nteams],$tnext[$nteams],$tinc[$nteams]) = (($secs + 12345),$input[1],$input[2],0,0,0,0); $tnum = $nteams; $nteams++; open(TEAMS, ">> hunt.t"); print(TEAMS "$tnum[$tnum]:$tname[$tnum]:$temail[$tnum]:0:0:0:0:\n"); close(TEAMS); mail($temail[$tnum], "WWW Treasure Hunt $huntnum Registation", "Registation for the team '$tname[$tnum]'\n\nYour team number is $tnum[$tnum]\n\nThanks for playing!\n"); print(<Registration Successful!

Your team has been successfully registered for the treasure hunt. To get your first question, follow the link below. The URL below is the one which you must return to each time you need to answer or pass on a question. Either follow the link and bookmark the page which it takes you to, or if your browser cannot do that, write it down. Do not use 'back' or other history functions of your browser, as this may cause answers to be resubmitted incorrectly, losing you points! If a suggested answer format is given in brackets, you must use this or your answer may not be recognised!

http://users.ox.ac.uk/cgi-bin/safeperl/microsoc/hunt?team=$tnum[$tnum]

BACK_TO_PERL &log("'$tname[$tnum]' <$temail[$tnum]> registered as $tnum"); } } elsif ($input[0] eq 'team') { # Output: Question request or answer # Find team details for ($i = 0; $i < $nteams; $i++) { if ($input[1] == $tnum[$i]) { $tnum = $i; } } if ($tnum == -1) { # Team doesn't exist &header("Illegal Team"); print(<Illegal Team Number!

Looks like you've mistyped the team number - unless you're trying to cheat, or something...

Your Team Number:
BACK_TO_PERL &log("Illegal team number $input[1]"); } else { # Team OK # Read in the question data $qnum = $tnext[$tnum] + 1; open(QUEST, "out/hunt.q"); for ($i = 0; $i <= $qnum; $i++) { ($quest,$ans) = split(':', ); } $anst = $ans; $anst =~ tr/[A-Z]/[a-z]/s; $tans = $input[2]; $tans =~ tr/[A-Z]/[a-z]/s; if ($tans eq '') { # No answer given, so just a question request &header("Your Question"); &log("'$tname[$tnum]' given question $qnum"); } elsif ($tans =~ /pass/) { # Question was passed $tans = ''; $tnext[$tnum]++; $tpass[$tnum]++; $tinc[$tnum] = 0; $tchange = 1; ($quest,$nans) = split(':', ); &header("Passed Question"); print(<You Passed the Last Question
BACK_TO_PERL &log("'$tname[$tnum]' passed question $qnum"); } elsif ($tans =~ m~$anst~) { # Correct answer $tnext[$tnum]++; $tans[$tnum]++; $tinc[$tnum] = 0; $tchange = 1; ($quest,$nans) = split(':', ); &header("Right Answer"); print(<The Right Answer!

Your answer, "$input[2]" was close enough to the answer we were looking for - "$ans" - to get the point.


BACK_TO_PERL &log("'$tname[$tnum]' correctly answered question $qnum"); } else { # Incorrect answer $tinc[$tnum]++; $tchange = 1; if ($tinc[$tnum] == 2) { # Second failed attempt - move to next question $tnext[$tnum]++; $tpass[$tnum]++; $tinc[$tnum] = 0; $next = "That was your second incorrect attempt at that question, so you have been automatically moved on to the next. If you still think that your answer was correct then send an email to microsoc\@sable.ox.ac.uk and we'll check up on it. You must include your team name and the URL where you found your answer or we cannot give you the point! Please don't use this unless you really do think we're wrong."; ($quest,$nans) = split(':', ); } else { # First failed attempt $next = "That was your first attempt at that question, you have one more remaining. Make sure that you haven't made any typos."; } &header("Wrong Answer"); print(<The Wrong Answer!

Your answer, "$input[2]" was not close enough to the answer we were looking for to get the point. $next


BACK_TO_PERL &log("'$tname[$tnum]' answered question $qnum incorrectly. '$tans', should be '$anst'"); } close(QUEST); # Rewrite team data, if neccessary if ($tchange == 1) { open(TEAMS, "> hunt.t"); for ($i = 0; $i < $nteams; $i++) { print(TEAMS "$tnum[$i]:$tname[$i]:$temail[$i]:$tans[$i]:$tpass[$i]:$tnext[$i]:$tinc[$i]:\n"); } } if ($quest eq '') { # All questions answered print("

No Questions Remaining!

\n

However, if you come back later there may be some more. Apologies for any inconvenience.

\n"); } else { # Give the next question print(<Your Next Question:

$quest

Your Answer:

BACK_TO_PERL } } } else { # Output: Neither registration or question/answer &header("Scores"); print(<If you want to register for the treasure hunt, the URL you require is:
http://users.ox.ac.uk/~microsoc/hunt/

If you are already participating, you need something of the form:
http://users.ox.ac.uk/cgi-bin/safeperl/microsoc/hunt?team=XXXXX

Your Team Number:
BACK_TO_PERL &log("Scores given out"); } close(TEAMS); if ($scoreline ne '') { # Display scores print(<

$scoreline

Team Name: Points: Passes:
BACK_TO_PERL for ($i = 0; $i < $nteams; $i++) { if ($i == $tnum) { print("
$tname[$i] $tans[$i] $tpass[$i]
\n"); } else { print("
$tname[$i] $tans[$i] $tpass[$i]
\n"); } } print("

"); } # Print footer print(<

-- Home --
©1996 Oxford University Computer Society
microsoc\@sable.ox.ac.uk

BACK_TO_PERL # Print an entry to the logfile with timestamp and remote accesser details sub log { ($text) = @_; $localtime = localtime; open(LOG, ">> hunt.l"); print(LOG "$localtime $ENV{REMOTE_USER}\@$ENV{REMOTE_HOST}($ENV{REMOTE_ADDR}) $text\n"); close(LOG); } # Pint out the top of a web page with the specified title addendum sub header { ($text) = @_; print(< Treasure Hunt - $text

-- CSOC --

World Wide Web Treasure Hunt $huntnum


BACK_TO_PERL } # EOF