#!/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.
[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;
[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:
[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:
[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.
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.