⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch10.htm

📁 CGI programming is the hottest stuff to look out for in this book
💻 HTM
📖 第 1 页 / 共 5 页
字号:
$add[$I]{'phone'}) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@results
= grep(!/$I/,@results);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if (!@results) { &amp;exitnone; }<BR>
}<BR>
<BR>
if (($street = $FORM{'street'}0 &amp;&amp; !@results) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;for ($I = 0; $I &lt;= $maxn; $I++) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($street eq
$add[$I]{'street'}) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push(@results,$I);
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if (!@results) { &amp;exitnone; }<BR>
} elsif ($street = $FORM{'street'}) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;@r2 = @results;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;foreach $I (@r2) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($street ne
$add[$I]{'street'}) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@results
= grep(!/$I/,@results);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if (!@results) { &amp;exitnone; }<BR>
}<BR>
<BR>
if (($city = $FORM{'city'}) &amp;&amp; !@results) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;for ($I = 0; $I &lt;= $maxn; $I++) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($city eq $add[$I]{'city'})
{<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push(@results,$I);
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if (!@results) { &amp;exitnone; }<BR>
} elsif ($city = $FORM{'city'}) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;@r2 = @results;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;foreach $I (@r2) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($city ne $add[$I]{'city'})
{<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@results
= grep(!/$I/,@results);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if (!@results) { &amp;exitnone; }<BR>
}<BR>
<BR>
if (($state = $FORM{'state'}) &amp;&amp; !@results) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;for ($I = 0; $I &lt;= $maxn; $I++) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($state eq
$add[$I]{'state'}) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push(@results,$I);
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if (!@results) { &amp;exitnone; }<BR>
} elsif ($state = $FORM{'state'}) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;@r2 = @results;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;foreach $I (@r2) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($state ne
$add[$I]{'state'}) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@results
= grep(!/$I/,@results);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if (!@results) { &amp;exitnone; }<BR>
}<BR>
<BR>
if (($zip = $FORM{'zip'}) &amp;&amp; !@results) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;for ($I = 0; $I &lt;= $maxn; $I++) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($zip eq $add[$I]{'zip'})
{<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push(@results,$I);
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if (!@results) { &amp;exitnone; }<BR>
} elsif ($zip = $FORM{'zip'}) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;@r2 = @results;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;foreach $I (@r2) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($zip ne $add[$I]{'zip'})
{<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@results
= grep(!/$I/,@results);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if (!@results) { &amp;exitnone; }<BR>
}</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
At this point, either we have successful matches that are stored
in the array <TT><FONT FACE="Courier">@results</FONT></TT>, or
we have no matches, in which case we call the <TT><FONT FACE="Courier">&amp;exitnone</FONT></TT>
subroutine. Now we can give the client the results (or lack thereof).
<BLOCKQUOTE>
<TT><FONT FACE="Courier"># If there are no matches, print a note
then die.<BR>
<BR>
sub exitnone {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;print &lt;&lt;EOE;<BR>
&lt;HTML&gt;&lt;HEAD&gt;&lt;TITLE&gt;No matches&lt;/title&gt;&lt;/head&gt;
<BR>
&lt;BODY&gt;<BR>
<BR>
&lt;h3&gt;There were no matches that fit your criteria.&lt;/h3&gt;
<BR>
&lt;A HREF=&quot;addrbk.html&quot;&gt;Go&lt;/a&gt; back to the
form to try again.<BR>
&lt;/body&gt;&lt;/html&gt;<BR>
EOE<BR>
<BR>
die;<BR>
}<BR>
<BR>
# Print all the fields of each match.<BR>
<BR>
print &lt;&lt;EOP;<BR>
&lt;HTML&gt;&lt;HEAD&gt;&lt;TITLE&gt;Search Results&lt;/title&gt;&lt;/head&gt;
<BR>
&lt;BODY&gt;<BR>
&lt;h3&gt;The entries that matched your search&lt;/h3&gt;<BR>
&lt;pre&gt;<BR>
EOP<BR>
<BR>
foreach $r (@results) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;print &lt;&lt;EOG;<BR>
<BR>
----<BR>
Name: $add[$r]{'name'}<BR>
Phone: $add[$r]{'phone'}<BR>
Address:<BR>
$add[$r]{'street'}<BR>
$add[$r]{'city'}, $add[$r]{'state'}&nbsp;&nbsp;$add[$r]{'zip'}
<BR>
<BR>
EOG<BR>
<BR>
}<BR>
print &lt;&lt;EOH;<BR>
&lt;/pre&gt;&lt;br&gt;<BR>
Thank you for using my address book.<BR>
&lt;A HREF=&quot;addrbk.html&quot;&gt;Go&lt;/a&gt; back to the
form to make another search.<BR>
&lt;/body&gt;&lt;/html&gt;<BR>
EOH</FONT></TT>
</BLOCKQUOTE>
<P>
Now we have a working front end to an address book. There are
several optimizations that could be made, but it runs quite well
for a few dozen lines. Note that this script, as is, only does
a Boolean <TT><FONT FACE="Courier">AND</FONT></TT> search on all
fields. It would be possible to make it an <TT><FONT FACE="Courier">OR</FONT></TT>
search by removing all calls to <TT><FONT FACE="Courier">&amp;exitnone</FONT></TT>
except for the last one. This way, when the program does not find
any matches, it will not die but move on to the next field. It
would also be possible to enable the end user to choose whether
to do an <TT><FONT FACE="Courier">AND</FONT></TT> or <TT><FONT FACE="Courier">OR</FONT></TT>
search by adding a pull-down menu to the form page. Then the CGI
could exit or not depending on the choice.
<P>
Now that the user can search your database for any number of criteria;
the next logical question is how to add or remove information
to the database. You could, of course, do this by hand, but it
would be advantageous to allow direct manipulation of the database
from the Web itself. Fortunately, this is not hard.
<P>
In the manipulation of the database itself is where the difference
between delimited and fixed-length record databases becomes important.
With delimited text, you have no easy way of knowing where one
record ends and another begins. Therefore, to change or delete
one record it's necessary to rewrite the entire database. So in
small databases, this is not really a big performance hit. If
your database is large enough that this becomes a problem, it
would probably be a good idea to look into using a database server.
<P>
With fixed-width field databases, however, it's not necessary
to rewrite the entire database to change a record. Because the
length of each record is known, functions like <TT><FONT FACE="Courier">seek()</FONT></TT>
and <TT><FONT FACE="Courier">tell()</FONT></TT> (or their equivalent
in your preferred language) can be used to write over only a portion
of the file, changing or deleting records.
<P>
<CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Caution</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
Enabling users to write to files is one of the most dangerous undertakings on the Web. Most Web servers are run as user 'nobody' (on systems that have distinct users). This means that the server has no special permissions to write to any file. To be 
accessible to a CGI script, a file must be world writeable, meaning that anyone with access to the server machine can modify the file in any way (including erasing it entirely). If you trust everyone on your machine (or you are the only user), this may not 
be a terrible problem. Because the name of the database file is not visible from the Web, you could hide it in some far-out directory with an unusual name, thereby providing &quot;security by obscurity.&quot; There are other solutions, however. A module 
exists for Perl called CGIWrap (<TT><A HREF="http://wwwcgi.umr.edu/~cgiwrap">http://wwwcgi.umr.edu/~cgiwrap</A></TT>), and similar modules exist for other languages. CGIWrap will execute your CGI program &quot;setuid owner.&quot; That is, the program runs 
as if it were executed by the user who owns the program. This allows you to remove write privileges for everyone but yourself. Be aware, however, that the program can now modify any file in your directory as if it were you. Therefore, it is wise to make 
very sure that your programs are secure. (For Perl users, try running the script with the <TT><FONT FACE="Courier">-Tw</FONT></TT> switch.)
</BLOCKQUOTE>

</TD></TR>
</TABLE></CENTER>
<P>
<P>
As with the front end to the searching CGI, a simple HTML form
is all that is required to enable users to directly modify your
database. Here again is our address book example:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">&lt;HTML&gt;&lt;HEAD&gt;&lt;TITLE&gt;My
Address Book&lt;/title&gt;&lt;/head&gt;<BR>
&lt;BODY&gt;<BR>
&lt;h4&gt;Fill out the form below to add an entry to the address
book&lt;/h4&gt;<BR>
&lt;FORM ACTION=&quot;add.cgi&quot; METHOD=&quot;POST&quot;&gt;
<BR>
Name: &lt;INPUT SIZE=45 NAME=&quot;name&quot;&gt;&lt;br&gt;<BR>
Phone: &lt;INPUT SIZE=45 NAME=&quot;phone&quot;&gt;&lt;br&gt;
<BR>
Street: &lt;INPUT SIZE=45 NAME=&quot;street&quot;&gt;&lt;br&gt;
<BR>
City: &lt;INPUT SIZE=20 NAME=&quot;city&quot;&gt; State: &lt;INPUT
SIZE=3 NAME=&quot;state&quot;&gt;<BR>
Zip: &lt;INPUT SIZE=6 NAME=&quot;zip&quot;&gt;<BR>
&lt;br&gt;&lt;br&gt;<BR>
&lt;INPUT TYPE=SUBMIT VALUE=&quot;&nbsp;&nbsp;Add Entry&nbsp;&nbsp;&quot;&gt;
<BR>
&lt;INPUT TYPE=RESET VALUE=&quot;&nbsp;&nbsp;Reset Form&nbsp;&nbsp;&quot;&gt;
<BR>
&lt;/form&gt;&lt;/body&gt;&lt;/html&gt;</FONT></TT>
</BLOCKQUOTE>
<P>
This form is almost identical to the one we made for searching.
The difference comes in how the data is treated by the CGI program.
In this case, the CGI script for adding an entry is actually much
simpler than the searching script. In this case, we will assume
that the database is a world writeable file.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">#!/bin/perl<BR>
<BR>
require cgi_head; # Set up the CGI environment<BR>
<BR>
while (-e &quot;datalock&quot;) { sleep 1; } # If database is
currently being<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
# modified, wait.<BR>
system(&quot;touch datalock&quot;);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#
Lock database<BR>
<BR>
open (DAT, &quot;database.txt&quot;); # open the database for
reading<BR>
while (&lt;DAT&gt;) { $line = $_; } # Read the last line of the
database<BR>
close DAT;<BR>
if ($line =~ /:/) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@field = split
(/:/, $line);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$num = $field[0];
# Get last ID number<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$num++;<BR>
} else { $num = 0; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Create
new ID number<BR>
<BR>
open (DAT, &quot;&gt;&gt;database.txt&quot;); # open the database
for appending<BR>
<BR>
# Add entry to database<BR>
print DAT<BR>
&quot;$num:$FORM{'name'}:$FORM{'phone'}:$FORM{'street'}:$FORM{'city'}:$FORM{'state'}:
<BR>
&Acirc;$FORM{'zip'}\n&quot;;<BR>
<BR>
close DAT;<BR>
system (&quot;rm datalock&quot;);<BR>
print &lt;&lt;EOF;<BR>
&lt;HTML&gt;&lt;HEAD&gt;&lt;TITLE&gt;Addition Successful&lt;/title&gt;&lt;/head&gt;
<BR>
&lt;BODY&gt;<BR>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -