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

📄 ch10.htm

📁 CGI programming is the hottest stuff to look out for in this book
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<HTML>

<HEAD>
   <TITLE>Chapter 10 -- Databases </TITLE>
   <META>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">
<H1><FONT COLOR=#FF0000>Chapter 10</FONT></H1>
<H1><B><FONT SIZE=5 COLOR=#FF0000>Databases </FONT></B>
</H1>
<P>
<HR WIDTH="100%"></P>
<P>
<H3 ALIGN=CENTER><FONT COLOR="#000000"><FONT SIZE=+2>CONTENTS<A NAME="CONTENTS"></A>
</FONT></FONT></H3>


<UL>
<LI><A HREF="#DatabaseInterfaces" >Database Interfaces</A>
<UL>
<LI><A HREF="#FrontEndCGIs" >Front End CGIs</A>
</UL>
<LI><A HREF="#WebIndexing" >Web Indexing</A>
<UL>
<LI><A HREF="#Indexers" >Indexers</A>
<LI><A HREF="#SearchEngines" >Search Engines</A>
</UL>
<LI><A HREF="#LargeScaleDatabases" >Large Scale Databases</A>
<LI><A HREF="#Summary" >Summary</A>
</UL>
<HR>
<P>
Databases have been intimately connected with the World Wide Web
and CGI ever since the inception of the Web. In fact, the Web
itself is an immense worldwide database, a collection of data
and resources accessible at the click of a mouse.
<P>
On a more mundane level, interaction with server-side databases
is one of the most natural applications of CGI. The end user can
submit a query through a form and have the results displayed directly
back to his or her browser.
<P>
Because real-time interaction is not usually needed for database
interaction, one of the major drawbacks of CGI (lack of persistent
connection) is avoided. In addition, because only the results
of the query are sent to the client, the size of the database
does not factor greatly in the speed of the transaction. (Anyone
who has used one of the Web searchers such as AltaVista or Lycos
can attest to this.)
<P>
Although any kind of database can be accessed via CGI, there are
a few types of databases that have become very popular on the
Web:
<UL>
<LI><FONT COLOR=#000000>Small Text Databases</FONT>-These are
the easiest to create and are useful for many small- to medium-sized
tasks. These databases are simply ASCII files with delimited or
fixed-length records. Address books, schedules, and other such
databases with limited number of entries are suited well for this
method.
<LI><FONT COLOR=#000000>Databases of the Web-A natural candidate
for Web databases</FONT> is the Web itself. Services that catalog
large portions of the Web (along with Usenet, Gopher, and so on)
are popping up with great frequency, as covered elsewhere in this
book. This can also be applied to intranets and single machines.
Indexing software like freeWais or Ice can create a database of
an entire site, which can then be accessed through CGI programs.
<LI><FONT COLOR=#000000>Large Database Servers</FONT>-Large databases
are generally stored in a database server of some sort (even if
the server is also a client, such as most common Windows-based
databases). As long as the server has some method of interface
with other programs, the information in these databases can be
accessed from a CGI program.
</UL>
<P>
In practice, Web-based databases can be some combination of these.
Each database has its own needs, and CGI programs must often be
customized to suit the needs of your particular database.
<H2><A NAME="DatabaseInterfaces"><FONT SIZE=5 COLOR=#FF0000>Database
Interfaces</FONT></A></H2>
<P>
To effectively and seamlessly merge your database with the Web,
CGIs must be used in both the front and back end of the database
interaction.
<H3><A NAME="FrontEndCGIs">Front End CGIs</A></H3>
<P>
The first thing that must be considered is how the user is going
to enter queries to the database. An HTML form is the most common
way for the user to submit information, although there are other
ways. As an example, consider an interface to an address book.
A simple form could look like this:
<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;H2&gt;Welcome to my address book&lt;/h2&gt;<BR>
To find addresses that match a certain category, fill in that
category and<BR>
then press 'submit'.<BR>
&lt;FORM ACTION=&quot;address.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 Address: &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;&lt;br&gt;<BR>
&lt;INPUT TYPE=SUBMIT Value=&quot;&nbsp;&nbsp;Submit Query&nbsp;&nbsp;&quot;&gt;
<BR>
&lt;INPUT TYPE=RESET Value=&quot;&nbsp;&nbsp;Reset Form&nbsp;&nbsp;&quot;&gt;&lt;br&gt;
<BR>
&lt;/body&gt;&lt;/html&gt;</FONT></TT>
</BLOCKQUOTE>
<P>
This form calls the CGI program <TT><FONT FACE="Courier">address.cgi</FONT></TT>.
This is the front end to the database interaction. The purpose
of the front end is to collect the data from the form, parse it,
and somehow pass the query to the database. If the database is
an ASCII text file, the front end is also the middle end and the
back end. It must do the searching, interpret the data, and then
pass the results back to client. For database servers (including
Web indexes like freeWais and Ice), the front end must put the
query into a form that the server will understand, and then pass
the query to the server. A back end CGI program must then retrieve
the results and pass them to the user. Very often in this case,
the front and back ends are contained in the same program. On
systems that support it (UNIX, Amiga, and others), this can be
accomplished with process forking. In the Windows environment,
special applications that take advantage of OLE or some other
type of inter-application communication is necessary.
<P>
To go back to the address book example, we can now construct the
CGI program that will answer the client's request.
<P>
First, we need to know the format of the database itself. A small
text-based format is sufficient for our needs. We'll use delimited
records, although fixed-length records would also work. An example
record follows:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">0:Elmer J. Fudd:555-1234:42 Jones Lane:Chuckville:CA:90210</FONT></TT>
</BLOCKQUOTE>
<P>
This format will be familiar to anyone who has ever seen a UNIX
password file. There are two drawbacks to this format. The total
of all fields cannot exceed any line length limitations on whatever
system you are using (in our case, this should not be a problem).
Also, our delimiter (a colon) should not appear in any field,
or it will look like the start of a new field. In an ideal world,
this should not be a problem for us (unless someone lived in &quot;New
York: The City&quot;). But in reality, people make typos or are
just plain malicious. Therefore, we must be aware of this potential
problem.
<P>
Now that we know the form of the database, we can begin the CGI
program to gather the information from the form. Any language
can be used to write CGIs, but in this example, we'll use Perl
for its text-handling capabilities.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">#!/bin/perl<BR>
<BR>
require cgi_head; # Get form data and print header.<BR>
</FONT></TT>
</BLOCKQUOTE>
<P>
<CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Tip</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
In all Perl CGIs in this chapter, a module called <TT><FONT FACE="Courier">cgi_head.pm</FONT></TT> is used to gather the information from the form and print the required HTML header. This module places a form entry with name <TT><FONT 
FACE="Courier">'foo'</FONT></TT> into an associative array entry with name <TT><FONT FACE="Courier">$FORM{'foo'}</FONT></TT>. There are several freely available programs for several languages to accomplish this, including CGI.pm for Perl at
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"><A HREF="http://www.perl.com/perl/CPAN/">http://www.perl.com/perl/CPAN/</A></TT>
</BLOCKQUOTE>

</TD></TR>
</TABLE></CENTER>
<P>
<P>
Now that form data has been read in, we must read in the database
itself. Because we are using a delimited database, it is easiest
to read in the entire database. A fixed-length field database
would enable us to move through the database without reading the
entire thing, but that method has its own drawbacks (the most
obvious being that the records must not exceed a fixed length).
We read in the database as a flat ASCII file and parse it line
by line using the handy Perl <TT><FONT FACE="Courier">while(&lt;FILEHANDLE&gt;)&lt;&gt;</FONT></TT>
construct.
<P>
<CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Caution</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
This example required Perl 5.001 or above because of its use of references that were not included in Perl 4 (or earlier). Perl 5 contains many enhancements and new features and is a must for any Perlphile. It is available at</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><A HREF="http://www.perl.com/perl/CPAN/">http://www.perl.com/perl/CPAN/</A></TT>
</BLOCKQUOTE>

</TD></TR>
</TABLE></CENTER>
<P>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"># First, open the database. (Which is
called 'database.txt' here.)<BR>
open (DAT, &quot;database.txt&quot;) || die &quot;Can't open the
database: $! !.\n&quot;;<BR>
$maxn = 0; # A counter for the number of entries.<BR>
while (&lt;DAT&gt;) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;chop;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;@field = split(/:/); # Split the line
into the data fields.<BR>
&nbsp;&nbsp;&nbsp;&nbsp;$n = $field[0]; # First field is an id
number<BR>
&nbsp;&nbsp;&nbsp;&nbsp;$add[$n]{'name'} = $field[1]; # Then the
name<BR>
&nbsp;&nbsp;&nbsp;&nbsp;$add[$n]{'phone'} = $field[2]; # The phone
number<BR>
&nbsp;&nbsp;&nbsp;&nbsp;$add[$n]{'street'} = $field[3]; # The
street address<BR>
&nbsp;&nbsp;&nbsp;&nbsp;$add[$n]{'city'} = $field[4]; # The city
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;$add[$n]{'state'} = $field[5]; # The state
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;$add[$n]{'zip'} = $field[6]; # The Zip
Code<BR>
}<BR>
$maxn = $n # Set the max number to the last entry</FONT></TT>
</BLOCKQUOTE>
<P>
Now that the database has been loaded, we need to compare the
user's query with the data, as shown in Listing 10.1.
<HR>
<BLOCKQUOTE>
<B>Listing 10.1. Searching an ASCII database.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">@results = (); # Zero out an array to
hold the results.<BR>
<BR>
if ($name = $FORM{'name'}) { # If the client wanted to search
a name,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;for ($I = 0; $I &lt;= $maxn; $I++) { #
Go through each entry<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($name eq $add[$I]{'name'})
{ # Looking for a match.<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push(@results,$I);
# If one is found, add its id<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#
Number to the list of results.<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if (!@results) { &amp;exitnone; }&nbsp;&nbsp;#
If no match is found, exit.<BR>
}<BR>
<BR>
# Now repeat for each criteria.&nbsp;&nbsp;If there are results
from a previous<BR>
# match, search them instead, and remove any entries that don't
match.<BR>
<BR>
if (($phone = $FORM{'phone'}) &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 ($phone eq
$add[$I]{'phone'}) {<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 ($phone = $FORM{'phone'}) {<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 ($phone ne

⌨️ 快捷键说明

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