📄 ch20.htm
字号:
data file.
<P>
While the program in Listing 20.5 works well, there are several
things that can improve it:
<UL>
<LI>Error Handling-instead of simply dying, the program could
generate an error page that indicates the problem.
<LI>Field Validation-blank fields should be checked for and warned
against.
<LI>Guest book display-visitors should be able to see the Guest
book without needing to add an entry.
</UL>
<P>
The CGI program in Listing 20.6 implements these new features.
If you add <TT>?display</TT> to the
URL of the script, the script will simply display the entries
in the data file. If you add <TT>?add</TT>
to the URL of the script, it will redirect the client browser
to the <TT>addgest.htm</TT> Web page.
If no additional information is passed with the URL, the script
will assume that it has been invoked from a form and will read
the form information. After saving the information, the Guestbook
page will be displayed.
<P>
A debugging routine called <TT>printENV()</TT>
has been added to this listing. If you have trouble getting the
script to work, you can call the <TT>printENV()</TT>
routine in order to display all of the environment variables and
any form information that was read. Place the call to <TT>printENV()</TT>
right before the <TT></BODY></TT>
tag of a Web page. The <TT>displayError()</TT>
fuNCtion calls the <TT>printENV()</TT>
fuNCtion so that the error can have as much information as possible
when a problem arises.
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Turn on the warning option.<BR>
Turn on the strict pragma.<BR>
Declare a hash variable to hold the HTML form field data.<BR>
Get the local time and pretend that it is one of the form fields.
<BR>
Get the data from the form.<BR>
Was the program was invoked with added URL information?<BR>
if the display command was used, display the Guest book.<BR>
if the add command was use, redirect to the Add Entry page.<BR>
otherwise display an error page.<BR>
If no extra URL information, check for blank fields.<BR>
if blank fields, display an error page.<BR>
Save the form data.<BR>
Display the Guest book. <BR>
Exit the program.<BR>
Define the </I><TT><I>displayError()</I></TT><I>
fuNCtion.<BR>
Display an error page with a specified error message.<BR>
Define the </I><TT><I>displayPage()</I></TT><I>
fuNCtion.<BR>
Read all of the entries into a hash.<BR>
Display the Guest book.<BR>
Define the </I><TT><I>readFormData()</I></TT><I>
fuNCtion.<BR>
Declare local variables for a file name and a hash refereNCe.
<BR>
Open the file for reading.<BR>
Iterate over the lines of the file.<BR>
Split the line into four variables using ~ as demlimiter.<BR>
Create a hash entry to hold the Guest book information.<BR>
Close the file.<BR>
Define the </I><TT><I>getFormData()</I></TT><I>
fuNCtion.<BR>
Declare a local variable to hold the refereNCe to the input field
hash.<BR>
Initialize a buffer.<BR>
If the </I><TT><I>GET</I></TT><I>
method is used, copy the form information into the buffer.<BR>
If the </I><TT><I>POST</I></TT><I>
method is used, read the form information into the buffer.<BR>
Iterate over the array returned by the </I><TT><I>split()</I></TT><I>
fuNCtion.<BR>
Decode both the input field name and value.<BR>
Compress multiple </I><TT><I><P></I></TT><I>
tags into one.<BR>
Convert </I><TT><I><</I></TT><I>
into </I><TT><I>&lt;</I></TT><I>
and </I><TT><I>></I></TT><I> into
</I><TT><I>&gt;</I></TT><I> stopping
HTML tags from interpretation.<BR>
Turn back on the bold and italic HTML tags.<BR>
Remove unneded carriage returns.<BR>
Convert two newlines into a HTML paragraph tag.<BR>
Convert single newlines into spaces.<BR>
Create an entry in the input field hash variable.<BR>
Define the </I><TT><I>decodeURL()</I></TT><I>
fuNCtion.<BR>
Get the eNCoded string from the parameter array.<BR>
Translate all plus signs into spaces.<BR>
Convert character coded as hexadecimal digits into regular characters.
<BR>
Return the decoded string.<BR>
Define the </I><TT><I>zeroFill()</I></TT><I>
fuNCtion-turns "1" into "01".<BR>
Declare a local variable to hold the number to be filled.<BR>
Declare a local variable to hold the string length that is needed.
<BR>
Find differeNCe between current string length and needed length.
<BR>
If the string is big enough (like "12") then return
it.<BR>
If the string is too big, prefix it with some zeroes.<BR>
Define the </I><TT><I>saveFormData()</I></TT><I>
fuNCtion.<BR>
Declare two local variables to hold the hash and file name.<BR>
Open the file for appending.<BR>
Store the contents of the hash in the data file.<BR>
Close the file.</I>
</BLOCKQUOTE>
<HR>
<BLOCKQUOTE>
<B>Listing 20.6 20LST06.PL-A More AdvaNCed Guestbook
<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
#! /user/bin/perl -w
#use strict;
my(%fields);
my($sec, $min, $hour, $mday, $mon, $year) = (localtime(time))[0..5];
my($dataFile) = "data/gestbook.dat";
$mon = zeroFill($mon, 2);
$hour = zeroFill($hour, 2);
$min = zeroFill($min, 2);
$sec = zeroFill($sec, 2);
$fields{'timestamp'} = "$mon/$mday/$year, $hour:$min:$sec";
getFormData(\%fields);
if ($ENV{'QUERY_STRING'}) {
if ($ENV{'QUERY_STRING'} eq 'display') {
displayPage();
}
elsif ($ENV{'QUERY_STRING'} eq 'add') {
print("Location: /addgest.htm\n\n");
}
else {
displayError("Unknown Command: <B>$ENV{'QUERY_STRING'}</B>");
}
}
else {
if (length($fields{'name'}) == 0) {
displayError("Please fill the name field,<BR>\n");
}
if (length($fields{'comments'}) == 0) {
displayError("Please fill the comments field,<BR>\n");
}
saveFormData(\%fields, $dataFile);
displayPage();
}
exit(0);
sub displayError {
print("Content-type: text/html\n\n");
print("<HTML>\n");
print("<HEAD><TITLE>Guestbook Error</TITLE></HEAD>\n");
print("<H1>Guestbook</H1>\n");
print("<HR>\n");
print("@_<BR>\n");
print("<HR>\n");
printENV();
print("</BODY>\n");
print("</HTML>\n");
exit(0);
}
sub displayPage {
my(%entries);
readFormData($dataFile, \%entries);
print("Content-type: text/html\n\n");
print("<HTML>\n");
print("<HEAD><TITLE>Guestbook</TITLE></HEAD>\n");
print("<TABLE><TR><TD VALIGN=top><H1>Guestbook</H1></TD>\n");
print("<TD VALIGN=top><UL><LI><A HREF=\"/cgi-bin/gestbook.pl?add\">Add an Entry</A>\n");
print("<LI><A HREF=\"/cgi-bin/gestbook.pl?display\">Refresh</A></UL></TD></TR></TABLE>\n");
print("<HR>\n");
foreach (sort(keys(%entries))) {
my($arrayRef) = $entries{$_};
my($timestamp, $name, $email, $comments) = ($_, @{$arrayRef});
print("$timestamp: <B>$name</B> <A HREF=mailto:$email>$email</A>\n");
print("<OL>$comments</OL>\n");
print("<HR>\n");
}
print("</BODY>\n");
print("</HTML>\n");
}
sub readFormData {
my($file) = shift;
my($hashRef) = shift;
open(FILE, "<$file") or displayError("Unable to open Guestbook data file.");
while (<FILE>) {
my($timestamp, $name, $email, $comments) = split(/~/, $_);
$hashRef->{$timestamp} = [ $name, $email, $comments ];
}
close(FILE);
}
sub getFormData {
my($hashRef) = shift;
my($buffer) = "";
if ($ENV{'REQUEST_METHOD'} eq "GET") {
$buffer = $ENV{'QUERY_STRING'};
}
else {
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}
foreach (split(/&/, $buffer)) {
my($key, $value) = split(/=/, $_);
$key = decodeURL($key);
$value = decodeURL($value);
$value =~ s/(<P>\s*)+/<P>/g; # compress multiple <P> tags.
$value =~ s/</&lt;/g; # turn off all HTML tags.
$value =~ s/>/&gt;/g;
$value =~ s/&lt;b&gt;/<b>/ig; # turn on the bold tag.
$value =~ s!&lt;/b&gt;!</b>!ig;
$value =~ s/&lt;i&gt;/<b>/ig; # turn on the italic tag.
$value =~ s!&lt;/i&gt;!</b>!ig;
$value =~ s!\cM!!g; # Remove unneeded carriage returns.
$value =~ s!\n\n!<P>!g; # Convert 2 newlines into paragraph.
$value =~ s!\n! !g; # convert newline into space.
%{$hashRef}->{$key} = $value;
}
}
sub decodeURL {
$_ = shift;
tr/+/ /;
s/%(..)/pack('c', hex($1))/eg;
return($_);
}
sub zeroFill {
my($temp) = shift;
my($len) = shift;
my($diff) = $len - length($temp);
return($temp) if $diff <= 0;
return(('0' x $diff) . $temp);
}
sub saveFormData {
my($hashRef) = shift;
my($file) = shift;
open(FILE, ">>$file") or die("Unable to open Guestbook data file.");
print FILE ("$hashRef->{'timestamp'}~");
print FILE ("$hashRef->{'name'}~");
print FILE ("$hashRef->{'email'}~");
print FILE ("$hashRef->{'comments'}");
print FILE ("\n");
close(FILE);
}
sub printENV {
print "The Environment report<BR>\n";
print "----------------------<BR><PRE>\n";
print "REQUEST_METHOD: *$ENV{'REQUEST_METHOD'}*\n";
print "SCRIPT_NAME: *$ENV{'SCRIPT_NAME'}*\n";
print "QUERY_STRING: *$ENV{'QUERY_STRING'}*\n";
print "PATH_INFO: *$ENV{'PATH_INFO'}*\n";
print "PATH_TRANSLATED: *$ENV{'PATH_TRANSLATED'}*</PRE>\n";
if ($ENV{'REQUEST_METHOD'} eq 'POST') {
print "CONTENT_TYPE: $ENV{'CONTENT_TYPE'}<BR>\n";
print "CONTENT_FILE: $ENV{'CONTENT_FILE'}<BR>\n";
print "CONTENT_LENGTH: $ENV{'CONTENT_LENGTH'}<BR>\n";
}
print("<BR>");
foreach (sort(keys(%ENV))) {
print("$_: $ENV{$_}<BR>\n");
}
print("<BR>");
foreach (sort(keys(%fields))) {
print("$_: $fields{$_}<BR>\n");
}
print("<BR>");
}
</PRE>
</BLOCKQUOTE>
<HR>
<P>
One of the major changes between Listing 20.5 and Listing 20.6
is in the <TT>readFormData()</TT>
fuNCtion. Instead of actually printing the Guest book data, the
fuNCtion now creates hash entries for it. This change was done
so that an error page could be generated if the data file could
not be opened. Otherwise, the error message would have appeared
it the middle of the Guest book page-leading to confusion on the
part of vistors.
<P>
A table was used to add two hypertext links to the top of t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -