Simplest Program Possible With Alternative Input

Here is the full text of our adjusted prototype question.
#!/usr/local/bin/perl -- -*- C -*-
use CGI;
$query = new CGI;
print $query->header;
print $query->start_html("Perl4q1.pl");
print $query->start_form;
$ans = 5280;
print "<P> How many feet are there in a mile?",
$query->textfield('stu_ans','',10,30);
print "<P> Is the above answer correct?",$query->submit("Send Answer in For Grading");
print $query->reset;
print $query->end_form;
$returned_ans = $query->param('stu_ans');
if ( $query->param('stu_ans') ne '')
{
	print "<em>Student_answer, </em>$returned_ans";
	$returned_ans =~ s/\\//gi; 
	$returned_ans =~ s/\$//gi; 
	$returned_ans =~ s/\#//gi; 
	$returned_ans =~ s/\~//gi;
	$stu_ans = eval($returned_ans);
	if ( (($stu_ans - $ans)**2  ) ge 0.01 ) 
		{print "<em>, was WRONG!</EM>
		<IMG SRC=../icons/checkno.gif>"}
		 else {print "<em>, was RIGHT! </EM>
		<IMG SRC=../icons/check.gif>"};
};
print $query->end_html;
Click Here to Exercise this code.
Here is the code repeated with line numbers pre-pended:
[1]#!/usr/local/bin/perl -- -*- C -*-
[2]use CGI;
[3]$query = new CGI;
[4]print $query->header;
[5]print $query->start_html("Perl4q1.pl");
[6]print $query->start_form;
[7]$ans = 5280;
[8]print "<P> How many feet are there in a mile?",
[9]$query->textfield('stu_ans','',10,30);
[10]print "<P> Is the above answer correct?",$query->submit("Send Answer in For Grading");
[11]print $query->reset;
[12]print $query->end_form;
[13]$returned_ans = $query->param('stu_ans');
[14]if ( $query->param('stu_ans') ne '')
[15]{
[16]	print "<em>Student_answer, </em>$returned_ans";
[17]	$returned_ans =~ s/\\//gi; 
[18]	$returned_ans =~ s/\$//gi; 
[19]	$returned_ans =~ s/\#//gi; 
[20]	$returned_ans =~ s/\~//gi;
[21]	$stu_ans = eval($returned_ans);
[22]	if ( (($stu_ans - $ans)**2  ) ge 0.01 ) 
[23]		{print "<em>, was WRONG!</EM>
[24]		<IMG SRC=../icons/checkno.gif>"}
[25]		 else {print "<em>, was RIGHT! </EM>
[26]		<IMG SRC=../icons/check.gif>"};
[27]};
[28]print $query->end_html;

and here is the code annotated and explained:
[1]#!/usr/local/bin/perl -- -*- C -*-
Line [1] is a comment, which indicates to the system where the appropriate compiler for this code is housed. The line is optional but recommended.
[2]use CGI;
Line [2] tells the compiler that we will be using CGI.pm, the library of specialized calls to WWW routines( Click Here to see Perl resources such as CGI.pm). If your system administrator has not installed CGI.pm in the correct library, or, in fact, if s/he has installed Perl in a non-traditional place, you will need help adjusting these various starting lines to fit you local situation. Just a warning, that if you use this code and it fails, there is a reasonable chance that things have been set up in a non-standard manner.
[3]$query = new CGI;
Line [3] is the first true line of Perl code, and is a specialized part of the object oriented program scheme employed by CGI.pm. For our purposes, this line is mandatory in every program using CGI.pm.
[4]print $query->header;
Line [4] starts the program's WWW code, telling the computer to write the proper header so that the WWW browsers will recognize this code.
[5]print $query->start_html("Perl4q1.pl");
Line [5] starts the HTML code generation itself, creating a document title which may appear in the browser (depends on the browser), Perl4q1.pl. Note that this title is contained between double quotes(").
[6]print $query->start_form;
Line [6] starts the form generation, i.e., the text which will constitute our question.
[7]$ans = 5280;
Line [7] is pure Perl code which has nothing to do with the WWW. It defines a variable, $ans has having the numerical value of 5,280 (no commas when one is programming!). We could have used $answer as our variable, but Unix makes one a cheapskate when it comes to keystrokes, and $a is to short, so $ans is an appropriate compromise.
[8]print "<P> How many feet are there in a mile?",
[9]$query->textfield('stu_ans','',10,30);
Lines [8] and [9] are really one line, terminating with the semicolon (as all Perl statements terminate). They are typed in in two lines for visual clarity only. Everything from the first double quote to the second one will be printed on the screen when this program is executed. the <.P> is an HTML code for making a paragraph break. HTML code word wraps, so the programmer is responsible for breaking (<br>) lines or skipping a line after breaking (<p>). These codes are case insensitive, i.e., upper and lower case are acceptable. The comma separates the text from whatever else is to be printed. In this case, we print a textfield, which is 10 characters wide (hence the 10), initially empty (hence the ''), defines a CGI variable 'stu_ans', whose maximum character length will be 30 (hence th3 30) in the call:
$query->textfield('stu_ans','',10,30);
Notice that the name stu_ans is our choice for the variable, and again we distinguish our answer and the student's, but use the fewest keystrokes possible.
[10]print "<P> Is the above answer correct?",$query->submit("Send Answer in For Grading");
Line [10] is mandatory for questions such as ours. This line shows where the student must click with her mouse in order to submit her answer for grading. The text `Send Answer in For Grading' is optional, and if omitted, will result in default behavior.
[11]print $query->reset;
Line [11] is optional.
[12]print $query->end_form;
Line [12] is mandatory, and ends the form, i.e., all of the material from start_form to end_form will be treated as a query by the WWW.
[13]$returned_ans = $query->param('stu_ans');
Line [13] defines a new variable $returned_ans which will contain the string which the student typed into the computer. The $query->param('stu_ans') code is the standard way the CGI.pm returns the values of forms to the user.
[14]if ( $query->param('stu_ans') ne '')
Line [14] starts an if (){} statement. The code between curly brackets will be executed if the statements between rounded brackets are true. In this case we ask if the student's answer is not blank. The statement:
$query->param('stu_ans') ne ''
retreives the student's answer and asks if it is not equal to the null string (the empty string), ''. All the code from Line 15 thru Line [27] will be executed if the student entered anything, but this code will be omitted if the student left the textfield empty.
[15]{
[16]	print "<em>Student_answer, </em>$returned_ans";
Line [16] shows the student what she entered. Notice that the student's returned answer, i.e., the Perl variable, is inside the doubel quotes.
[17]	$returned_ans =~ s/\\//gi; 
[18]	$returned_ans =~ s/\$//gi; 
[19]	$returned_ans =~ s/\#//gi; 
[20]	$returned_ans =~ s/\~//gi;
[21]	$stu_ans = eval($returned_ans);
Line [21] evaluates the returned answer, i.e., attempts to convert the string into a number. It puts that value into a new variable called $stu_ans, which is one of our Perl variables, not the CGI variable 'stu_ans'. It takes some getting used to that there are two sets of variables here.
 
[22]	if ( (($stu_ans - $ans)**2  ) ge 0.01 ) 
Line [22] starts a second if () {} statement, nested inside the outer if statement (which just makes sure that the student entered something). Here, we are setting the agreement level between our answer and the student's answer, i.e., demanding that they differ by no more than 0.1. Normally, we would ask that the absolute value of the difference between our answer and the student's answer be less than 0.1. Here, we take the square root of the square of the difference instead. That guarantees that the resultant difference is positive, emphasizing the idea that the student's answer can be higher or lower than our answer. Since the square root costs us computer time, we choose instead to just square the difference and compare that squared difference to 0.01 (0.1**2).
[23]		{print "<em>, was WRONG!</EM>
[24]		<IMG SRC=../icons/checkno.gif>"}
Lines [23] and [24] are executed if indeed the student's answer is not within 0.1 of our answer.
[25]		 else {print "<em>, was RIGHT! </EM>
[26]		<IMG SRC=../icons/check.gif>"};
Line [25] and [26] are executed if the difference between our answers is small enough to allow the assumption that the student is right.
[27]};
Line [27] ends the processing associated with a non-null student answer.
[28]print $query->end_html;

Line [28] signals the end of the entire Perl program, including the HTML code.
When you use this code, the Icons referred to in Lines [24] and [26] will be located somewhere else, and you need to edit their locations. Your system administrator will tell you where the standard Icons are located, and you can always find others on the World Wide Web. Just point your browser to http://www.yahoo.com and search for the word Icon.
Notice that we are `print'ing HTML code which is being interpreted by the server! Thus <img src= etc., etc.> is pure HTML.

Intentionally, we omitted commenting on lines [17] thru [20] when writing the above. Now it is time to consider them.
Hackers, when seeing a textfield, recognize an intrinsic weakness in the security which servers need. They know that they can enter pseudo code into such a textfield, and there is a chance that the interpreting program does not check for such code, affording the hacker the opportunity to infiltrate the system and execute system commands surreptitiously. Therefore, we are required (by common sense if not installation rules) to scan every incoming string and substitute out those offending symbols which might be used to obtain control of our system. We remove all backslashes, all dollar signs, all pound signs, and all tildes. We substitute blanks for them. The `=~ s' assignment is special Perl, which says substitute in the variable on the left, for the text contained in the first delimited field the text contained in the second delimited field. In our case, the delimiter is the `/', i.e., the forward slash. Thus
/text to be substituted/replacement text/
is what we have. But our replacement text is nothing, the null string, and the text to be substituted is, in our case, special symbols which must be appropriately handled. Thus, one can not just enter a backslash, since a backslash is an escape symbol which means that the next symbol should be taken literally, i.e. not interpreted. Thus two backslashes indicates that the second symbol (a backslash) should be left un-interpreted. Oh, my, this is difficult. For the time being, until you've become more expert at all this, just leave the code in and don't worry about it.
The effect of this is to replace all ``hacker'' characters with blanks, so that when we evaluate the student's expression, we have only ``legal'' characters to evaluate. If these give rise to a nonsense result, that is not our concern, in a testing environment. It is you choice whether or not to check for the existence of ``hacker'' characters, and chastise the user who submits them. I ignore them, and accept that the student answer is, a posteriori, wrong.