NOTE: This article is an archived copy for portfolio purposes only, and may refer to obsolete products or technologies. Old articles are not maintained for continued relevance and accuracy.
January 15, 1996

Adding Interactive Services To Your Web Server

Look around the World Wide Web, and most of what you'll find today are online equivalents of printed propaganda. There may also be some downloadable files or imagesæas well as the seemingly requisite overabundance of hypertext links to every imaginable corner of the Internet. But, for the most part, Web servers are about as interactive as their paper-based counterparts.

While getting to this level of highly-functional-yet-somewhat-interoperable online publishing can seem miraculous to many, it is far from where these systems need to be if they are ever to be something more than an outlet for marketing's creativity. In order for the Web to become the next-generation platform for distributed computing, it must go beyond read-only into the world of interactive. Users should be able to add, edit and delete data in real time, as security and application locking allow.

We'll outline some of the concepts and technologies to help you get there today. We'll also look at some basic examples, and provide pointers to other materials where appropriate and available. By no means can we cover everything. We will attempt to give you enough information so that you can get started in the right direction.

"What kinds of applications can be called from the server, and where can they be found?" These are the two most common questions asked at this point. Before we can answer these questions, we must first look at how the server and applications communicate.

The Common Gateway Interface (CGI)

Most, but not all, Web servers have two basic methods of handling back-end data. They either read a file or communicate with other programs through the Common Gateway Interface (CGI). It's up to the application to figure out what to do with that data, and to return HTML to the server. This is an extremely simplistic overview of the process, and there are many possible exceptions and extensions.

Examples of CGI can be seen on many servers today. Clickable image maps such as those found on Network Computing's home page use CGI. The client sends an HTTP request containing the URL and XY coordinates to the server, which passes the coordinates to a local application. The application executes an event that has been associated with those coordinates and returns HTML to the server for delivery to the client. In the case of image maps, most of the time this HTML data consists of an HTTP redirect command that instructs the client to request another document from the servers.

Another common use of CGI is for searching through files or databases (Yahoo and WebCrawler are good examples). A user constructs a query that is sent to the server, which then spawns an application that conducts the actual search and returns the "hits" in HTML form.

So, to answer the question about the kinds of applications that can be called by the server: They include any application that supports CGI on the front end and can generate HTML responses. In fact, you can call almost any program you want, as long as it supports command-line operation.

However, the unfortunate truth is that no two Web servers are alike. They have all been developed with specific audiences in mind and "enhanced" to suit those markets. This means that just because something works with server brand X does not mean that it will work with server brand Y. For example, there are considerable differences between the Netscape server's CGI interface and the O'Reilly and Associates WebSite server's CGI interface, even though they both use Windows NT's cmd.exe command interpreter. The differences between the various Unix shells, Digital's DCL, DOS' COMMAND.COM, and all other platforms, can also impact what you want to do.

CGI Detailed: GET Vs. POST

One of the most common methods of implementing CGI is through the use of GETs and POSTs. In the "Clickable Image Map" figure, the client submitted a URL with a question mark and XY coordinates appended to the end. This method of CGI call is known as a GET. Not only are GETs the oldest, but they are also the default and easiest to implement. Another form of call, known as POST has become more popular, and is generally considered to be much more powerful. The differences between them are subtle, but significant.

The GET method is named for what the client does. It asks the server to GET the HTML document at HTTP://URL?Param. The server sees that the URL points to an executable, calls it and passes it the parameters.

In contrast, the POST method is used when the client submits a block of data to the server. The client is not necessarily assuming that anything will be returned to it, although the connection is still open. In most cases, the server's Webmaster has configured things so that the client is given a thank you message, or response data is sent to the client.

CGI Examples

Let's walk through an example using O'Reilly and Associates WebSite server, since its use of Windows NT's cmd.exe makes it easy to write simplistic demonstration scripts. WebSite can also run on Windows 95, so it's easy to use on a personal system for learning purposes. Besides, you can evaluate it free for 60 days. It's available at http://website.ora.com.

Once the WebSite Manager is downloaded, use the administrative tool to locate the directory for DOS executables (C:\WEBSITE\CGI-DOS is the default). Using notepad or some other text editor, create a file called DIRSEARCH.CMD in that directory and carefully copy the contents of script contents shown at the bottom of this article and save the file. Using a Web client, connect to your server and point to http://<servername>/DOS-CGI/DIRSEARCH.CMD . Assuming that your server is configured to allow your client to access DOS-based CGI scripts, you should get an HTML page stating No Files Specified. Don't worry. This is what we want! Connect again and this time add ?command.com to the end. You should see a standard directory listing of all the files named command.com. dirsearch.cmd is a simple NT batch file that scans your server's C: drive for any occurrence of a specified file and returns the directory list to the user. If a file is not specified, then an error message is displayed. We'll extend this program later, but first we need to examine it in detail.

Always Test the Data First

The first line in the box below is a parameter test to make sure that a user has supplied a filename. If "%1" is blank (that is, does not exist), then the batch file jumps to the :errlabel label, which returns an error message to the user. Any seasoned programmer will tell you that it's important to test your program inputs before acting on them, and it is even more crucial here for several reasons.

Most important is an open issue regarding system security. There are known weaknesses with many operating systems that allow shell metacharacters to break your script or a called application, thereby exposing your system. It sounds far-fetched, but it happens all the time. By adding keystroke traps to your script, however, you can go a long way toward preventing this from happening. Refer to the CERT archives for more information on this subject. This weakness is not prevalent on all systems, but it is on many of them.

Another good reason to test the parameters is for program control. As we'll show below, you can use this function to minimize your development. Finally, there's a programming reason to test the input: to make sure that the data is valid. If instead of conducting a directory search, you queried a database, you would want to make sure that all of the necessary information had been provided. Testing the data in a script is more efficient than letting the called application fail. You would still have to test for errors, so you might as well do it up front.

Define Your MIME Type

The use of MIME types to coordinate data exchange is now part of the HTTP specification, as of version 1.0. As you can see, both the :goodlabel and :errlabel sections begin with MIME type declarations echoed to STDOUT.

For our purposes, we are simply declaring that the following data is HTML. The Web client interprets this and knows to read and apply whatever HTML formatting tags it sees in the data. If the MIME type had not been declared, then your browser may or may not interpret the HTML tags.

As you may have guessed, you can also send binaries or other nontext data back to the client. For example, if you wanted to return a GIF image, you would define the MIME content-type as Image/GIF. The client would then receive and display the image appropriately. Likewise, you could send application binaries by using the Application/Octet-stream MIME type, and so on. Note the echo statement that follows the MIME declaration. You must send a blank line after you send the content-type: statement.

The Rest of It

The remaining code is fairly self explanatory. There are, however, some things worth noting. Notice that the < and > characters are proceeded by ^. This is to prevent cmd.exe from interpreting them as redirection commands. Also notice that DIR C:\"%1"/s is the actual command that we are calling. The remaining lines of code are used to prepare the environment and command line, as well as generate HTML on its behalf.

Image map servers and dynamic directory builders are two of the more common CGI-aware applications that you'll find. Additionally, there are a variety of third-party tools, such as database requesters and indexed searching agents, available on the Internet. If you wish to write your own, you can apply the same concepts we've shown you to a compiled language.

Adding Support for Forms

In its current form, dirsearch.cmd must be given a parameter on the URL's command line. This is far from intuitive, and if you made your users work like this, you'd have very little traffic on your site. Most users prefer to enter information on a form, and so do administrators, since the level of control increases tremendously.

The easiest way to build a form is through the use of the <ISINDEX> HTML tag. This simple tag has the delightful affect of putting an edit box widget on your page. When a user enters text into the edit box and presses the enter key, the text is appended to the URL (with the question mark), and the page is reloaded. At this point, a valid search string exists, and the script will process accordingly.

For our example, change the line in dirsearch.cmd that reads ^<H1^> No Files Specified^</H1^> to Enter a filename to search for: ^<ISINDEX^>. Now point your Web browser to /BIN/CGI-DOS/DIRSEARCH, and you will be greeted with an edit box. Type in COMMAND.COM and press enter, and the same script will now branch through the :goodlabel section, and return a directory listing.

