📄 ch22.htm
字号:
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 <html><head> <TITLE>Sample
Credit Form</TITLE><BR>
2 </head><BR>
3 <BR>
4 <body><BR>
5 <center><h1>Sample Credit Application Form</h1></center>
<BR>
6 <hr><BR>
7 <FORM METHOD="POST" ACTION="http://ikra.com/cgi-bin/credit.pl">
<BR>
8 First Name <INPUT SIZE=20 NAME="fname">
<BR>
9 Last Name <INPUT SIZE=20 NAME="lname">
<BR><BR>
10 Social Security Number <INPUT SIZE=12 NAME="ssn">
<BR>
11 Mom's Maiden Name <INPUT SIZE=20 NAME="mname">
<BR><BR>
12 <HR><BR>
13 <H4>Type of Cards Desired</H4><BR>
14 <INPUT TYPE="CheckBox" VALUE="VISA"
NAME="visa">VISA<BR>
15 <INPUT TYPE="CheckBox" VALUE="MCRD"
NAME="mastercard">Mastercard<BR>
16 <P><BR>
17 <HR><BR>
18 <H4>Number of Dependants</H4><BR>
19 <SELECT NAME="dependants" SIZE="1">
<BR>
20 <OPTION SELECTED>1<BR>
21 <OPTION>2<BR>
22 <OPTION>3<BR>
23 <OPTION>4<BR>
24 <OPTION>5<BR>
25 <OPTION>6<BR>
26 </SELECT><BR>
27 <HR><BR>
28 <H4>Yearly Income</H4><BR>
29 <INPUT TYPE="Radio" VALUE="1" NAME="income">0-10K
<BR>
30 <INPUT TYPE="Radio" VALUE="2" NAME="income">10-20K
<BR>
31 <INPUT TYPE="Radio" VALUE="3" NAME="income">20-30K
<BR>
32 <INPUT TYPE="Radio" VALUE="4" NAME="income">30-40K
<BR>
33 <INPUT TYPE="Radio" VALUE="5" NAME="income">40-50K
<BR>
34 <INPUT TYPE="Radio" VALUE="6" NAME="income">50K+
<BR>
35 <HR><BR>
36 <INPUT TYPE="Reset" VALUE="Clear
Form"><BR>
37 <INPUT TYPE="Submit" VALUE="Submit">
<BR>
38 </FORM><BR>
39 <BR>
40 </body></html></FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Here is the output from the <TT><FONT FACE="Courier">credit.pl</FONT></TT>
Perl script:
<P>
<TT><FONT FACE="Courier">=============================================</FONT></TT>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">SERVER_NAME = pop.ikra.com<BR>
REQUEST_METHOD = POST<BR>
SCRIPT_NAME = /cgi-bin/credit.pl<BR>
QUERY_STRING =<BR>
CONTENT_TYPE = application/x-www-form-urlencoded<BR>
CONTENT_LENGTH = 91<BR>
income is set to 5<BR>
ssn is set to 123-45-6789<BR>
lname is set to Doe<BR>
dependants is set to 4<BR>
mastercard is set to MCRD<BR>
mname is set to Jane Smith<BR>
fname is set to John</FONT></TT>
</BLOCKQUOTE>
<P>
In this output from the <TT><FONT FACE="Courier">POST</FONT></TT>
request, the <TT><FONT FACE="Courier">REQUEST_METHOD</FONT></TT>
is <TT><FONT FACE="Courier">POST</FONT></TT>, and the query string
is shown as empty! So where did all the user's input go? The input
has been pumped into the standard input of the Perl script. You
have to design your Perl script to pick the input from either
the <TT><FONT FACE="Courier">POST</FONT></TT> or <TT><FONT FACE="Courier">GET</FONT></TT>
requests automatically. Listing 22.5 illustrates how to process
both types of requests.
<HR>
<BLOCKQUOTE>
<B>Listing 22.5. The Perl script to handle </B><TT><B><FONT FACE="Courier">credit.html</FONT></B></TT><B>.
<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 #<BR>
3 # The sample script file to show difference in<BR>
4 # handling POST and GET requests.<BR>
5 #<BR>
6 #<BR>
7 $|=1; #
Flush immediately.<BR>
8 print "Content-Type: text/plain\n\n";<BR>
9 <BR>
10 <BR>
11 print "\n=============================================\n";
<BR>
12 print "SERVER_NAME = $ENV{'SERVER_NAME'}\n";<BR>
13 print "REQUEST_METHOD = $ENV{'REQUEST_METHOD'}\n";
<BR>
14 print "SCRIPT_NAME = $ENV{'SCRIPT_NAME'}\n";<BR>
15 print "QUERY_STRING = $ENV{'QUERY_STRING'}\n";<BR>
16 print "CONTENT_TYPE = $ENV{'CONTENT_TYPE'}\n";<BR>
17 print "CONTENT_LENGTH = $ENV{'CONTENT_LENGTH'}\n";
<BR>
18 <BR>
19 if ( $ENV{'REQUEST_METHOD'} eq "GET" &&<BR>
20 $ENV{'QUERY_STRING'} ne
'') {<BR>
21 $form = $ENV{'QUERY_STRING'};
<BR>
22 }<BR>
23 elsif ( $ENV{'REQUEST_METHOD'} eq "POST" ) {<BR>
24 read(STDIN,$form, $ENV{'CONTENT_LENGTH'});
<BR>
25 } else {<BR>
26 print "\n At least fill something!
I cannot work with empty strings";<BR>
27 exit;<BR>
28 }<BR>
29 <BR>
30 #<BR>
31 # Now the variable $form has your input data.<BR>
32 # Create your associative array.<BR>
33 #<BR>
34 foreach $pair (split('&',
$form)) {<BR>
35 if ($pair
=~ /(.*)=(.*)/) { # found key=value;<BR>
36 ($key,$value)
= ($1,$2); # get key, value.<BR>
37 $value
=~ s/\+/ /g; # substitute spaces for + signs.<BR>
38 $value
=~ s/%(..)/pack('c',hex($1))/eg;<BR>
39 $inputs{$key}
= $value; # Create Associative Array.<BR>
40 }<BR>
41 }<BR>
42 <BR>
43 foreach $item (keys(%inputs)) {<BR>
44 print "$item is set to $inputs{$item}\n";
<BR>
45 }<BR>
Lines 19 through 28 contain fragments of code that actually determine
where to pick up the input.</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Basically, this script handles the input for a <TT><FONT FACE="Courier">GET</FONT></TT>
request with non-empty input and a <TT><FONT FACE="Courier">POST</FONT></TT>
request with any input. At the end of this conditional, <TT><FONT FACE="Courier">$form</FONT></TT>
has the input string in a URL-encoded form. Obviously, this kind
of data handling is not acceptable in a real-life scenario. The
parsing of the incoming input to figure out if it's <TT><FONT FACE="Courier">POST</FONT></TT>
or <TT><FONT FACE="Courier">GET</FONT></TT> has to be done so
many times and in so many shell scripts that it's really a good
idea to simply write a subroutine that handles both types of processing.
Once you have such a subroutine defined, all you have to do is
simply include it in the rest of the CGI scripts to extract the
incoming parameters.
<P>
In either case, the output of the Perl script is what is sent
back to the calling browser. In other words, all the words written
to <TT><FONT FACE="Courier">STDOUT</FONT></TT> (the default if
a file handle is not specified in the <TT><FONT FACE="Courier">print</FONT></TT>
statement) are sent the browser. In fact, the output is forced
to be flushed as soon as possible with the use of the <TT><FONT FACE="Courier">$|=1</FONT></TT>
command.<P>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR VALIGN=TOP><TD ><B>Tip</B></TD></TR>
<TR VALIGN=TOP><TD >
<BLOCKQUOTE>
You have to deal with handling any errors in input. Imagine the type of input your script might receive if your user walks away from his desk and his three-year-old gets to do some typing! Always check for input into your CGI form. It's better to be safe
than sorry.</BLOCKQUOTE>
</TD></TR>
</TABLE></CENTER>
<P>
<P>
In Listing 22.5, lines 19 through 28 will parse the incoming parameters
into an associative array called <TT><FONT FACE="Courier">inputs</FONT></TT>.
Look at what you have parsed into the incoming <TT><FONT FACE="Courier">inputs</FONT></TT>
associative array from a test run. The output of what the values
that were entered in the form and sent to the script are set in
<TT><FONT FACE="Courier">inputs</FONT></TT>:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">%inputs{'income'} is set to 5<BR>
%inputs{'ssn'} is set to 123-45-6789<BR>
%inputs{'lname'} is set to Doe<BR>
%inputs{'dependants'} is set to 4<BR>
%inputs{'mastercard'} is set to MCRD<BR>
%inputs{'mname'} is set to Jane Smith<BR>
%inputs{'fname'} is set to John</FONT></TT>
</BLOCKQUOTE>
<P>
If you look at the HTML file that invoked this script, you'll
recognize some of the indices in the <TT><FONT FACE="Courier">%inputs</FONT></TT>
array. The keys used to index into the <TT><FONT FACE="Courier">%inputs</FONT></TT>
array were set in the HTML document. They have now been passed
into the Perl script for use. The<FONT FACE="AGaramond Bold">
</FONT><TT><FONT FACE="Courier">%inputs</FONT></TT><FONT FACE="AGaramond Bold">
</FONT>array now has all the values for you to work with.
<P>
Of course, you always have to check the incoming values to see
if they make sense. There are several ways to check the input
for your credit card application example. You could check if the
social security number has the right number of digits, if all
the fields were filled in, and so on. One possible way to check
the input is shown in Listing 22.7. Note how each variable is
tested for a range of values and to see if it's empty. In your
HTML pages and CGI scripts, you must check for missing or inconsistent
responses. Prepare for the worst-case scenario.
<P>
The tedious part is checking for all the possible responses that
your user can type in. Checking for non-zero responses, empty
strings, and out-of-range values takes time in execution and in
setting up tests. However, the time will be well spent if the
users of your page are not given <TT><FONT FACE="Courier">Server
Error</FONT></TT> messages, or, even worse, data on bad input
without even a whimper of an error message. This type of response
may lead to the user actually believing in the erroneous test
results.
<HR>
<BLOCKQUOTE>
<B>Listing 22.6. Checking for missing or inconsistent responses.
<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 #<BR>
3 # The sample script file to show difference in<BR>
4 # handling POST and GET requests.<BR>
5 #<BR>
6 #<BR>
7 <BR>
8 $|=1; #
Flush immediately.<BR>
9 print "Content-Type: text/plain\n\n";
<BR>
10 <BR>
11 print "\n=============================================\n";
<BR>
12 print "SERVER_NAME = $ENV{'SERVER_NAME'}\n";
<BR>
13 print "REQUEST_METHOD = $ENV{'REQUEST_METHOD'}\n";
<BR>
14 print "SCRIPT_NAME = $ENV{'SCRIPT_NAME'}\n";
<BR>
15 print "QUERY_STRING = $ENV{'QUERY_STRING'}\n";
<BR>
16 print "CONTENT_TYPE = $ENV{'CONTENT_TYPE'}\n";
<BR>
17 print "CONTENT_LENGTH = $ENV{'CONTENT_LENGTH'}\n";
<BR>
18 print "SERVER_NAME = $ENV{'SERVER_NAME'}\n";
<BR>
19 print "\n=============================================\n";
<BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -