|
by Danny Brands
In this chapter, you learn about writing Visual Basic applications
using the Common Gateway Interface for Windows (3.x, 95, NT) Web
servers. The Windows CGI standard is quite different from the
usual UNIX-type CGI, so you also look at how it works.
Visual Basic is a programming environment that's frequently used
to implement applications for Windows CGI because it's relatively
easy to learn and has many powerful built-in functions you can
use to process forms and access databases.
In this chapter, you set up a simple Windows CGI application in
Visual Basic step by step. After that, you move on to setting
up forms and decoding the data returned by the user. You also
examine database-access programming in Visual Basic and setting
up a Web-searchable phone number database. Finally, you review
server performance issues and alternative scripting languages.
In this chapter, you learn the following:
- What the Windows CGI standard is and how it differs from standard
(UNIX) CGI
- What the input and output files of Windows CGI are and how
they're decoded
- What the cgi32.bas framework is
- How to set up a Windows CGI application using Visual Basic
- How to create forms
- How to process submitted data and access a database using
Visual Basic
For this chapter, I assume that you have some Visual Basic programming
skills and that you know how to handle simple Visual Basic projects.
If you haven't used Visual Basic before, you still might want
to read this chapter and follow the examples presented and read
a good book on Visual Basic programming as soon as you start to
alter the projects for your own use. You're expected to have Visual
Basic installed on your system. Later, I discuss the preferred
version of Visual Basic you should use. The examples given here
are focused on Visual Basic, but if you have some experience with
programming environments such as Delphi, you may be able to port
the examples to those environments.
For purposes of this chapter, I also assume that you have access
to a properly configured Web server that supports the Windows
CGI standard. The scripts discussed here have been tested with
the WebSite Web server versions 1.0 and 1.1, but any other server
that runs under Windows 95 or NT and supports Windows CGI will
work.
| TIP |
You can download several try-before-you-buy versions of the Web servers. You can obtain the WebSite Web server, which runs under Windows 95 and Windows NT, from http://website.ora.com. You can even install a Web
server on a PC that isn't connected to the Internet and use the loopback IP address to access it (http://127.0.0.1). Read the documentation that comes with your Web server on how to install it on your system
|
Standard CGI was used by the pioneers of CGI to develop applications
using UNIX shell scripts and the Perl language. Data is passed
from the server to the CGI application, and vice versa, using
environment variables. The disadvantage of using standard CGI
for Web servers running under Windows is that Windows 3.x and
Windows 95 can't efficiently pass environment variables to Windows
CGI applications. Under Windows NT, in principle, it's possible
to pass environment variables in the UNIX way. However, CGI programming
with Visual Basic using environment variables is difficult because
some of the functions that are used in UNIX-type CGI applications
programmed in C are missing in Visual Basic.
The DOS CGI interface was the first attempt to make CGI applications
run with Windows Web servers. Because Windows has no basic command
interpreter, you need to rely on a DOS session to run CGI applications.
The DOS CGI application is usually a batch (.BAT) file or a DOS
executable. Data is passed to the CGI application using environment
variables. The main disadvantage of using DOS CGI, besides the
limited capabilities of batch files, is that Windows has to create
a DOS virtual machine for every CGI request. This means you can
run only a very limited number of CGI processes at the same time.
What's more, this approach reportedly results in memory leaks
that eat up your server's memory and require frequent reboots.
The Windows Common Gateway Interface (Windows CGI) was developed
by Bob Denny, author the Windows Web servers WinHTTPD and WebSite,
to overcome the limitations of DOS CGI. As mentioned previously,
Windows has no native command interpreter (Windows NT is an exception).
Therefore, the Windows CGI application needs to be a Windows executable.
In a goal to minimize programming efforts and keep the interface
simple, data from server to client, and vice versa, is passed
via input and output files instead of environment variables.
The input file is in the same format as Windows initialization
(.INI) files. You might have noticed that Windows applications
share a common file format to store setup parameters (like the
four most recently accessed files) in an .INI file. The .INI files
share the same format because Windows contains services that allow
programmers to read and write these files quickly and easily.
These services are part of the application programming interface
(API) and are usually referred to as API calls. Using the .INI
file format was a brilliant idea because most Windows CGI applications
are written in Visual Basic. Although it's a powerful programming
environment, Visual Basic contains limited and particularly slow
file read and write capabilities. The API calls allow you to read
these files quickly and reliably from within Visual Basic.
Before moving on to some CGI programming examples in Visual Basic,
let me briefly discuss the mechanisms behind Windows CGI. Suppose
that you're selling pizzas using the Internet. You want people
to log on to your Web server and order a pizza using their Web
browsers. You present users a form like the one shown in figure
21.1. A user fills in all details and submits the form.
Figure 21.1 : You can easily order a pizza online.
The user's Web browser contacts your server and submits the data
that was filled in the fields and the path of the CGI application
that handles the request. Figure 21.2 shows what happens when
the user submits the data.
Figure 21.2 : During a Windows CGI request, the server launches an application that processes an input file and sends results to an output file. The output file is subsequently sent back by the server.
After all data is sent by the user's Web browser, the server launches
the CGI application. This is done using the following command-line
syntax:
cgi-application cgi-data-file content-file output-file url-args
Here's a breakdown of the syntax:
- cgi-application This parameter is the
full path to the CGI application that's usually a Windows executable.
In practice, CGI applications are located in a separate directory.
This directory is inaccessible from the Internet, so no one can
download the executable. This directory is usually set in the
server's setup. If your Windows CGI directory is set to cgi-win,
the path could be something like c:\website\cgi-win\order.exe.
- cgi-data-file This parameter is the path
to the file containing all data concerning the request. It contains
fields submitted by the user (what size, the user's address, and
so on) and some information about the connection (the Internet
address and the type of Internet software of the user, for instance).
This data is read by the CGI application after it's launched.
The file is placed in your temporary directory.
- content-file The content file contains
any content that was submitted during the user's request. It could,
for instance, contain a file that the user uploaded. It's almost
never used by CGI programmers because it contains raw data. This
file is placed in your temporary directory.
- output-file This parameter is the path
to the output file; it's used to pass data from the CGI application
to the server. This data could be a confirmation that the order
is accepted. The server sends this data to the user, so usually
it's in HTML format.
- url-args This parameter is anything that
follows a ? (question mark) in the URL requested by the user.
If no URL argument is present, this parameter is omitted from
the command line. Some CGI database search scripts use URL arguments.
So what happens after the server launches the CGI application?
The CGI application initializes and reads the data from the input
file. Depending on the input, the application generates an output
file.
Suppose that all fields have been filled in properly by the user
and that the order can be acknowledged. The CGI application then
writes order accepted to the output file and
exits. The Web server notices that the CGI application has ended,
reads the output file, and sends the data from the output file
back to the user.
As discussed earlier, the first thing a CGI application needs
to do after it's launched is read the input file written by the
Web server. Listing 21.1 shows a typical input file.
Listing 21.1 Contents of a Typical Input File
[CGI]
Request Protocol=HTTP/1.0
Request Method=GET
Executable Path=/cgi-win/order.exe
Server Software=WebSite/1.0
Server Name=server.domain.com
Server Port=80
Server Admin=user@mailserver.com
CGI Version=CGI/1.2 (Win)
Remote Address=123.123.123.123
Authentication Method=Basic
Authentication Realm=Web Server
[System]
GMT Offset=3600
Debug Mode=No
Output File=c:\temp\59ws.out
[Accept]
image/gif=Yes
image/x-xbitmap=Yes
image/jpeg=Yes
image/pjpeg=Yes
*/*=Yes
[Extra Headers]
Connection=Keep-Alive
User-Agent=Mozilla/2.0b3 (Win95; I)
Pragma=no-cache
Host=123.123.123.123
If you focus on the [CGI] section, a couple of things
may attract your attention: One of them is Request Method.
The user requests this method to be performed by the server (GET
in this case).
As you can see, the input file contains more interesting information.
In the [Extra Headers] section, you can detect
the type of Web browser of the user. The User-Agent item
tells you that a Netscape 2.0 browser running under Windows 95
is used (Mozilla is the name that the Netscape developers use
for their browser). The user's Internet IP address is shown after
the Host item (it's 123.123.123.123 in this
case). You can use all this data in your CGI application.
Listing 21.2 shows another input file.
Listing 21.2 Input File for a User's POST
Request
[CGI]
Request Protocol=HTTP/1.0
Request Method=POST
Executable Path=/cgi-win/order.exe
Server Software=WebSite/1.0
Server Name=server.domain.com
Server Port=80
Server Admin=user@mailserver.com
CGI Version=CGI/1.2 (Win)
Remote Address=123.123.123.123
Authentication Method=Basic
Authentication Realm=Web Server
Content Type=application/x-www-form-urlencoded
Content Length=115
[System]
GMT Offset=3600
Debug Mode=No
Output File=c:\temp\5ews.out
Content File=c:\temp\5ews.inp
[Form Literal]
size=large
extra=cheese
name=Danny Brands
address=123 Main St.
phone=1-234-567
[Accept]
image/gif=Yes
image/x-xbitmap=Yes
image/jpeg=Yes
image/pjpeg=Yes
*/*=Yes
[Extra Headers]
Connection=Keep-Alive
User-Agent=Mozilla/2.0b3 (Win95; I)
Host=127.0.0.1
The input file now mentions Request Method=POST.
In this case, a user submits data, as shown in the [Form
Literal] section. As you can see, he has ordered a pizza.
The address, phone number, what kind of pizza-the information
is all there.
As mentioned previously, the input file is in the .INI file format.
If you know a little bit about Visual Basic programming, you may
know that getting the information out of this file is quite complicated
and would probably be unacceptably slow. Fortunately, Windows
contains very powerful API calls that let you read data from these
files quickly and easily. The GetPrivateProfileString
API call is used for this purpose.
Even more fortunately, Bob Denny, inventor of Windows CGI, has
released a standard Basic framework that does all file input and
output for you using these API calls. It's distributed with the
WebSite Web server. This framework, called cgi32.bas, can be found
on the accompanying CD-ROM and in your server's CGI-SRC directory.
Alternatively, you can obtain this file from the Internet at http://website.ora.com.
You just need to add this file to your Visual Basic project and
use the routines stored in it.
I mention the API call for two reasons. First, it's platform-dependent.
When you want to recompile a CGI script that works fine under
16-bit Visual Basic using the 32-bit version, you might need to
change it to the 32-bit equivalent. Second, you might want to
read something from the input file that wasn't implemented in
the cgi32.bas framework. In this case, you need to use the API
function by yourself. Look at the cgi32.bas file to see how it's
done.
For other programming environments, such as Borland Delphi and
Microsoft Visual C++ (MSVC++), common Windows CGI libraries are
available from the Internet, too. A framework for MSVC++ is distributed
with the WebSite version 1.1 Web server (installed in the \cgi-src\cppsample
directory). You can download a free trial version of WebSite from
the Internet at http://website.ora.com. Information about
Delphi Windows CGI framework components can be found at: http://super.sonic.net/ann/delphi/cgicomp/
and http://www.href.com.
In this section, you create your first CGI application, which
allows you to request a user's e-mail address and return a form,
showing that the address has been successfully submitted. Later,
you add more fields and see how to decode them.
You start by setting up the project in Visual Basic. I'm assuming
that you're using Visual Basic 4, the 32-bit version. See the
later section "Obtaining the Latest Version of Visual Basic"
for more information.
Previous versions of Visual Basic require another version of the
CGI framework (cgi.bas, which is distributed with the WinHTTPd
Web server, available from the Internet at http://www.city.net/win-httpd/).
The 16-bit version of Visual Basic 4 should work fine with cgi32.bas,
but I advise you to use the 32-bit version. (See the later section
"Server Performance Issues" for a discussion on this
subject.)
Run Visual Basic, and create a new project by opening the File
menu and choosing New. Remove all forms (if any) by opening the
File menu and choosing Remove. Next, remove all modules (if any)
in a similar way. Then open the Tools menu and choose Custom Controls
to open the Custom Controls dialog box. Make sure that you deselect
everything on the list, so you can decrease the number of modules
your project needs to load and significantly increase your CGI
application's performance. Then close the Custom Controls dialog
box.
Next, open the File menu and choose Add File; then add the file
cgi32.bas to your project. It's the basic CGI framework and should
be in your Web server's CGI-SRC directory or your current directory.
The code supplied here is tested with version 1.7 of cgi32.bas
but should work with older and newer versions as well.
| NOTE |
Be careful with the cgi32.bas file because you use it in all projects. In principle, you never need to edit this file
|
Now add a Basic file in which you can place your own code. Open
the Insert menu and choose Module to add a Basic file to the project.
Visual Basic names it Module1 for you.
| NOTE |
You should never add a form to a CGI application; it relies on input and output files and never needs to open a window during execution. A form will slow down execution of your application
|
Now you're ready to create the procedure that starts execution
after the CGI executable is launched by the server. This procedure
is called CGI_Main. When you're reviewing an existing
CGI application, you should always start looking in this procedure.
Open the code window of Module1. Make sure that you're in the
general-declarations section of Module1; then create
the CGI_Main procedure by typing the following:
Visual Basic then creates the procedure for you. In the same way,
create an Inter_Main procedure in the general-declarations
section of Module1 by typing this line:
The Inter_Main routine is used only when the script isn't
executed by a Web server, and you don't use this routine in this
project. However, cgi32.bas contains a call to the Inter_Main
subroutine, and you can't compile the project without it.
Now you can add functionality to your CGI project. First, determine
what method the users request when they launch the script. You
can access the request method using the CGI_RequestMethod
variable. This method, as discussed earlier, is either GET
or POST. You need to decide what to do on receipt of
each of these requests.
The GET method is used when the CGI script is accessed
for the first time. In this case, you send users a form to request
that they type in an e-mail address. Make sure that you're in
the general-CGI_Main procedure of Module1. Then add the
code shown in boldface in listing 21.3 (everything between the
Sub CGI_Main() and End Sub
lines).
Listing 21.3 The CGI_Main
Procedure of email.bas
Sub CGI_Main()
If CGI_RequestMethod = "GET" Then
SendReQuest
Exit Sub
End If
End Sub
This code results in the SendReQuest procedure being
called when the user requests the GET method. In this
procedure, you generate an HTML document.
Next, add the SendReQuest procedure. In the general-declarations
section of Module1, enter all the code shown in listing 21.4.
(Visual Basic creates the SendReQuest procedure for you
after you type the Sub SendRequest line.)
Listing 21.4 The SendReQuest
Procedure of email.bas
View Code
Next, the contents of the SendRequest procedure will
be discussed. You may have noticed that you use the Send()
routine to write data to the output file; this routine is defined
in the cgi32.bas framework. The SendRequest procedure
begins with the following line:
Send ("Content-type: text/html")
The users' Web browsers need to know what kind of data is being
sent. In this case, you send HTML, but you could also send a GIF
picture, a sound file, a binary executable, and so on, as long
as you indicate this with the correct content-type. If you forget
to include a content-type HTML statement, an error is generated.
Starting an HTML page with a title is a good custom. The title
is shown on the title bar of the users' Web browsers after the
HTML document is loaded. The title is added with the following
code:
Send ("<HTML><HEAD><TITLE>")
Send ("Please fill in your e-mail address.")
Send ("</TITLE></HEAD>")
To set up a form in HTML that can be submitted to a server, you
need to specify the FORM METHOD, which tells
the users' Web browsers what method to request. In this case,
the users' Web browsers perform a POST request. What's
more, you see what action will be performed. The users contact
the server and request it to execute the email.exe file (your
CGI executable). You could specify the full URL to your server,
too, but you would have to change the script when you move it
to another server. The way the URL is specified now, the user's
browser will fill in the rest of the URL. In this case, the following
is used:
| NOTE |
This line contains two double quotation marks. In Visual Basic, quotation marks have a special meaning. If you specify two double quotation marks, Visual Basic ignores the first and regards the second as a plain text quotation mark. For instance,
METHOD=""POST"" results in METHOD="POST" being sent to the users
|
Next, you create an input field in which the users can fill in
their e-mail addresses:
The input field is 30 characters wide and is described by the
identifier EMailAddress. You can add several other options,
which are discussed later. For now, you can be satisfied with
this simple field. The only thing you need to add is a Submit
button:
Notice that this button is another input type. The caption put
on the button is determined by the VALUE variable; in
this case, the caption is "Submit".
Ending the HTML form with the proper syntax is a good custom:
Send ("</FORM>")
Send ("</BODY></HTML>")
Now you can save your project and prepare the CGI executable.
Save the project by opening the File menu and choosing Save Project.
Save Module1 (the module you added to the project) as email.bas
and the project as email.vbp. You can save these files in a separate
directory or in your server's CGI-SRC directory.
Next, compile the .EXE file by opening the File menu and choosing
Make Exe. Name the executable email.exe and place it in your server's
cgi-win directory or any other directory that's enabled for Windows
CGI. This directory is usually set during the install procedure
of your server but can be changed afterward (consult your server's
manual).
Now, you can access the CGI executable using your Web browser.
Point your Web browser to the following URL:
http://your.servers.address/cgi-win\email.exe
Replace your.servers.address with the Internet address
of your Web server; if you run your Web browser and server on
the same machine, you can use the loopback IP number: 127.0.0.1.
(If your machine isn't connected to the Net, you do need
to use the loopback IP number.) Make sure that you use a back-slash
(\) in the path name; many problems arise from using a forward
slash (/) instead. If everything goes well, you end up with a
form as shown in figure 21.3.
Figure 21.3 : After running the email.exe application with a web browser, the results should look like this.
| Troubleshooting |
I pointed my Web browser to the CGI script but nothing happened. What's going wrong?
Don't panic yet. First, make sure that your Web server is running and that you've supplied the correct URL for your server. If you run the server and the Web browser on the same PC, you can use the loopback IP number (127.0.0.1) as the IP address. That you
can access normal HTML files on the server is a good indication that you have the right IP address and that your server is properly running.
Then convince yourself that you've placed the email.exe file in a directory that's enabled for Windows CGI applications. You can't run CGI applications from standard HTML directories on the server (such as \htdocs). Files in HTML directories are read by
the server; CGI applications are executed, which is why a special directory needs to be configured for Windows CGI files. Generally, this directory is called \cgi-win.
I have the impression that the application runs okay, but the server complains about Empty output from CGI program.
You can't place a Windows CGI executable in a standard CGI directory. The server uses a different method for launching these types of CGI applications. Whether a directory is enabled for Windows or standard CGI is set in your server's setup, so you should
consult your server's manual on this matter.
With most Web servers, precompiled CGI executables are distributed. If you can run these files, chances are high that something is wrong within your Windows CGI executable.
If you can run other CGI executables, you should check whether the version of your cgi32.bas file is recent. These scripts have been tested with version 1.7, but should in principle work with older and newer versions. Anyway, trying a newer version can't
hurt. Recent versions of cgi32.bas are distributed with the WebSite Web server, which you can obtain from the Internet at http://website.ora.com. Most problems with Visual Basic CGI scripts arise from the fact
that people use the outdated cgi.bas instead of the newer cgi32.bas file in the 32-bit Visual Basic 4 environment. cgi.bas uses calls to the 16-bit Windows API, so you can't compile applications that use cgi.bas in the 32-bit VB 4 environment. You should
remove the cgi.bas file and replace it with a recent version of the cgi32.bas file.
If your Web server has been set up properly but the problem lies within your Visual Basic CGI application, you'll probably receive an error message after accessing the application with your Web browser. You can then try to solve the problem using this
information
|
| TIP |
Sometimes, errors occurring within your Visual Basic program are difficult to trace. Because the CGI application is called by the server, running your application from within the Visual Basic design environment isn't particularly useful. You can add the
following line to the start of the CGI_Main procedure:
MsgBox("Hello World!")
When you compile the CGI application and execute it, a small box with the message Hello World! Will appear on the server PC. The application halts on this line until you click OK. You can move the MsgBox line through your
application until the error is generated before the box pops up. With a little experience, you can easily track down the line that generates the error
|
After the users receive the form shown in figure 21.3, they can
fill in their e-mail addresses and click the Submit button. However,
you haven't yet written code to handle the POST request
that will be generated after the users submit the form.
Now you can get back to the Visual Basic design environment and
add code for the POST request method. In the email.bas
module, change the CGI_Main procedure as shown in boldface
in listing 21.5.
Listing 21.5 The Revised CGI_Main
Procedure of email.bas
Sub CGI_Main()
If CGI_RequestMethod = "GET" Then
SendReQuest
Exit Sub
Else
SendResponse
Exit Sub
End If
End Sub
The SendResponse procedure handles the POST
requests. Next, enter the SendResponse procedure as shown
in listing 21.6.
Listing 21.6 The SendResponse
Procedure of email.bas
Sub SendResponse()
Dim Email as String
Email = GetSmallField("EMailAddress")
Send ("Content-type: text/html")
Send ("")
Send ("<HTML><HEAD><TITLE> Thanks!")
Send ("</TITLE></HEAD>")
Send ("Thank you for submitting your e-mail address!")
Send ("<br>")
Send ("We have registered: " + Email)
Send ("</FORM>")
Send ("</HTML>")
End Sub
The following line is meaningful because it shows how you can
read fields from the form that has been submitted by the users
by using the GetSmallField() function, which is part
of the cgi32.bas framework:
Email = GetSmallField("EMailAddress")
The GetSmallField() function is called with the name
of the field as an argument. You might have noticed that EMailAddress
is the name of the input field that you specified in the SendRequest
subroutine:
The variable Email is sent back to the users afterward
using the following code (note that you've previously declared
the Email variable by using a Dim statement):
Send ("We have registered: " + Email)
Save and compile your project and run the CGI application by pointing
your Web browser to the correct URL as you've done before. Then
type something in
the e-mail field and click Submit. If everything
goes well, you see a response like the one shown in figure 21.4.
Unlike what the result shows, you have, of course, not registered
anything at this point.
Figure 21.4 : Filling in an e-mail address and clicking the submit button results in this screen.
In this section, you continue with some more advanced forms. You
use your existing e-mail project and edit the SendRequest
procedure. In addition to the e-mail addresses, you need to query
users for their names, gender, locations, and what actions they
want to have taken (to be added to your mailing list, to be sent
more information, to be called). You see how to set up prefilled
fields, select boxes, radio buttons, check boxes, and hidden fields.
You start by editing the SendReQuest procedure in email.bas.
Edit the procedure so that it looks like listing 21.7. Alternatively,
you can load the file email.vbp project from the CD and follow
changes made starting from the existing e-mail application.
Listing 21.7 email.vbp: The Revised SendRequest
Procedure of email.bas
View Code
The first thing you added here is a prefilled field:
The VALUE keyword places text in the input field that
can be useful to suggest what users should fill in there.
After that, you set up some radio buttons by using INPUT
TYPE="radio". Radio buttons are used to let
users choose one out of several options. If you want to group
a couple of buttons, you should use the same NAME for
all of them. If you want to set up two separate groups of radio
buttons, you need to use a different NAME for the members
of each group. The variable, specified by the identifier NAME
(Male_or_Female, in this case), contains the VALUE
of the radio button checked by the users. The following code results
in male and female radio buttons:
If the users don't check any of the buttons, the NAME
identifier will be absent, and trying to decode it using the GetSmallField()
function generates an error. You learn more about this situation
when you decode these fields later in the section "Advanced
Forms Decoding."
Another way of letting users pick one out of several options is
by using a select box. This method is particularly useful when
you have several options to choose from and you want your form
to stay readable and compact. You can set up a select box for
selecting where the user lives, as follows:
Send ("<p>")
Send ("Where do you live?")
Send ("<SELECT NAME=""Continent"">")
Send ("<OPTION SELECTED>North America")
Send ("<OPTION>Europe")
Send ("<OPTION>Other")
Send ("</SELECT> ")
The select box is identified by NAME=""Continent""
and is filled with options using the OPTION keyword.
Only three options are used here, but you can use virtually as
many options as you like. When you're finished filling the select
box, you use the /SELECT keyword. (Note that one option
uses the SELECTED keyword. This option is the default;
it shows up as preselected.)
Sometimes, you want the users to choose more than one of the available
options. In this situation, use check boxes to let users choose
from several actions-being added to a mailing list, being sent
more information, and being called:
The check boxes all have the same identifier, "Action".
This variable contains the VALUE that has been specified
for a box checked by the users. Because the users can check more
than one box, the identifier is enumerated. Therefore, if the
users check all boxes, you see the identifiers Action,
Action_1, and Action_2, which all have to be
decoded separately by your CGI application.
Sometimes, you might want to add something to a form that users
can't see-for example, an account number, the number of pizzas
ordered, and so on. You can add this information by using hidden
fields that aren't shown to the users but can be decoded when
they submit their forms. Just to illustrate how hidden fields
work, add the current time. You might use this information to
store the time the form was requested by a user:
For now, save your project, compile the executable, and run it
by using your Web browser. If everything goes well, you get a
form like the one shown in figure 21.5. Note that the name field
is prefilled with the value you specified, the select box shows
the option you preselected, and the time field isn't shown.
Figure 21.5 : After you run the email.exe application, the resulting page should look something like this.
Decoding radio buttons, select boxes, and especially check boxes
needs special attention. If you request to decode a non-existing
field by using the GetSmallField() function, an unknown
field error is generated, and a response like the one in figure
21.6 is shown.
Figure 21.6 : This figure shows a typical result of an error generated by a CGI script.
A radio button field can also be non-existing when it hasn't been
clicked. You see how you can trap these errors using the VB On
Error statement later.
Start by editing the SendResponse procedure as shown
in boldface in listing 21.8. Alternatively, you can load the email.vbp
project from the CD and follow the code.
Listing 21.8 email.vbp: The Updated SendResponse
Procedure of email.bas
View Code
The first thing that may attract your attention is the way you
decode the radio buttons:
On Error Resume Next
Male_or_Female = GetSmallField("Male_or_Female")
On Error GoTo 0
You previously learned that the radio button field is non-existing
when not touched by the users and that the GetSmallField
function generates an error on a non-existing field. Therefore,
you need to use error trapping. The On Error
statement traps the error and performs a task specified behind
the statement. So if the following line generates an error,
Male_or_Female = GetSmallField("Male_or_Female")
the program discards this line and continues with the execution
of the next line as specified in the On Error
statement. The variable Male_or_Female then stays empty.
The following line resets the error handler:
The cgi32.bas framework also contains error-handling routines,
so resetting the error handler to its defaults is a good idea.
The select box is decoded quite easily, similar to the normal
input fields:
Continent = GetSmallField("Continent")
The check boxes are also decoded in a special way. Depending on
the number of checked boxes, more or fewer Action fields are enumerated
(Action, Action_1, Action_2, and so
on). You can't predict how many fields there will be; the number
of fields depends on the number of checked boxes. Because you've
seen that decoding a non-existing field generates an error, you
need to use error trapping here, too. You can construct a Do
Loop in which you sequentially read Action,
Action_1, Action_2, and so on until the GetSmallField()
function generates an error (on a non-existing field). You then
trap the error in the Done_Decoding routine. This then
does a Resume call to the Done_Decoding1 routine,
which restores the error handler:
This approach may seem impractical at first sight; however, it
works well, and there's no other simple way to do it as reliably
as this. Notice that you're constructing a phrase inside the Do
Loop that contains the actions the users requested.
The hidden field is read by using a normal GetSmallField()
call:
Your_Time = GetSmallField("Time")
All data that has been decoded is then sent back to the user,
as follows:
You use the <pre> HTML tag to align the output
properly.
Now that you've finished editing the SendResponse procedure,
save your project, compile it, and run it. Submitting a form of
the e-mail project results in a response like the one shown in
figure 21.7.
Figure 21.7 : After the user fills in some fields of the form generated by the email.exe application and clicks the Submit button, this is how a response might look.
One main advantage of using Visual Basic for writing Windows CGI
applications is that it has powerful data-access capabilities.
Visual Basic can access almost any database. It can access Btrieve,
dBASE, Microsoft Excel, and Microsoft Access databases directly
and many other database formats by using an ODBC (Open Database
Connectivity) driver. So if an ODBC driver is available for your
database, you can access it by using Visual Basic. You can even
access databases over a network, such as SQL Server and other
high-performance (UNIX) databases.
You would want to set up a Web-searchable database for many reasons.
Suppose that you have a large database you want to make accessible
for all people in your company. Because the employees probably
work with several different computer platforms (such as PC, Mac,
and UNIX), you need to have client applications developed for
every platform that they use. Even if you succeed in getting an
application for every platform, you may spend tens of thousands
of dollars on obtaining software licenses, hiring programmers,
and so on. Why not write a CGI script that accesses your database?
Free Web browsers are available for every computer platform. A
Web server shouldn't cost very much, nor should the PC it runs
on either. If the information in the database is confidential,
you can restrict access to your database from the outside world
by using IP filtering or a user name/password combination. This
is discussed later in the section "Security Concerns and
Restricting Access to Your CGI Scripts."
In this section, you set up a Web-searchable database in Visual
Basic by using the Windows CGI interface. This application allows
you to search and display the contents of a phone number database.
If you own a company, you might want to set up such a database
to allow customers to find phone numbers (and e-mail addresses)
of your employees. To keep things compact and understandable for
this example, I have set up the application without using fancy
HTML. However, after you understand the idea behind it, you can
always enhance the look of it yourself.
This application uses features that aren't supported by the standard
edition of Visual Basic, so you need the professional or enterprise
edition of VB4. Alternatively, you can use the professional edition
of VB3.
First, you need a database. It should contain a few records with
names, phone numbers, and e-mail addresses to illustrate how data
access works with Visual Basic. In principle, you can use one
of the database flavors mentioned earlier or a database for which
you have an ODBC driver. In this example, I used an Access 2.0
database, but I discuss where you should alter the code for use
with other databases.
You can obtain the database needed for this example in two ways:
- Copy the phone.mdb database from the CD into your server's
cgi-win directory. You can't use the database straight from the
CD because the database engine needs to be able to write to the
database.
- Create the database using Microsoft Access. Note that you
need to do this only if you can't copy the database from the CD.
For purposes of this example, I'm assuming that you're using Access
2.0, although other versions of Access work similarly.Start Access.
Then create a new database by opening the File menu and choosing
New Database. Name the database phone.mdb and situate it in your
server's cgi-win directory. Click the New button while the Table
tab is activated and then choose New Table. A table is then created.
Now add three new fields by typing the names Name, Phone_Number,
and Email_Address into three separate Field Name cells.
The data type needs to be Text for all fields (which is the default).
Next, close the table and choose Yes after being asked to save
the table. Name the table My_Table, and if you're asked
for it, choose to create a primary key.Use the Open button while
the Table tab is activated to open the table and start adding
names, numbers, and e-mail addresses. Your database should look
something like figure 21.8. At this point, you've created a database
called phone.mdb, which contains the table My_Table with the text
fields Name, Phone_Number, and Email_Address.
Figure 21.8 : After you've successfully created a database using Access 2.0, the results should look something like this.
Now that you have your database, you can start writing the data-access
application. The first part of it is similar to the e-mail application
you created previously.
Open Visual Basic. Then open the File menu and choose New to start
a new project. If you have any forms, remove them by opening the
File menu and choosing Remove File. Do the same for modules (if
any). Then open the Tools menu and choose References. In the References
dialog box, deselect the MS DAO 3.0 Object Library item, select
the MS DAO 2.5 Object Library item, and close the dialog box.
This is to ensure that VB uses the proper database engine.
Add the cgi32.bas framework to your project by opening the File
menu and choosing Add File. The cgi32.bas should be in your Web
server's cgi-src directory.
Next, add the module that contains the data-access code. Open
the Insert menu and choose Module to add the module. Visual Basic
names it Module1. As with the e-mail application, add an Inter_Main
procedure by typing the following in the general-declarations
section of Module1:
Then, in the general-declarations section of Module1,
add the code shown in listing 21.9.
Listing 21.9 phone.vbp: The CGI_Main
Procedure of phone.bas
Sub CGI_Main()
If CGI_RequestMethod = "GET" Then
SendReQuest
Exit Sub
Else
SendResults
Exit Sub
End If
End Sub
When the users access the CGI script for the first time using
a GET request method, the SendReQuest procedure
is executed. This procedure generates a form. When the users submit
a query using the POST request method, the SendResults
procedure is called; it contains the actual data access code.
Next, add the SendReQuest procedure to Module1 as shown
in listing 21.10.
Listing 21.10 phone.vbp: The SendRequest
Procedure of phone.bas
View Code
The SendReQuest procedure generates a form with a 30-character-wide
input field named query. Because this example is essentially the
same as the e-mail example, you can quickly move on to the actual
search procedure called SendResults. Enter the code shown
in listing 21.11.
Listing 21.11 phone.vbp: The SendResults
Procedure of phone.bas
View Code
Now you have all you need to search a database in Visual Basic
and send back the results to the users. Simple, isn't it? Because
you might want to set up your own Web-searchable database, I explain
all code used here. If you understand how this code works, you
can adapt it for use with your own database.
The SendResults routine starts with decoding the query
field:
query = GetSmallField("query")
Then it includes some lines of HTML to generate a response form:
For your users' convenience, you repeat the query that has been
submitted:
Next, you open the database by using the Visual Basic OpenDatabase()
function. It has the following syntax:
Set db = OpenDatabase(dbname[, exclusive[, read-only[, source]]])
Here's a breakdown of the parameters:
- db This is the name of an object that
has been declared as a database object with a Dim statement.
- dbname This string contains a path or
a network path to a database that Visual Basic supports directly
or a name of an ODBC data source.
- exclusive This Boolean value determines
whether the database is opened as exclusive-that is, whether other
applications are allowed to open the database at the same time.
In general, you should set the exclusive value to False
because it allows more than one user to search your database at
the same time.
- read-only This Boolean value determines
whether the database is to be opened with read/write or read-only
access. You should set this value to False unless you
want to alter the database with your CGI application.
- source This string contains any additional
information that's needed to open the database. This information
could be a logon name, a password, and so on. If you leave the
dbname string empty and set the source string
to "ODBC", a dialog box appears in which you
can browse for a registered ODBC data source. This feature is
particularly useful when you experience problems while opening
a database with an ODBC driver. The documentation that comes with
a particular driver should provide you more information on how
to open such a database.
For this example, the following line is used to open the database:
Set Db = OpenDatabase("cgi-win\phone.mdb", False, True)
Db has been previously declared using a Dim
statement:
Because you situate the database phone.mdb in the server's cgi-win
directory, you use the following path to it: "cgi-win\phone.mdb".
If you experience problems, you should change it to the full path,
which may look like the following:
"c:\website\cgi-win\phone.mdb"
The full path, of course, depends on your setup. You don't have
to place the database in your server's cgi-win directory. It works
as long as you supply the correct path. You can also use a database
file from another PC on your network. You should specify it as
follows:
"\\server\directory\database.mdb"
Notice in the example that the database is opened in non-exclusive
and read-only modes. By using these modes, you allow other applications
to open the database and multiple users to use your Web-searchable
database concurrently. Because you're only searching and not altering
the database, opening the database in read-only mode is safe.
The source string is omitted in this case because the
database needs no additional information to be opened. As you
learned previously, you probably need to specify this string only
when you're using an ODBC driver.
After you open the database, you need to search for the terms
that the users have submitted. You can do so in a couple of ways
in Visual Basic, but here you use an SQL query. In this case,
the following SQL query is used:
SELECT * FROM MY_Table WHERE Name like '*query*'
This query tells the VB database engine to select every record
in table My_Table for which the Name field contains the string
query.
The * (asterisk) wild card before and after the query string make
the database engine search for substring matches. This means that
the query selects all records that contain the query string, not
just the ones that exactly match it. So if you search for '*fred*',
not only does the database engine select records matching Fred,
but it also selects Alfred and Frederique. Similarly,
you can also use ? and # as single-character and single-digit
(0-9) wild cards, respectively. By default, SQL queries in VB
are case-insensitive. However, some ODBC drivers are case-sensitive.
| NOTE |
SQL in Visual Basic varies slightly from ANSI (standard) SQL. If you're using an ODBC driver or direct ODBC.DLL API calls, you might need to use the ANSI equivalent of the wild cards mentioned here:
|
| Visual Basic SQL
|
ANSI SQL Equivalent |
| ? |
_ (underscore)
|
| * |
%
|
The single quotation mark (') has a special meaning in
Visual Basic. You use it to add comments within your Visual Basic
source code. Because you need the quotation mark for the SQL query,
you precede it with a double quotation mark. You can see how that's
done as you store the SQL query in the string SQLQuery
(the query variable contains the name submitted by the user):
If you want to use your own database, you can make changes to
My_Table and Name to let the database engine search the correct
table and field names.
Next, the SQL query is executed by using the CreateDynaset
method:
Set tmpDyna = Db.CreateDynaset(SQLQuery)
The tmpDyna object variable was earlier declared as Dynaset:
A Dynaset is a dynamic part of the database that matches
the criteria of the SQL query. You first check whether the search
returns anything by using the RecordCount method. If
the Dynaset contains no matching records, you send a
short message that the search failed:
If the Dynaset isn't empty, you read the Dynaset
record by record by using the MoveNext method within
a Do Loop. The Do Loop is
aborted as soon as the end of the Dynaset is reached.
This is done by reading the EOF property of the Dynaset,
which is True after the last record is read:
In each cycle of the Do Loop, all three fields
(Name, Phone_Number, and Email_Address) for the current record
are read by calling the Dynaset tmpDyna with
the name of the field as an argument. (If you use another database,
you should, of course, change Name, Phone_Number, and Email_Address
to the correct field names.)
You're now finished with the phone Web-searchable database. To
save your project, open the File menu and choose Save Project.
Name your project phone.vbp and name Module1 phone.bas.
Then open the File menu and choose Make EXE File to compile your
project. Name your project phone.exe and place it in your
server's cgi-win directory. (You can also find the project file
phone.vbp and the BASIC file phone.bas on the CD-ROM that comes
with this book.)
Run phone.exe by pointing your Web browser to the following URL:
http://your.servers.address/cgi-win\phone.exe
Replace your.servers.address with the Internet address
of your server; or, if you run your Web browser on the same machine
the Web server resides on, you can use the loopback IP number
127.0.0.1. (If your machine isn't connected to the Internet,
you do need to use the loopback IP number.)
Your completed Web-searchable phone number database should look
something like figure 21.9 on your Web browser.
Figure 21.9 : The phone.exe CGI application generates a form like this.
Now type something in the field and click Search. The results
of a search for the letter a are shown in figure 21.10.
All names that contain an a are listed. You also can type
a name such as Paul or Carl, but this example better illustrates
how the application searches for substrings.
Figure 21.10 : After you search for a with the phone.exe application, the results should look something like this.
| Troubleshooting |
I received the error message Couldn't find file 'cgi-win\phone.mdb'. (error #3024). What's going on?
This message tells you that the path specified in the line containing the OpenDatabase statement in procedure SendResults of phone.bas is incorrect.You should change cgi-win\phone.mdb to the full path of your database.
When I try to compile the phone.vbp project, a User defined type not defined error is generated. During execution of the script, an Error Loading DLL message is
generated. What's happening?
The references to the Visual Basic data object libraries are incorrect. Open the File menu and choose References. From the References dialog box, deselect MS DAO 3.0 Object Library and select MS DAO 2.5 Object Library. Depending on the type of database,
you might need to select the Microsoft 2.5/3.0 Compatibility library item.
I've specified the correct path to the database, but the application still refuses to run. What more could be wrong?
If you've specified the correct path to the database and your database application still refuses to access the database, you should make sure that the Visual Basic runtime libraries for data access have been properly installed on the server PC. Even if you
know what files are needed, it's not enough to just copy them to your server's hard disk.
You can, of course, install another copy of VB on the server, but there's an easier way. You can use VB's Setup Wizard to prepare installation floppies with all the libraries you need. If you select phone.vbp as the project, the Setup Wizard includes all
data-access libraries, and the setup.exe file that's generated installs these libraries when executed on the server PC.
If you're using an ODBC driver, make sure that you've configured it as prescribed in the documentation that's supplied with the driver.
By default, Visual Basic 3 can't use the Access 2.0 database supplied on the CD-ROM because it supports only the Access 1.0 and 1.1 database formats. However, after the release of Access 2.0, Microsoft released a compatibility layer that allows Visual
Basic 3 to use Access 2.0 databases. If you have access to the Internet, you can download the compatibility layer from Microsoft's Web site at http://www.microsoft.com. You can also contact your local Microsoft
dealer
|
In addition to the risks related to exposing (part) of your network
to the outside world (that is, by setting up a Web server), running
CGI scripts on your server requires special attention. How vulnerable
your setup is depends largely on your application.
Sending confidential information over a public network is always
risky. You don't want to have customers submit their credit-card
numbers unprotected over the Internet. Computer hackers can easily
get hold of this information. Fortunately, S-HTTP (Secure HTTP)
and SSL (Secure Sockets Layer) standards have been developed,
so you can securely transport data over a public network. Many
Web browsers and UNIX Web servers already support these transactions.
The professional edition of Website version 1.1 also supports
secure transactions.
In some cases, you may want to restrict access to your CGI application.
If your database contains confidential information, you can restrict
access in several ways.
One effective way to restrict access is to place your CGI executable
in a protected directory on your server. See your Web server's
manual for information on setting up restricted directories. Restricting
access to a directory can be done on the basis of two criteria:
IP number or a user/password combination.
Restricting access on the basis of IP number-that is, allowing
ranges of IP numbers or certain IP numbers access (also called
IP filtering)-is particularly useful when you want to allow
a large group of people access to your CGI application. Because
users can't forget or lose their IP number (it's determined by
their Internet connection), this method can be pretty secure.
Users like this kind of access restriction because they never
even notice that it's there (unless they're disallowed access,
of course). The disadvantage of IP filtering is that, when users
are connected through dial-up accounts, their IP numbers could
be dynamically assigned. In other words, IP numbers may change
slightly each time the users dial into their service providers.
You can also use the IP number within your CGI application. The
CGI_RemoteAddr variable contains the IP address of the
user. You can use this variable to enable parts of your CGI application
for some users and disable it for others. You might want to allow
employees from within your company to change their phone numbers
in the corporate database and restrict outside users to searching
it.
Restricting access by using a user/password combination is another
way of preventing unwanted use of your application. When users
access a restricted directory, the Web browser presents a dialog
box asking for their user/password combination. When the users
submit their user/password combination, their browsers store this
information and submit it with every new request to a file in
the same (protected) directory. Therefore, users have to type
their user/password only once. Remember that the logon/password
is sent over the network in a way that's relatively easy to intercept,
unless you're using some kind of secure connection (S-HTTP, SSL).
You also can use the logon name and password in your CGI application.
The CGI_AuthUser and CGI_AuthPass variables
contain, respectively, the logon name and the password that have
been submitted by the users. As with the IP number, you can allow
and disallow certain functionality of your CGI application for
certain users. Note that the CGI_AuthUser and CGI_AuthPass
variables contain something only when your CGI application is
in a protected directory. Furthermore, most Windows-based Web
servers pass these variables to the CGI application only when
the name of the CGI application starts with a dollar sign ($).
You should take care of a number of things when setting up a Web
server with CGI functionality. First, CGI applications belong
in a special CGI directory. This directory is specified in your
server's setup. Windows CGI executables should be in a directory
that's enabled for the Windows CGI standard. When you place your
CGI executable in a directory meant for HTML, users can download
it, reverse-engineer it, and do all kinds of nasty things. If
your CGI executable is in a properly configured CGI directory,
users can only execute it, not download it.
Several Web browsers can upload files, and the capability to handle
these files is being implemented in many Web servers. File handling
is usually done on the server side using a CGI application. Uploading
files, however, exposes your server to some security hazards.
First of all, users can upload some really huge files, filling
a partition on your hard disk. More serious is the possibility
that hackers can upload a CGI application to your server and subsequently
execute it by accessing it with their Web browsers. CGI applications
that accept uploaded files should therefore preferentially be
in a protected directory and uploaded files should be placed in
a separate upload directory that's invisible from the outside
world.
Visual Basic 4 was released a couple of months after Windows 95
in 1995. It's the first version of Visual Basic that lets you
develop true 32-bit applications that can use the new features
of the Windows 95 and Windows NT (Win32) operating systems. Besides
that, the professional and enterprise editions of Visual Basic
4 also compile 16-bit Windows applications that can run under
the Win16 (Windows 3.x) environment.
Visual Basic 4 comes in three versions: standard, professional,
and enterprise. The standard version contains the basic functionality
of the Visual Basic development environment. You are, however,
strongly advised to buy the professional edition. It contains
additional database functionality that's frequently used in CGI
projects. You must decide whether you want to spend the extra
money for the enterprise edition, which is meant for managing
large projects with multiple programmers.
The sample applications discussed in this chapter have been tested
with the professional edition of Visual Basic 4. The phone database
doesn't run with the standard version of Visual Basic 4.
You're encouraged to use the 32-bit version of Visual Basic 4;
the examples presented in this chapter are meant for that version.
The main advantageof the Win32 over the Win16 environment is that
Win32 applications pre-emptively multitask. Pre-emptive
multitasking means that the operating system (Windows) assigns
processor time to all processes. Win16 applications cooperatively
multitask, which means that when you run a Win16 task, all
other tasks stop functioning until the task ends or returns control
to the system. As a result, your Web server becomes unresponsive
during execution of your CGI application.
What's more, only one CGI request can run at the same time. This
is annoying when your CGI application performs database lookups
that, depending on the complexity of the query, can take some
time. You can sometimes bypass these limitations by using the
VB DoEvents statement in your program; this statement
returns control to the system. Especially in data-access applications,
however, you can't always use it. The 32-bit version of Visual
Basic solves this problem by being pre-emptively multitasking.
This means that all other processes keep running, allowing your
server to serve other requests at the same time and run more CGI
requests concurrently, thus serving more users at once.
Visual Basic 4 has become a large development environment that
requires considerable processor power and a substantial amount
of RAM. Many developers report a drop in performance when they
move from VB 3 to version 4 on systems with limited RAM. When
you're setting up a Web site, make sure that your server has at
least 16M of RAM and a Pentium processor. When you're running
Windows NT or expecting many CGI requests, you need at least 32M
but preferably 64M of RAM. Reports indicate that CGI applications
show an impressive performance increase after you upgrade RAM
from 32M to 64M, especially on Windows NT systems.
| Improving CGI Performance by Preloading Runtime DLLs
|
An important issue is preloading DLLs. Visual Basic is an interpreted language, which means that it needs runtime libraries during execution, generally called dynamic link libraries, or DLLs. These libraries are modules that Windows needs to load
into memory before a VB application can be executed, and this can take up to several seconds. Your CGI application runs faster when these DLLs are loaded into memory beforehand, since this saves you the time of loading them during the CGI request.
Many Web servers can preload DLLs at server startup and keep them in memory for as long as the server runs. The WebSite Web server can do so when you use the -l command-line option. For example, httpd32.exe -l
vb40032.dll starts the Web server and preloads the Visual Basic runtime library. For other Web servers, check the manual for information on this subject.
In addition to vb40032.dll (the main runtime library of Visual Basic), you might want to load other DLLs-for instance, if your application uses database access. However, what files you need to preload depends on the type of database you use
|
In an attempt to minimize server load and maximize the capabilities
of the Web browser, developers are working on client-side scripting
languages. These scripts are basically programs within the HTML
document and are interpreted by the browser. This approach results
in very little load on the Web server because the scripts run
on the user's PC. A document containing a script isn't static
like standard HTML. Imagine a script that places a live clock
in your Web browser or a script that alerts you if you improperly
fill in a form (even before you send it to the server).
At the time of this writing, at least two scripting languages
are being developed: Microsoft's Visual Basic Script (VBScript)
and JavaScript.
Microsoft's VBScript will be a subset of Visual Basic that's optimized
for Web browsers. The Visual Basic code can be embedded within
the HTML document. A small runtime library will be called by the
browser when it receives a Visual Basic script. The runtime library
can be licensed for free.
Imagine that you're selling CDs on the Internet, and you want
your forms to add up the total costs while the user is gathering
acquisitions. You'll be able to add a script like the following
to your form:
<Script>
Sub CheckBoxLouReed.Click
TotalAmount.Text = Cstr(Val(TotalAmount.Text) + 19.99)
End Sub
</Script>
Note that this is just an illustrative example. Even the HTML
<Script> tags still have to be negotiated with
the World Wide Web standards committees. The main advantage of
Visual Basic Script is that it's as intuitive and easy to learn
as Visual Basic. If you've done some Visual Basic programming
before, you'll probably be programming Visual Basic Script in
no time.
JavaScript is another scripting language that's being implemented
in the Netscape browser. Unlike the Java language, which is compiled
at the server side, JavaScript is interpreted at the client side.
Because it's object-oriented, JavaScript has more of a C++-type
of approach and requires somewhat more advanced programming skills.
Implementations of JavaScript for Web servers will also be available
as alternatives for CGI.
One ongoing discussion is how safe these scripting languages are.
Could someone write a computer virus in a scripting language and
erase your hard disk? The JavaScript developers have dealt with
this issue beforehand by dis-allowing write access to your hard
disk. However, I have heard reports of a JavaScript that collected
and submitted the user's e-mail addresses to a server as a quick
and dirty way of doing market research.
Some other restrictions related to these scripting languages are
in place. Suppose that you don't want to share the source code
of your script with the rest of the world. This is impossible
with VBScript and JavaScript, because the source is sent to the
user when he accesses your server; it's embedded in the HTML document
and interpreted by the user's Web browser.
In the case of a script that accesses a database, you'll need
to send the database along with the script, which is, of course,
undesirable. These scripting languages will certainly be useful
for some applications; for other applications, you'll still need
to rely on CGI.
Copyright notice: The Visual Basic projects in this
chapter use the cgi32.bas Visual Basic CGI framework by Robert
Denny, which is Copyright© 1995, O'Reilly & Associates,
Inc., All Rights Reserved, and is reproduced with permission of
O'Reilly & Associates.
|