Don't be confused by the name ISINDEX, it's an unfortunate moniker for such a flexible gizmo. This tag does not automatically make your documents searchable; some other tool (such as DIR, in our case) must do the searching if that's what you want. The <ISINDEX> tag simply provides an edit box whose contents are appended to the current URL.

Just as the <ISINDEX> tag is poorly named, so is it poorly treated by most browsers. Many of them prepend the edit box with an inane comment about the document being searchable, which is just plain wrong. In order for us to have an attractive form that doesn't confuse people, we'll have to use real forms.

Creating Real HTML Forms

Form creation with HTML is a fairly simple task, and as we've shown, passing data with CGI is also straightforward. When you combine these two components' simplicity and strength, tremendous results can develop.

In order to illustrate this, we need to modify our sample code. Edit dirsearch.cmd once again, and replace the <ISINDEX> tag with the code shown in the "ISINDEX Replacement" at the bottom of this page.

Save these changes, and reload our now familiar URL. Now, instead of seeing an <ISINDEX> input field, you should see a real HTML form. When you enter a file name into the edit box and click on the "submit" button, the script will process the directory search and return the list of matching files.

Let's examine this syntax in detail. The line that contains the HTML tag does what you might guess: It notifies the client that the following text contains form elements, until a closing tag is encountered.

There are additional keywords that can be used with the tag, which provide greater amounts of control. One of these is the Action= statement, which tells the browser where to send the form contents. By default, the destination is a URL but it could be any CGI application available to the user. For companies that have several distributed Web servers, but only one or two CGI servers, this is a great way to split the load. Also of importance is the Method= keyword, which allows you to specify that the query data is to be submitted using the GET or POST methods as described earlier.

Widget Lingo

Another keyword, the input tag, has many options, but it basically applies to almost every type of form widget available. This includes edit boxes, radio buttons, check boxes and command buttons. The only types of widgets not controlled by <input> are list boxes (either drop-down or scrollable) and large, multi-line text boxes, both of which have their own specific tags.

In our example, the first occurrence reads <Input Name="FILENAME">. This syntax will create an edit box with the resource name of Filename. The Name= command associates a name with the control data. After successfully running a query, look at the client's URL command line. Notice that where it used to have ?command.com, it now has ?filename=command.com. One final thing to remember about the Name= option is that it does not apply to command buttons (you'll see why in a moment).

Notice that we did not explicitly declare the edit box as such. That's because the default of <Input> widget is an edit box. If we chose to do so, we would declare it using the Type=Text attribute. Other valid Type= declarations include Password fields (like edit boxes, only keystrokes are echoed as asterisks), CheckBox, Radio, Submit and Reset.

Additionally, we could preload a string into the edit box by using the Value= statement. This can also be used with password fields, as well as checkboxes, radio buttons and command buttons, although its usage varies widely among them.

The default width (in theory, at least) of an edit box is 20 characters, and the height is one. You can define different sizes using the Size= directive. When setting the width, use Size=W. When setting the height, use Size=W,H. Note that setting the width does not restrict input to that amount of characters, but instead defines the width of the box itself.

One problem with the GET method is that text is appended to the URL as entered. If you let the user enter as much as they want, you run the risk of script or called application failure due to overflown buffers. The Maxlength= attribute is useful for limiting the maximum number of characters that an edit box will accept, thereby limiting your system's exposure.

Altogether, our simplistic <Input Name="Filename"> example could (and probably should) read as <Input Type="Text" Name="Filename" Width= 20 maxlength=20>. Note the use of quote marks around the textual values; this is an HTML requirement that needs to be followed for maximum compatibility.

Command Buttons

Command buttons are not nearly as complex as the edit boxes; there are only two possible types. Our example uses the Type="Submit" variety, which builds the parameter list and appends it to the URL specified by the <Form Action=....> tag. The other type of command button is Type="Reset", which clears the form and resets all of the widgets to their original state.

The only optional attribute that can be set for command buttons is Value=. In this case, the Value= attribute defines the text that appears on the button's face. It does not change the button's behavior. For our example, we could change <Input Type="Submit"> to <Input Type="Submit" Value= "Search">, and add another button that cleared the editbox by using <Input Type="Reset" Value="Clear">.

And Then Some

You should experiment with the different types of widgets and their optional parameters. Together they provide a fairly comprehensive set of tools for getting user input into your CGI scripts and applications. A good starting place is http://www.ncsa.uiuc.edu/ SDG/Software/Mosaic/Docs/fill-out-forms/ overview.html, and by searching Yahoo's (http://www.yahoo.com) database for "HTML and Forms."

Anyone familiar with other types of graphical forms-based tools will tell you that these gizmos, while handy, are hardly sufficient. New extensions have been added to the HTML drafts that address some concerns, but not all. Vendors are stepping up with products that address these concerns, however, so you should be able to find something that suits your need.

On the back end, Lotus Development and Netscape have both promised to ship HTML filters for their respective groupware products, allowing you to leverage in-form value testing, mathematical functions and the like. How these extensions will be handled by generic clients is anybody's guess. But it is a step in the right direction.

As for the clients, Netscape Navigator 2.0 and Oracle's PowerBrowser clients both promise to offer event-driven scripting language extensions that will allow Webmasters to embed extended controls into the forms directly. Although these clients will perform the functions as directed, it means more work for the administrators, since you may have to support multiple proprietary extensions. Again, it's a step that will drive further standards-based development.

GET vs. POST Revisited

We have been using the GET method to pass data down to our script. The POST method, which offers more capabilities, deserves some attention as well. To see a quick demonstration, change the <Form...> line in dirsearch.cmd to read <Form Method="POST" Action="/BIN/CGI-DOS/DIRSEARCH">, and reload the form again. This won't change the behavior of your script, but you may receive a security notice from your client.

Remember, we've been using O'Reilly's WebSite. It's CGI interface to cmd.exe is relatively consistent between POST and GET. However, there is one significant difference. WebSite manager generates a unique temporary file that contains the data provided during the post operation. You can sniff through this output file on a programmatic basis if needed, allowing your script to branch according to content. This is extremely handy if you have to allow users to submit large strings of text or binary objects.

Beyond Simple CGI

GET and POST both offer value, depending on your objectives. However, in this implementation theyare also both limited in that they rely on NT's cmd.exe, a character-based command interpreter, as well as require that scripts and applications support the use of STDIN and STDOUT. This precludes the use of Windows-based applications as CGI-callable services.

A handful of vendors are working together to develop WIN-CGI to circumvent this problem. Implemented as a CGI-aware library, you can extend any application for which you have the source code, recompiling it to read and write CGI instead of the more traditional I/O interfaces. Such efforts aren't new. Many sources are available for CGI libraries for various servers and operating systems. Contact your Web server vendor for leads.

Now that you understand some of the concepts behind CGI programming, you should be able to develop applications that communicate between the Web and any data system. Remember to follow the specifications, and do a lot of testing, and you'll come out ahead.


IF "%1=="" goto errlabel
echo Content-type: text/html
echo ^<html^>^<head^>
echo ^<title^>All occurances of %1^</title^>^</head^>
echo ^<body^>
echo ^<h1^>All occurances of %1^</h1^>
echo ^<pre^>
dir c:\"%1" /s
echo ^</pre^>
echo ^</body^>
echo ^</html^>
goto exitlabel
echo Content-type: text/html
echo ^<html^>^<head^>
echo ^<title^>No files specified!^</tile^>^</head^>
echo ^<body^>
echo ^<h1^>No files specified^</h1^>
echo ^</body^>
echo ^</html^>
goto exitlabel

ISINDEX Replacement

echo ^<Form^>
echo Enter A File Name to search for:
echo ^<Input Name="FILENAME"^>
echo ^<Input Type="SUBMIT"^>
echo ^</Form^>


-- 30 --
Copyright © 2010-2017 Eric A. Hall.
Portions copyright © 1996 CMP Media, Inc. Used with permission.