This chapter discusses the Common Gateway Interface (CGI) and the role it plays in linking client-side actions (such as database access requests) to server-side reactions (such as database access and queries, as well as the subsequent dynamic generation of HTML for data presentation). You've already looked at using HTML user interfaces (enhanced with ActiveX and VBScript) to support database access on the client side. Now it's time to start looking at one of the most popular methods for handling information submitted from these forms to a Web server--this is the world of CGI. This chapter demystifies CGI and shows you that it really is no more than another component of a distributed applications development environment.
This chapter begins with an introduction to just what CGI is and some of the tasks it can help you accomplish. A discussion on CGI input and output processing follows, including some specifics on environment variables and their uses, as well as the methods used by the client to make a request to the server when an HTML form is submitted.
Next you will discover how the Windows CGI interface provides an easy means for developing CGI applications in a Windows development environment. Additionally, you will see how the enterprising work of some sharp Visual Basic developers has resulted in a publicly available module of VB code that greatly simplifies development of Web applications using Windows CGI and Visual Basic.
Finally, the remainder of the chapter takes a look at using the DB-Library VB API that comes with Microsoft SQL Server to create sophisticated Web database applications.
CGI is most simply described as a means by which a Web server can communicate with applications external to the server software and have those applications perform some processing on its behalf. In essence, CGI is a server-side process that serves as a go-between for the Web server and other applications programs, information resources, and databases. These information resources and databases can reside on the same physical machine as the Web server or on a machine at some other geographical location.
CGI provides a standard interface between the Web server and external applications. These applications commonly are referred to as gateway programs, CGI programs, or simply CGI scripts. This interface abstracts the details of communications between the Web server and the CGI program to the point where the only detail that application developers really need to know about the interface is how to input data into and retrieve data from their application. You therefore need no fundamental knowledge of the process of communicating directly with HTTP servers to use programs such as database query programs. You just need to understand how to handle the data that the server passes to the program and return the data generated by the program.
CGI programs extend the basic functionality of the Web server and give it the capability to service a variety of Web client requests that the server alone ordinarily would not be able to accommodate. CGI provides the mechanism for giving Web clients (your users) access to any application or resource to which you want to provide access.
http://hoohoo.ncsa.uiuc.edu
Gateway program, CGI program, and CGI script are essentially three names for the same thing; the remainder of this chapter uses the term CGI program. CGI programs contain the code that accepts data from the Web server (most often passed on from its Web clients) and does something with that data. Tasks can range from various forms of processing, accessing information resources, creating output, or all of these. CGI programs can be developed in virtually any language supported on the Web server host machine, including compiled and interpreted languages such as C, C++, Java, JavaScript, Visual Basic, FORTRAN, Perl, Awk, Expect, and Tcl, as well as some of the newer Perl extensions for client/server database access--for example, Sybperl and Oraperl.
A CGI program enables you to develop applications that greatly extend the functionality and capabilities of your Web server. In doing so, you can integrate other system resources, such as databases, document repositories, statistical applications, specialty processing, and so on with your Web server. These resources do not need to be local to the server host machine; they can be geographically distributed databases and applications that the CGI program can access. In other words, a CGI program running on a machine in Washington, D.C., can be designed to access databases on machines in Los Angeles, California, or any other location around the globe.
By providing a means to access resources external to your Web server, CGI programs extend the availability of these resources to your Web clients. What does this mean? Suppose that your organization has a database of information that it wants the public or users internal to the organization to be able to access. You now can develop CGI programs that accept user input from an HTML forms interface and use that input to perform complex searches and queries against the database. Other applications can be processing HTML order forms for your online store. This order processing also can be integrated with applications that perform inventory and warehouse management, accounting, and so on.
One of the most powerful aspects of CGI programming is that it gives you a means of generating HTML documents on-the-fly. No longer does your Website have to be a repository of static documents and data. Using CGI, you can develop applications that enable users to create dynamic, customized HTML documents and data presentations by specifying their unique content.
The typical steps in the CGI data-flow process follow, as shown in Figure 18.1:
FIGURE 18.1. The CGI data-flow process.
A Web server and a CGI program can communicate and pass data to one another in four ways:
Actually, CGI programs and a Web server can communicate through one additional method: by using a Windows .INI file. This method is specific to a specialized form of CGI known as Windows CGI. Because the Windows CGI specification is of particular interest to CGI developers in the Windows operating system environment, the latter half of this chapter (beginning with the section entitled "What is Windows CGI?") is dedicated to covering it in detail.
CGI input data is data submitted by the requesting client to the server, which the CGI program uses to perform some action, such as a database query. Depending on the way in which the client request is made (for example, the forms request METHOD=POST), this input data may be encoded before being passed by the server to the CGI program by environment variables or by standard input. When standard input is used, the length of the input string still is passed through an environment variable.
In addition to the actual data, the server also may pass information to the CGI program detailing the type of data that was passed. This is the case when the data is passed to the program by standard input. Standard input gives the CGI program a means of determining how it is supposed to handle or process the input data. This data type information also is passed through an environment variable.
A CGI program can generate a variety of types of output. This output can consist of instructions to the server to perform some task, such as calling another program or perhaps redirecting the client to obtain resources at another URL. More often, though, this output consists of HTML, ActiveX controls, and VBScript generated to present the results of some action performed for a requesting client. These results could be the results of a database query, for example.
CGI output always is returned by standard output. Even in cases when the CGI program has no data to return, it must generate a response indicating this. Two methods of return are possible: parsed-header output and non-parsed headers. With parsed-header output, CGI scripts produce output that is interpreted by the server and sent to the client. The script is not required to send an HTTP header, because this function is handled by the server when it parses the script output before passing it on to the Web client. Parsing incurs some overhead in processing by the server. Sometimes, you may want to avoid the overhead of this additional processing. To do so, CGI scripts can generate an HTTP header directly to avoid parsing by the server. These scripts must be prefixed by nph- to tell the server that output is to be passed directly to the client without parsing. Parsed header output is the only concern here, because this is the form that servers are required to support.
When the CGI program has data to return to the client, the data must be sent in a specific format:
Data Header (of a type understood by the server)
. . .a blank line . . .
the body of the response (i.e. optional output data to the requesting client)
As noted, the response data is optional, but if it is included, it must be prefaced by a MIME Content-type data header as seen in the following line of code:
Content-type: text/html
If the output data is not included, the data header must be a Location type (a URL), such as this:
Location: http://www.north.pole/santas_list.html
or a Status type (a message string), such as this:
Status: msg# msg_text
The server reads the CGI output and takes action depending on the header it finds. If the header is a Content-type header, the output is returned to the client. If the header is a Location type, the server ignores anything following the Location header and instead directs the client to access data or resources at the URL specified. If the header is a Status type, msg# and text enable the server to override the defaults it normally would return to the client.
Whenever you are working on a computer, running a program, or simply logging on, background variables are part of your working environment. These background variables are known as environment variables and typically are set automatically when you log on, established by a program at runtime, or even defined and set explicitly by you. Typically, environment variables persist for the life of a parent process and are passed to or inherited by child processes and applications of the parent.
Several standard CGI environment variables are defined when a server executes a CGI program. These can be used to pass data between the server and the CGI program. These variables come in two basic types. The first type of variable is the variable set during all client requests; this is a not request-specific variable. The second type of variable is a variable specific to the client request the CGI program is fulfilling; this is a client-specific or, more commonly, request-specific variable.
HTTP_REFERER=file:///C|/My Documents/SAMS/WebDev/echoenv.html
HTTP_CONNECTION=Keep-Alive
Environment variable values are used by CGI programs primarily as a means of attending to client requests for processing, database accesses, and so on. Sometimes, however, the variables are used to determine the client's type of Web browser. In other cases, the variables may be used to maintain and pass state information between the client and the CGI program between independent requests for service from the client. This need for state information occurs because HTTP is a stateless protocol. Therefore, after a client/server connection is dropped, your CGI program has no knowledge or memory of preceding connections unless you explicitly build in a mechanism for maintaining this information. You can maintain the state of user input to a form, for example, by designing CGI applications that embed these values as hidden fields in subsequent HTML documents that it generates for the client.
A list of 19 standard CGI environment variables follows (variables that are not request-specific are so indicated):
CONTENT_LENGTH
CONTENT_TYPE
GATEWAY_INTERFACE (not request-specific)
HTTP_ACCEPT
HTTP_USER_AGENT
PATH_INFO
PATH_TRANSLATED
QUERY_STRING
REMOTE_ADDR
REMOTE_HOST
REMOTE_IDENT
REMOTE_USER
REQUEST_METHOD
SCRIPT_NAME
SERVER_NAME (not request-specific)
SERVER_PORT
SERVER_PROTOCOL
SERVER_SOFTWARE (not request-specific)
The following sections briefly describe each of the CGI environment variables.
For servers that support user authentication and run protected CGI programs, the value of the AUTH_TYPE variable details the method used to validate users. The authentication method is protocol-specific. For example, this code indicates the most common value used:
AUTH_TYPE = Basic
In this case, a basic authentication scheme requires that a client provide a password and user identification in order to authenticate itself.
The CONTENT_LENGTH variable represents the length (in characters) of the data buffer sent by the client to the server during a request. For example, a test request for forms processing on the server reported this:
CONTENT_LENGTH=105
The value of the CONTENT_TYPE variable represents the MIME type of the data sent from the client to the server as the result of a METHOD=POST request from the client. This method commonly is used in HTML forms processing. If no data is sent, the value is set to NULL. For example, a test request for forms (using POST) processing on the server reported this:
CONTENT_TYPE=application/x-www-form-urlencoded
This is the default encoding for forms.
The GATEWAY_INTERFACE variable simply contains the version of the CGI specification to which the server complies. This environment variable is not request-specific. The server reports this value as the following, which indicates CGI 1.1:
GATEWAY_INTERFACE=CGI/1.1
The value of the HTTP_ACCEPT variable is a comma delimited list of all the MIME data types the requesting client will accept. MIME is covered in more detail in Appendix G, but basically seven MIME types are used by HTTP. These include application, text, multipart, message, image, audio, and video. All these types also have subtypes associated with them. For example, GIF is a subtype of image. My server reported that a Microsoft Internet Explorer Web client accepts the following image types:
HTTP_ACCEPT=image/gif, image/x-xbitmap, image/jpeg, */*
Note that the value of HTTP_ACCEPT is a list of accepted MIME types and is formatted as type/subtype, type/subtype, and so on.
The HTTP_USER_AGENT variable contains the Web browser the client used to send a request. It provides a nice way for CGI programs to format output to take advantage of extensions used by certain browsers or to accommodate shortcomings of some browsers. The server reported the following for a Microsoft Internet Explorer Web client, for example:
HTTP_USER_AGENT=Mozilla/1.22 (compatible; MSIE 2.0; Windows 95)
In this case, the value of the environment variable indicates that the client Web browser is Microsoft Internet Explorer (MSIE) 2.0 running under Windows 95 and that it is compatible with Netscape (Mozilla) 1.22.
The value of the PATH_INFO variable represents extra path information supplied by the client. Servers can decode this information from URLs before executing the CGI script. Notice the following URL in an HTML forms interface document:
<FORM METHOD="POST" ACTION="http://jupiter.omniscient.com/cgi-bin/test-env/extrastuff">
This URL points to a CGI program called test-env and is appended with additional information (extrastuff). This resulted in the server reporting the following:
PATH_INFO=/extrastuff
CGI applications typically do not have any knowledge of the method by which this value was set. It is up to the developer to know the context in which this value may be used. This variable gives the developer another method of passing information from an HTML document to a CGI program. Suppose that an anchor with the following URL is in the document:
<A HREF="http://jupiter.omniscient.com/cgi-bin/myVBGateway.exe/param1=val1+param2=val2
This results in the following PATH_INFO variable value:
PATH_INFO=/param1=val1+param2=val2
This variable provides a method by which two additional parameters might be passed to the CGI program myVBGateway.exe, which then could obtain these values from the PATH_INFO environment variable.
The value of the PATH_TRANSLATED variable is a virtual-to-physical PATH_INFO mapping provided by the server. In other words, it represents the server's attempt to provide a full operating system absolute path to the data indicated in PATH_INFO. For the URL specified in the FORM ACTION attribute in the previous example, that is
="http://jupiter.omniscient.com/cgi-bin/test-env/extrastuff"
the server uses the server's DocumentRoot value of /usr/local/etc/httpd/htdocs to translate the full path to this:
PATH_TRANSLATED=/usr/local/etc/httpd/htdocs/extrastuff
The value of the QUERY_STRING variable is a URL-encoded string that is appended after a question-mark (?) character at the end of the URL referencing the CGI routine being executed. URL-encoding is a method of translating some data values to be transferred between the client and server to ensure that the data sent is received intact. URL-encoding and using the METHOD=GET form request method to set this variable are discussed in the sections "Getting Client Data to a CGI Program" and "Query Strings" a bit later in this chapter.
For a METHOD=GET test, the following URL-encoded data string was sent to the server by the client:
http://jupiter.omniscient.com/cgi-bin/test-env?uname=&email=&address=&bus=sw Â&title=Pres&cgidev=Perl5&dbase=Access&description=&dbyesno=YES&subscribe=YES
The server reported the value of the QUERY_STRING variable as this:
QUERY_STRING=uname=&email=&address=&bus=sw&title=Pres&cgidev=Perl5 Â&dbase=Access&description=&dbyesno=YES&subscribe=YES
The REMOTE_ADDR variable contains the value of the Internet provider (IP) address for the requesting client or agent (which actually may be a host of the requesting client). For the previous test examples, the server reported the following:
REMOTE_ADDR=168.143.1.44
The REMOTE_HOST variable contains the full DNS hostname for the requesting client or agent if the server is able to obtain this information. Otherwise, the value is NULL. For the previous test examples, the server reported the following:
REMOTE_HOST=dkittel.clark.net
The REMOTE_IDENT variable contains the name of the remote user as retrieved from the server if the HTTP server supports RFC 931 identification. The RFC 931 Authentication Server documentation states that HTTP servers supporting this feature should make an effort to identify the requesting client or agent. This is not considered a valid means of authenticating users. Enabling this feature also can result in performance degradation because extra work is imposed on the server to attempt identification. An example of this variable follows:
REMOTE_IDENT=kittel.omniscient.com
The REMOTE_USER variable contains the authenticated user's name if the server supports user authentication and the CGI application program is protected from unauthorized use. If the AUTH_TYPE variable is set to basic, for example, the REMOTE_USER variable can be set by using the user's identification as sent by the client. An example of this process follows:
REMOTE_USER=julie_wirkkala
The REQUEST_METHOD variable contains the client request method. The GET and POST methods are by far the most popular and widely used methods.
In the previous test example of a request for forms processing, METHOD=POST was specified. The server subsequently reported the following:
REQUEST_METHOD=POST
http://www.w3.org/hypertext/WWW/Protocols/HTTP/Request.html http://www.w3.org/hypertext/WWW/Protocols/HTTP/Methods.html
The SCRIPT_NAME variable contains a virtual path to the CGI program being executed by the server. For the previous text example, the server reported this:
SCRIPT_NAME=/cgi-bin/test-env
The SERVER_NAME variable contains the Web server hostname, DNS alias, or IP address. This environment variable is not request-specific. The server reports this value as the following:
SERVER_NAME=jupiter.omniscient.com
In this case, the Web server hostname, jupiter.omniscient.com, was set. In other cases, the following DNS alias might be returned:
SERVER_NAME=jupiter
Or an IP address can be returned, such as this:
SERVER_NAME=555.555.0.19
The SERVER_PORT variable contains the port to which the client request was sent. Ports are communications sockets used by TCP/IP applications. Most TCP/IP applications use a well-known port identifier. Such is the case with HTTP, which uses port number 80 as a default. It is possible, however, for the port number to be explicitly called out in the URL. A server may use a port number such as 8080 as the designated port for the HTTP server. In this case, URLs need to explicitly reference the port, as this example shows:
http://jupiter.omniscient.com:8080/cgi-bin/test-env
The server reported the following:
SERVER_PORT=8080
Using different port numbers enables multiple servers to be run from the same machine. This can be beneficial for establishing servers for CGI testing as well as separate intranets.
The SERVER_PROTOCOL variable contains information about the protocol used by the requesting client. This variable includes both the name and revision number. For the earlier test example, the server reported this:
SERVER_PROTOCOL=HTTP/"1.0
The SERVER_SOFTWARE variable contains the name and version number of the Web server that is tending to Web client requests and running the CGI. This environment variable is not client-request-specific. The server reports this value as the following:
SERVER_SOFTWARE=NCSA/1.5
In this case, the server software is the NCSA Web server, Version 1.5.
A server can pass client data to a CGI program by using several methods. Two methods are by far the most functional and widely used: GET and POST. This section contains references to query strings and URL-encoding. This material is covered in the sections "Query Strings" and "URL-Encoding" presented a bit later. Feel free to flip forward for a look at this material if you get curious during the discussion of GET and POST.
The GET method is used to pass user input to an HTML form to a CGI program for processing. Although GET is the default value for the METHOD attribute, it is considered to be the less-preferred method for forms-input handling because of limitations on the amount of data that can be passed using GET (a limitation not incurred by using the POST method). Because writing CGI programs that obtain their input from the QUERY-STRING environment variable is very straightforward, GET still is useful for simpler forms with only a few input objects. A fair number of older HTML and CGI programs still exist that use GET.
After a user clicks the Submit button on a form, the client browser URL-encodes and assembles user-input data into a query string that is appended to the Action URL specified in the <FORM> tag in the HTML document. A particular request to the server may look like this:
GET /cgi-bin/dosomething.exe?name=myname&title=developer HTTP/1.0
The server then passes the URL-encoded user-input query string to the CGI program through the QUERY_STRING environment variable.
After a user clicks the Submit button on a form, the client browser URL-encodes user input in the same manner it does for GET; however, the data is not appended to the specified Action URL. Instead, the data is sent in a data block to the server as part of the POST operation. (A data block is simply a stream of data, of arbitrary length, passed to the CGI program.) In this case, the Action URL is the URL to which the data block is POSTed. A particular request to the server might look like this:
POST /cgi-bin/dosomething.exe HTTP/1.0 Accept: text/plain Accept: text/html Accept: */* Content-type: application/x-www-form-urlencoded Content-length: 36 ford=escort&toyota=mr2&special=rolls
The server now passes the encoded user data to the CGI program by standard input. Additionally, the CONTENT_LENGTH and CONTENT_TYPE environment variables are set for use by the CGI program.
Earlier, you learned that the value of the QUERY_STRING environment variable is obtained from a URL-encoded string that is appended after a ? character at the end of the URL that references the CGI routine being executed. But how is the information added to the end of the URL in the first place? This can occur in two ways.
In the first method, the query information is added manually to an anchor's HREF URL in an HTML document. The URL in the following anchor, for example, references a program that prints a list of all employees due for a promotion this year:
<A HREF http://www.north.pole/print-promotion-list.exe>List Promotions</A>
However, the URL may be manually appended with query string information to cause the CGI program to print a list only if a certain specified name or names are on the list:
<A HREF http://www.north.pole/print-promotion-list.exe?Mark+Drew> ÂDisplay Promotions List</A>
In the second method, HTML forms using the GET method cause encoded user form input to be appended to the URL.
URL-encoding is a method by which requesting client data is changed or remapped to encoded characters before the server passes that data to a CGI program. URL-encoding causes the following things to occur:
Suppose that you have a form using the POST method. This form has three user-input fields for the user's name, e-mail address, and some free-form text. The user fills the fields as follows:
User name field (uname) is set to Drew Kittel E-mail field (email) is set to kittel@lnk.com Freeform text (description) is set to ~!@#$%^&*()-=+|\/~
When the form is submitted, the requesting client's data is URL-encoded according to the previously described specifications, and the server then passes this data to the CGI program. In this case, the URL-encoded data sent to the CGI program via standard input follows:
uname=Drew+Kittel&email=kittel@lnk.com Â&description=%7E%21@%23%24%25%5E%26*%28%29-%3D%2B%7C%5C%2F%7E
Note that the form name/value pairs are separated by & characters and that the actual field names and their respective values are separated by = characters. Finally, note how some of the characters in the free-form text are mapped to %hex-equivalent. For example, the = character in the free-form text was encoded as %3D. This differentiates it from the = character the server uses as a separator for field names and values.
Data provided by a requesting client using forms with GET and POST methods always is URL-encoded before being passed to the CGI program.
As stated in earlier sections, CGI specifies that data passed to back-end programs, such as a database program, be passed by environment variables or standard input. This specification is very specific to UNIX-type environments and does not suit the Windows development environment particularly well.
The Windows CGI specification was developed to provide a framework for how Web servers should implement CGI interfaces that support the development of CGI applications in a Windows environment. Unlike its UNIX counterparts (or any other known CGI interfaces), the Windows CGI interface does the work of decoding and parsing URL-encoded data passed to the server from the browser client. This decoded data is provided to back-end CGI programs via a formatted profile file (and, in some instances, a raw content file). The profile file is simply a version of the very familiar Windows .INI file.
The Windows CGI interface is the only known CGI interface that performs the work of decoding and parsing form data for you. Doing things in this manner greatly improves the capability to develop Web applications using common Windows development tools, such as Visual Basic and Visual Basic for Applications. This process also enables developers to focus on developing the application instead of worrying about the details of how data is passed from the client to the server and to CGI programs.
http://www.ora.com/
Evaluation versions of Netscape's servers are available for downloading at
http://www.netscape.com/
Additionally, you can get the full Windows CGI 1.3a Interface specification at the O'Reilly WebSite central site at
http://website.ora.com/wsdocs/32demo/windows-cgi.html
In the following sections, you'll examine a few fundamental concepts about the workings of Windows CGI. In particular, you'll learn about these topics:
The Windows CGI Data-Flow Process Figure 18.2 illustrates the data flow and processing performed during the request-response cycle. Windows CGI responds to and services requests from client browsers by following these steps:
FIGURE 18.2: The Windows CGI data-flow process.
Windows CGI I/O Spooling The Windows CGI specification stipulates that servers implementing the Windows CGI interface should provide for a spooled exchange of data between the Web server and CGI programs. In order to ensure efficient transfers of data between spool files and the network, the specification also recommends that the server use memory-mapping techniques while minimizing the number of network I/O requests used.
I/O spooling is performed by Windows CGI-compliant servers for a number of reasons:
Data Decoding Performed by the Server A browser can send form data to a server in one of two ways:
Windows CGI-compliant servers are required to support both of these form data types.
How the Server Launches Windows CGI Programs The Windows CGI specification states that compliant servers must launch a CGI program by using the CreateProcess() service with the following command line:
win-cgi-exe cgi-data-file
Here, win-cgi-exe is the complete path to the CGI program executable, and cgi-data-file is the complete path to the CGI data file.
The Windows CGI Profile (.INI) File As previously stated, Windows CGI-compliant Web servers pass data to CGI programs via a private profile (.INI) file. The data in this file is maintained in key-value format so that CGI programs can use standard Windows API calls for extracting key-value pairs from the file. The profile file consists of eight sections per the following template:
[CGI] [Accept] [System] [Extra Headers] [Form Literal] [Form External] [Form File] [Form Huge]
Accept: type/subtype {parameters}
Accept: type/subtype=Yes
key=pathname length
key=offset length
key=[pathname] length type xfer [filename]
In the previous section, you discovered in great detail how the Windows CGI interface works. In particular, you saw how the interface takes care of many details, such as I/O spooling and the tedious task of decoding URL-encoded form data. Your CGI program still must do a bit of work, though, before it can complete the specific tasks it was designed to perform. Consider how you would perform these tasks:
Because these are functions that should be performed by any well-conceived CGI program, wouldn't it be nice if some proven development tools existed that took care of many of these details for you and enabled you to focus on the application?
Thankfully for VB developers, such a set of proven tools does exist in the form of the Windows CGI framework for Visual Basic. This framework is a 32-bit Visual Basic module (CGI32.BAS) that can be added to your VB projects to provide the following functionality:
http://software.ora.com/techsupport/software/extras.html
Using the CGI32.BAS framework in your applications requires that you structure your applications in a specific way and keep a few additional considerations in mind:
A Sample CGI_Main() Program As previously mentioned, CGI_Main() is a program you write to perform the primary functions of your CGI program--it is where the meat of your application resides. This program is called from the Main() program in the CGI32.BAS framework. Listing 18.1 shows a simple CGI_Main() program that uses the WebDate() and Send() functions supplied by the framework and returns the date and time at the Web server.
Listing 18.1. A Simple CGI_Main() Program.
Sub CGI_Main()
Send("Content-type: text\html")
Send( " ")
Send("<HTML><HEAD><TITLE>Web Server Date/Time</TITLE></HEAD>")
Send("<BODY>")
Send("The Web Server Date/Time is: " & WebDate())
Send("</BODY></HTML>")
End Sub
A Sample Inter_Main() Program The Inter_Main() program is called from the Main() program in the CGI32.BAS framework if the CGI program is executed from Windows (if a user double-clicks the .exe filename). For most CGI applications, it is sufficient to have the program display a message box stating that this program is a CGI program. The following example illustrates how this is done:
Sub Inter_Main() MsgBox "This is a Windows CGI Program" End Sub
Table 18.1 provides a listing and description of global CGI variables provided by the Windows CGI Visual Basic framework. The use of many of these variables is demonstrated in Listing 18.2 and Figures 18.5 through 18.7. Data types in this table are specified as the following:
S String
T Tupl
V Variant
Table 18.1. Global CGI Variables Provided by the Windows CGI Visual
Basic Framework.
| Variable | Description | Data Type |
|
The following variables hold server information |
||
| CGI_GMTOffset | Number of seconds from Greenwich Mean Time (GMT). | V |
| CGI_ServerAdmin | Server administrator's e-mail address. | S |
| CGI_ServerSoftware | Name and version of Web server software (for example, WebSite/1.1f). | S |
| CGI_Version | CGI version this server complies with (for example, CGI/1.2). |
S |
|
The following variables hold browser and user information |
||
|
CGI_AcceptTypes |
MIME data types accepted by the browser. |
T |
|
CGI_From |
E-mail address of the user. This rarely |
S |
|
CGI_NumAcceptTypes |
Number of MIME data types accepted by the browser. |
I |
|
CGI_Referer |
URL that referred to the CGI program. |
S |
|
CGI_RemoteAddr |
IP address for the remote host running the browser. |
S |
|
CGI_RemoteHost |
Hostname for the remote host running |
S |
|
CGI_RequestProtocol |
Name and revision of protocol used |
S |
|
The following variables hold information about executable, logical, and physical paths |
||
|
CGI_ContentFile |
Full path to a file that contains any |
S |
|
CGI_ContentLength |
Length (in bytes) of attached ContentFile data. |
L |
|
CGI_ContentType |
MIME content types of request with |
S |
|
CGI_ExecutablePath |
Path to the CGI program being run. |
S |
|
CGI_FormTuples |
name=value pairs sent by the form (if any). |
T |
|
CGI_HugeTuples |
Large name=value pairs. |
HT |
|
CGI_LogicalPath |
Logical or extra path information. |
S |
|
CGI_NumFormTuples |
Number of name=value pairs sent by the form (if any). |
I |
|
CGI_NumHugeTuples |
Number of large name=value pairs. |
I |
|
CGI_PhysicalPath |
Physical path--the translated version of the logical path in CGI_LogicalPath. |
S |
|
CGI_QueryString |
Encoded portion of the URL appended after the ? character. This contains GET data or the query string (if it exists). |
S |
|
CGI_RequestMethod |
Request method (for example, GET or POST). |
S |
|
CGI_ServerName |
Server hostname for the request (this |
S |
|
CGI_ServerPort |
Port number associated with the request. |
I |
|
The following variables hold information about security |
||
|
CGI_AuthPass |
Authorized user's password (only if |
S |
|
CGI_AuthRealm |
Authorized user's realm. |
S |
|
CGI_AuthType |
Authorization method. |
S |
|
CGI_AuthUser |
Authorized user's name. |
S |
|
The following variables hold other miscellaneous information |
||
|
CGI_DebugMode |
CGI tracing flag from the server. |
I |
|
CGI_ExtraHeaders |
Extra header information supplied by |
T |
|
CGI_NumExtraHeaders |
Number of extra headers supplied. |
I |
|
CGI_OutputFile |
Full path to the file in which the Web |
S |
Table 18.2 provides a listing and description of utility functions provided by the Windows CGI Visual Basic framework. The use of many of these functions is demonstrated in Listing 18.2 and Figures 18.5 through 18.7. Return value types in this table are specified as the following:
| N/A | Not applicable |
| T/F | True or False |
| S | String |
| Function | Description | Return Type |
| ErrorHandler() | Global exception handler. | N/A |
| FieldPresent() | Tests for the presence of a form field | T/F |
| (especially useful to determine whether | ||
| checkboxes on a form were checked). | ||
| GetSmallField() | Retrieves the contents (for example, | S |
| a value from a name=value pair) of a | ||
| named form field. | ||
| PlusToSpace() | Removes plus sign (+) delimiting | N/A |
| characters from a string. The + signs | ||
| are converted to spaces. | ||
| Send() | Writes a string into the output spool | N/A |
| file. This function is used heavily for | ||
| formatting HTML output to the client. | ||
| SendNoOp() | Sends a complete response that causes the | N/A |
| browser to do nothing and to stay on its | ||
| current page. | ||
| Unescape() | Removes URL-escaping from a string; | S |
| returns a modified string. | ||
| WebDate() | Returns a Web-compliant date and time | S |
| string (in GMT). |
You may remember that one of the benefits of using CGI applications is the capability to generate HTML on-the-fly. This capability to generate HTML documents and data presentations dynamically is not just a nice feature--it is an essential feature when providing access to database, customer service, and electronic commerce applications. These types of applications are interactive by nature and require the capability to formulate responses and outputs at runtime. Prepackaged HTML and static documents may be served up, but more often, responses need to be customized according to the user's input. Besides, it just isn't practical or desirable to have canned output for every permutation of database query a user's form inputs might generate.
Generating HTML on-the-fly might sound complicated, but by using Windows CGI and the CGI32.BAS framework utility functions, it's actually remarkably easy if you remember the following two points. First, a specific format is required if the CGI program is returning data to the requesting client. The format requires a data header, followed by a blank line, followed by the data to be returned. The required format follows:
Content_type: text/html start of HTML document ...body of document... end of HTML document
Note that the blank line after the data header is absolutely required. This action is something that is required time and again, and it easily can be implemented as the subprocedure (see the SendHTMLStart procedure in Listing 18.2).
Second, CGI programs that use the framework should never abort or perform an exit within the CGI program. This can cause the program to hang or exhibit undesirable results.
Generating dynamic HTML that uses the CGI32.BAS framework module and its Send() utility function is demonstrated in the next section.
Up to this point, you've been introduced to how Windows CGI interface passes form data to a Windows CGI program and is used to return data to a client. Additionally, you saw an overview of the CGI32.BAS framework and the functionality it provides. Now it's time to look at how the CGI32.BAS Visual Basic framework actually can be used by a CGI program to access the form data and then dynamically generate a response back to the client browser.
Listing 18.2 presents the Windows CGI Visual Basic program process_form_demo.exe. This program uses several CGI32.Bas utility functions and global variables to obtain information about HTML form input and CGI environment variables from the CGI request package created by the server. It then uses the CGI32.BAS Send() function to echo this information back to the client browser in the form of an HTML document. This program can be used with any HTML form and provides a nice way to test HTML forms in your applications.
In this sample Windows CGI Visual Basic program, a user is presented with the
HTML form shown in Figures 18.3 and 18.4.
FIGURE
18.3.: An online reader survey and subscription
appli-cation form used to invoke the CGI program shown in Listing 18.1.
FIGURE
18.4.: A continuation of the online reader
survey and subscription appli-cation form shown in Listing 18.1.
This form, an online reader survey and subscription application for a trade magazine, asks the user to input demographic information and then submit it to qualify for a subscription. Listing 18.2 shows the HTML code for this form.
Listing 18.2. Code Listing for dBWeb_form.htm, an Online Reader Survey and Subscription Application.
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Microsoft FrontPage 2.0">
<title>Web.dB Journal - Reader Survey and Subscription Application</title>
</head>
<body bgcolor="#FFFFFF">
<!-- Example: Magazine Reader Survey and Subscription Form -->
<!-- Author: Drew Kittel -->
<!-- HTML Specifications: HTML Level 2.0 Compliant (w/TABLE) -->
<!-- Revision History: created 10 Mar 1996 -->
<h2 align="center">
<em>Web.dB</em> - Reader Survey and Subscription Application</h2>
<hr>
<form action="http://dkittel.clark.net:8080/cgi-win/process_form_demo.exe"
method="POST">
<!-- Create TEXT and TEXTAREA widgets for name, e-mail, mail entry -->
<!-- Use TABLE to provide a bit of formatting control -->
<p><strong>Please provide the following personal information</strong> <em>
(Please fill all fields)</em> </p>
<table border="0">
<tr>
<td>Full Name: </td>
<td><input type="text" size="50" name="uname"></td>
<td><br>
</td>
</tr>
<tr>
<td>E-Mail: </td>
<td><input type="text" size="50" name="email"></td>
</tr>
<tr>
<td>Mailing<br>
Address: </td>
<td><textarea name="address" rows="5" cols="50"></textarea></td>
</tr>
</table>
<p><strong>What is your company's main product/service</strong>
(choose the most applicable) <br>
<!-- Use radio buttons to force mutually-exclusive choices -->
DB-Software <input type="radio" checked name="bus" value="sw">
Consulting <input type="radio" name="bus" value="consult">
Engineering <input type="radio" name="bus" value="engr">
Research <input type="radio" name="bus" value="research">
ADP Services <input type="radio" name="bus" value="adp"> </p>
<p><strong>What is your title?</strong> (choose the most applicable) <br>
<!-- Use radio buttons to force mutually-exclusive choices -->
President-CEO <input type="radio" checked name="title" value="Pres">
Manager <input type="radio" name="title" value="Manager">
Designer <input type="radio" name="title" value="Designer">
Programmer <input type="radio" name="title" value="Programmer">
Analyst <input type="radio" name="title" value="Analyst"> </p>
<hr>
<!-- These scrolled lists allow multiple choices -->
<!-- TABLE used to provide side-by-side formatting -->
<p><strong>Please tell us about your development environment</strong>
<em>(Please select all that apply)</em> </p>
<table border="0" noborder>
<tr>
<th>Languages</th>
<th>Data Bases</th>
<th width="20%">Describe Your Applications</th>
</tr>
<tr>
<td><select name="cgidev" multiple size="8">
<option selected value="Perl5">Perl 5.0 </option>
<option value="Magic">MAGIC </option>
<option value="Sybperl">SybPerl </option>
<option value="Oraperl">OraPerl</option>
<option value="C">C </option>
<option value="C++">C++</option>
<option value="Unix Shells">Unix Shells</option>
<option value="Python">Python</option>
<option value="REXX">REXX</option>
<option value="FORTRAN">FORTRAN</option>
</select> </td>
<td><select name="dbase" multiple size="8">
<option selected value="Access">MS ACCESS</option>
<option value="Sybase">Sybase</option>
<option value="Oracle">Oracle</option>
<option value="FoxPro">FoxPro</option>
<option value="WDB">WDB</option>
<option value="Web-Genera">Web-Genera</option>
<option value="VAX DBMS">VAX DBMS</option>
<option value="DB2">DB2</option>
<option value="Informix">Informix</option>
<option value="RdB">RdB</option>
</select> </td>
<td><textarea name="description" rows="8" cols="50"></textarea>
</td>
</tr>
</table>
<p><strong>Do you currently develop/plan to develop
Web-accessible databases?</strong><br>
YES<input type="radio" checked name="dbyesno" value="YES">
NO<input type="radio" name="dbyesno" value="NO"> </p>
<p><strong>Do you want to receive/continue to receive a free subscription
to </strong><em><strong>Web.dB</strong></em><strong>?</strong><br>
<strong>YES!</strong><input type="radio" checked name="subscribe" value="YES">
NO<input type="radio" name="subscribe" value="NO"> </p>
<p><input type="submit" value="Send My Subscription Now!">
<input type="reset" value="Clear Form Entries"> </p>
</form>
<hr>
<p> </p>
</body>
</html>
When the survey form is submitted, this Action URL is invoked:
action="http://dkittel.clark.net:8080/cgi-win/process_form_demo.exe"method="POST"
Form data is passed to the server, and the CGI program process_form_demo.exe is launched.
Figures 18.5 through 18.7 illustrate the dynamic HTML generated by the program
and returned to the client.
FIGURES
18.5. Dynamic HTML generated by
the program and re- turned to the user. (Remainder of this form is shown in Figures
18.6 and 18.7.)
FIGURE
18.6.Figure 18.5 continued.
FIGURE
18.7. Figures 18.5 and 18.6 continued.
Listing 18.3 shows the VB code for CGI_Main(), Inter_Main(), and a few subroutines used to create the executable.
Listing 18.3. Code Listings for Modules Used to Create the process_form_demo.exe CGI Program.
Attribute VB_Name = "Process_Form_Demo"
Option Explicit
Sub CGI_Main()
Dim i As Integer
SendHTMLStart
Send ("<HTML><HEAD><TITLE>Form Processing Demo</TITLE></HEAD>")
Send ("<body bgcolor=#FFFFFF>")
Send ("<CENTER>")
Send ("<H2>Form Inputs and CGI EnvironmentVariables</H2>")
Send ("</CENTER>")
Send ("<HR>")
SendFormTuples
Send ("<HR>")
SendCGIVariables
Send ("<HR>")
SendExtraHeaders
Send ("<HR>")
SendMIMETypes
` Now return to complete HTTP.
Send ("</BODY></HTML>")
End Sub
Sub Inter_Main()
MsgBox "This is a Windows CGI program"
End Sub
Sub SendCGIVariables()
Send ("<H3>CGI Variables</H3>")
Send ("<UL>")
Send ("<LI><I>CGI Version: </I>" & CGI_Version)
Send ("<LI><I>Request Protocol: </I>" & CGI_RequestProtocol)
Send ("<LI><I>Request Method: </I>" & CGI_RequestMethod)
If CGI_RequestKeepAlive Then
Send ("<LI><I>Keep-Alive: </I> Yes")
Else
Send ("<LI><I>Keep-Alive: </I> No")
End If
Send ("<LI><I>Executable Path: </I>" & CGI_ExecutablePath)
Send ("<LI><I>Logical Path: </I>" & CGI_LogicalPath)
Send ("<LI><I>Physical Path: </I>" & CGI_PhysicalPath)
Send ("<LI><I>Query String: </I>" & CGI_QueryString)
Send ("<LI><I>Content Type: </I>" & CGI_ContentType)
Send ("<LI><I>Content Length: </I>" & CGI_ContentLength)
Send ("<LI><I>Server Software: </I>" & CGI_ServerSoftware)
Send ("<LI><I>Server Name: </I>" & CGI_ServerName)
Send ("<LI><I>Server Port: </I>" & CGI_ServerPort)
Send ("<LI><I>Server Admin: </I>" & CGI_ServerAdmin)
Send ("<LI><I>Remote Host: </I>" & CGI_RemoteHost)
Send ("<LI><I>Remote Address: </I>" & CGI_RemoteAddr)
Send ("<LI><I>From: </I>" & CGI_From)
Send ("<LI><I>Referer: </I>" & CGI_Referer)
Send ("<LI><I>User Agent: </I>" & CGI_UserAgent)
Send ("<LI><I>Authentication Method: </I>" & CGI_AuthType)
Send ("<LI><I>Authenticated Username: </I>" & CGI_AuthUser)
Send ("<LI><I>Authentication Realm: </I>" & CGI_AuthRealm)
Send ("</UL>")
End Sub
Sub SendExtraHeaders()
Dim i As Integer
If CGI_NumExtraHeaders > 0 Then
Send ("<H3>Extra Headers:</H3>")
Send ("<UL>")
For i = 0 To CGI_NumExtraHeaders - 1
Send ("<LI><I>" & CGI_ExtraHeaders(i).key & ": </I>" &
ÂCGI_ExtraHeaders(i).value)
Next i
Send ("</UL>")
End If
End Sub
Sub SendFormTuples()
Dim i As Integer
Send ("<H3>Form fields data</H3>")
If CGI_NumFormTuples > 0 Then
Send ("<UL>")
For i = 0 To CGI_NumFormTuples - 1
Send ("<LI><I>" & CGI_FormTuples(i).key & ": </I>" &
ÂCGI_FormTuples(i).value)
Next i
Send ("</UL>")
Else
Send ("(none)")
End If
End Sub
Sub SendHTMLStart()
Send ("Content-type: text/html")
Send ("")
End Sub
Sub SendMIMETypes()
Dim i As Integer
Send ("<H3>MIME Types:</H3>")
If CGI_NumAcceptTypes > 0 Then
Send ("<UL>")
For i = 0 To CGI_NumAcceptTypes - 1
If CGI_AcceptTypes(i).value = "Yes" Then
Send ("<LI>" & CGI_AcceptTypes(i).key)
Else
Send ("<LI>" & CGI_AcceptTypes(i).key & " (" &
ÂCGI_AcceptTypes(i).value & ")")
End If
Next i
Send ("</UL>")
Else
Send ("(none)")
End If
End Sub
Most of this program is very straightforward and can be easily understood by briefly studying the variables and functions summarized in Tables 18.1 and 18.2. You should note a few things about this example:
As you can see, dynamic HTML generation in a CGI program is very straightforward. Of course, this is a simple example that simply uses HTML tags for creating lists. But the example does demonstrate how powerful this method can be when your CGI integrates other processing, database accesses, and subroutines designed to streamline the generation of the HTML tags and data returned. It also is possible to generate very complex responses to the requesting client. Data retrieved from a database, for example, could be formatted in very elaborate HTML tables using a variety of header fields, different font sizes and styles, as well as different font colors and table cell background colors for emphasis and to create visually appealing presentations of data. Additionally, dynamic generation of responses to the client could be used to generate graphical charts using specialized ActiveX controls. VBScript also could be included to enable the user to manipulate attributes of the displayed chart, such as color, title, graph style, and so on. These techniques are explored in greater detail in Chapter 19, "Database Results Presentation Using HTML and CGI."
Now it's time to explore how a Web server can use the power of CGI programs to access databases and submit queries on behalf of a Web client. This is an exciting time to be involved in Web database development. The world is just now realizing the potential of Web-based database applications. Individuals, organizations, and agencies are rushing to exploit the technology and implement these systems. This section provides you with some of the tools required to get involved right away.
In this section, you'll briefly examine some of the common methods used to access Web databases. You'll look at the reasons for my opinion that customized CGI programs offer one of the most flexible means of providing that access. You'll also see that all useful CGI database applications must accomplish a series of basic steps. Finally, you'll be presented with an example that illustrates how Windows CGI and the Visual Basic API for Microsoft's SQL Server can be used to develop Web database applications.
Currently, a few fundamental methods exist by which Web servers can access database systems on behalf of a Web client. Most of these methods use extensions to or are some variant of CGI programs. Note that each method has its inherent strengths and weaknesses, and some have implementations specific to the database system and Web server being used. The following sections briefly explore these common methods:
HTML Embedded SQL Extensions Many database systems provide a mechanism for embedding SQL statements directly within HTML files passed to the Web client by the Web server. When a user submits a query, the HTML file is passed to a CGI program, which parses the SQL statements and passes these on to the database system. Results of the SQL query subsequently are retrieved by the CGI program, reformatted to HTML, and returned to the requesting client. This mechanism is typical of many shareware databases and gateways. Additionally, the developer often is limited in his capability to modify the CGI program performing the actual database access and formatting of results. Chapter 24, "The Development of a PC-Based WWW Database System," demonstrates the use of DBGateway--a gateway application (developed using Windows CGI and Visual Basic) that uses HTML-embedded SQL. Codeless Interfaces Essentially, codeless types of access methods consist of software toolsets (often Perl scripts) that work with developer-defined template files. These template files specify various views into the database and the way in which extracted data should be manipulated and formatted when returned to the requesting client. Programs within the software toolset use these template files to automatically generate HTML forms. These forms, when submitted by the user, are then processed by CGI programs, which query the database and format the results in accordance with the predefined templates.
Most of the toolsets available today are somewhat manual in nature. In the near future, however, visual programming tools that implement drag-and-drop technology for building forms interfaces, specifying database queries, and detailing the format of results sent to the user should become more prevalent. Custom CGI Programs Customized CGI programs are gateway programs specifically written to accept and process Web client requests for a service provided by the Web server. Typically, these requests are submitted by users in the form of input they have entered in an HTML form. CGI programs designed for database access parse this user input, formulate queries based on the input, connect to the database and submit the query, and accumulate results. They also can manipulate these results or perform some other specialized processing and dynamically create HTML documents, which subsequently are sent back to the Web client. Web Server API Programs The use of Web Server APIs is becoming increasingly more popular. Most major Web servers now have an API available to applications developers. Microsoft has ISAPI for Internet Information Server (IIS), Netscape has NSAPI for its line of servers, and O'Reilly has WSAPI for its WebSite servers.
Server API programs provide many of the same benefits of CGI because they are very flexible and enable developers to greatly extend the functionality of the server. Most server APIs do not allow developers to choose the language in which they would like to develop their applications, however. In other words, the server API is language-specific. Additionally, although many server API programs realize a significant performance advantage over their CGI counterparts, this advantage often is realized because the application shares process space with the server itself. This can be dangerous; if a bug causes an application to die, for example, the server may crash as a result.
Currently, customized CGI programs are by far the most common method for accessing Web databases. CGI programs give developers a tremendous amount of power and flexibility in extending Web server functionality. Without question, other methods, such as those described earlier, have their place and provide advantages when dealing with well-defined and structured systems. As most experienced software developers have discovered, though, there invariably comes a time when development tools don't provide the functionality, flexibility, or power to do what is necessary to get the job done. Custom CGI programs provide this functionality, flexibility, and power by enabling developers to design the application to best suit the problem at hand.
A custom CGI program allows for development of applications that access databases in a variety of ways, including these:
Additionally, custom CGI programs provide distinct advantages over other methods, including these:
Figure 18.8 illustrates the basic steps required in all useful CGI database access programs. The basic steps apply to most programs, but the sequence may vary somewhat from application to application. All useful programs perform the following tasks, however:
FIGURE 18.8. The fundamental steps that make up basic CGI database programs.
In this section, you will explore a method of developing Web database Windows CGI applications using Visual Basic. Specifically, you will examine all the fundamentals required to begin developing Web database applications that use Microsoft's SQL Server 6.5 database. In doing so, you will be introduced to the Microsoft DB-Library Visual Basic API for SQL Server.
http://www.microsoft.com/This evaluation version is a full copy of the SQL Server 6.5 product and includes the DB-Library API for developing VB applications. Note that the main setup program included with the downloadable version does not perform a full installation of all components of the product. You must manually execute the setup programs under the following directories to install ODBC, Programmer's Toolkit (PTK) and other VBSQL sample and help components, respectively. These directory paths are all relative from the temporary installation directory created by the main setup program:
/I386/ODBC/Setup.exe /PTK/I386/Setup.exe /PTK/Vbsql/Setup.exeWhen installing the PTK components, make certain that if you are running IIS on your system you first shut down the server before running the setup program. Otherwise, the PTK installation will hang occasionally.
Microsoft DB-Library is a library of functions that enables very sophisticated client/server applications to be developed for SQL Server. The VB API is a set of Visual Basic functions and routines that lets your application (in this case, your CGI program) interact directly with Microsoft SQL Server. Functionality in the VB API represents a subset of the functionality available in the C language API.
As you will see in subsequent sections of this chapter, this API enables you to develop CGI programs that act as clients to SQL Server databases. The DB-Library API provides these database client programs with the capability to make multiple connections to SQL Server databases, send very complex Transact-SQL queries to the databases, and retrieve results of those queries. The interface also provides the mechanisms necessary to use more sophisticated SQL Server capabilities, such as stored procedures, triggers, and cursors.
By using the VB API, SQL Server now becomes an integral part of your Visual Basic CGI programs and enables you to perform virtually any database operation supported by SQL Server on behalf of Web clients submitting requests from their browsers. CGI database applications can include standard database operations such as these:
CGI database applications also can perform more complex operations, such as these:
Several files are necessary for developing applications using the VB API; these
are summarized in Table 18.3. Note that many of these files are not included with
DB-Library for Visual Basic; therefore, you need to make certain that they already
exist on your system.
Table 18.3. Files Required for Developing Visual Basic DB-Library
Applications.
| Filename | Description | Included with DB-Library? |
| VBSQL.OCX | OLE custom control for DB-Library for Visual Basic. Contains all library functions required to develop client applications. Located in the \PTK\I386 directory under the temporary installation directory used by the main setup program when SQL Server was installed. | Yes |
| VBSQL.BAS | An include file that contains all DB-Library Visual Basic function androutine declarations. Located in the \MSSQL\DBLIB\INCLUDE directory of the SQL Server installation on your system. | Yes |
| MFC40.DLL | A current version of the MicrosoftFoundation Class (MFC). | Yes |
| NTWDBLIB.DLL | The DB-Library for Win32 (Windows 95 and Windows NT). | No, but included with SQL Server |
| MFCANS32.DLL | The MFC ANSI to Unicode Translation layer. | No |
| MSVCRT40.DLL | The Microsoft Visual C Runtime Library. | No, but included with SQL Server |
To create a VB 5 project that uses the DB-Library Visual Basic API, you should follow these five basic steps:
Adding the VBSQL.BAS DB-Library Header File to the Project To add the VBSQL.BAS DB-Library OLE header file to the project, perform these steps:
Adding the VBSQL.OCX DB-Library OLE Custom Control to the Toolbox To add the VBSQL.OCX DB-Library OLE custom control to the project toolbox, follow these steps:
FIGURE 18.9.The components dialog box.
FIGURE 18.10. The Add ActiveX Control dialog box.
FIGURE 18.11. Adding the VBSQL.OCX custom control to the project toolbox.
Adding the VBSQL.OCX DB-Library OLE Custom Control to a Form in the Project To add the VBSQL.OCX DB-Library OLE custom control to a form in the project, perform the following steps. Do not add a control to more than one form.
FIGURE
18.12.The VBSQL.OCX control has been added to the project
toolbox.
FIGURE
18.13. Selecting the VBSQL.OCX
control.
FIGURE 18.14. Adding the VBSQL.OCX control to a form in the project.
Adding Error-Handling and Message-Handling Event Procedures The VBSQL.OCX custom control has two event procedures that can be used within your applications: