Common Gateway Interface

Advanced Internet Programming Techniques Using CobolScript®

This chapter discusses advanced techniques for processing internet data retrieval using CobolScript. We also briefly discuss the use of embedded JavaScript in your CobolScript programs, for handling tasks suited for client-side processing.

Our discussion of CGI data retrieval and processing assumes that the incoming CGI data is always submitted using the POST method. With the POST method, URL-encoded data is delivered to the CobolScript program through standard input. The CobolScript engine reads all of this data, decodes it, and places it in corresponding CobolScript variables.

Also, all code examples assume that you’ve set your file permissions correctly. As mentioned in earlier chapters, if you’re working in a Unix environment, always make certain that the file permissions on your CobolScript internet programs allow the CGI user (usually user ‘nobody’) to execute them.

All of our web and internet code examples also assume that you have not modified your web server software to make CobolScript your default CGI interpreter. However, making CobolScript the default CGI interpreter is usually relatively easy, depending on your web server. Doing so will simplify the URLs you use to call CobolScript programs; instead of calling a program with a URL such as the following:

http://www.cobolscript.com/cgi-bin/cobolscript.exe?samples.cbl

You would instead use a URL such as:

http://www.cobolscript.com/cgi-bin/samples.cgi

Or, if your web server is flexible enough to allow modification to the CGI program extension, even this:

http://www.cobolscript.com/cgi-bin/samples.cbl

However, by modifying your web server’s configuration in this manner, you will disable any interpreted programs already existing on the server that relied on the previous configuration, and that were written in a different language such as Perl (these programs will be treated as CobolScript programs and will fail to run because they are not valid CobolScript code). Use your own discretion in making this type of modification; a web system built from scratch, using only CobolScript code, is an ideal candidate for this kind of configuration change; a web system with existing interpreted code written in other languages is not. Consult your web server’s documentation for more information on how to configure the default interpreter path and the default CGI extension.

Environment Variables

Environment variables are system variables that exist within a particular computer user’s environment. With regard to a web server, the full set of environment variables is recreated each time a CGI process is executed. You can think of these variables as placeholders that a web server uses to pass data about an HTTP request from the server to the CGI-processing application, i.e., your CobolScript program.

With CobolScript, environment variables are accessed with the GETENV command:

GETENV USING <environment variable> <cobolscript variable>.

The names for environment variables are system-specific. Fortunately, most web servers have adopted many of the same names. Here are a few of the standard ones; experiment with these variables in the GETENV statement to determine the formats of the contents of each of these variables:

Environment Variable

Description

CONTENT_LENGTH

Size of the attached incoming CGI data in bytes (characters).

CONTENT_TYPE

The MIME type of the incoming CGI data

PATH_INFO

Path to be interpreted by the CGI application.

PATH_TRANSLATED

The virtual-to-physical mapping of the file on the system.

QUERY_STRING

The URL-encoded string that was submitted to the web server

REMOTE_ADDR

The IP address of the agent making the CGI request.

REMOTE_HOST

The fully qualified domain name of the requesting agent.

REMOTE_IDENT

Data reported about the agents’ connection to the server.

REMOTE_USER

The User ID sent by the client agent.

REQUEST_METHOD

The request method used by the client. For CobolScript applications, this should be “POST”.

SCRIPT_NAME

The path identifying the CGI application requested.

SERVER_NAME

The server name of the requested URL. This will either be the IP address of the server or the fully qualified domain name.

SERVER_PORT

The port where the client request was received by the server.

SERVER_PROTOCOL

The name and revision of the request protocol.

Environment Variable

Description

SERVER_SOFTWARE

The name and version of the server software. For example: “OmniHTTPd/1.01 (Win32; I386)”

Some web servers do not support all of these environment variables. You should consult your web server documentation to find out what environment variables are supported by your specific web server.

All normal web servers support the CONTENT_LENGTH environment variable. Because of this, we recommend getting this variable when your CobolScript application is first invoked via a web server, like this:

GETENV USING `CONTENT_LENGTH` content_length.

IF content_length > 0

ACCEPT DATA FROM WEBPAGE

END-IF.

By doing this, you will know if a form was submitted to your application or not. If your application was called directly from a typed URL, outside of a form submission, the value of CONTENT_LENGTH would be 0 and you would not need to accept CGI data from the web server. Normally, when the ACCEPT DATA FROM WEBPAGE statement is executed, CobolScript will begin reading data from the CGI stream and place the contents in the appropriate CobolScript variables. Of course, it’s not necessary to do this if no CGI data has been sent to the web server.

Sometimes, web servers are configured to not populate certain environment variables such as REMOTE_HOST. This is often done because there is a time cost in resolving the IP addresses of each client as it makes a request. However, you can still resolve these IP addresses by using the GETHOSTBYNAME command. Simply get the REMOTE_ADDR environment variable that contains the IP address of the client, and use this as the argument to GETHOSTBYNAME:

GETENV USING `REMOTE_ADDR` download_ip.

GETHOSTBYNAME USING download_ip.

MOVE TCPIP-HOSTENT-HOSTNAME TO download_host.

The GETHOSTBYNAME command will resolve the IP address to its fully qualified domain name, and the result will be placed in the TCPIP-HOSTENT-HOSTNAME variable. If the DNS server cannot resolve the IP address, the TCPIP-HOSTENT-HOSTNAME will be spaces. Also, for completeness, the TCP/IP return code values should always be examined after executing GETHOSTBYNAME to determine whether the command executed successfully or not.

CGI Form Components


As we saw in Chapter 5, the ACCEPT DATA FROM WEBPAGE statement can capture HTML form data. This data capture can be done from all of the possible submitting form components – text boxes, multi-line text boxes, list boxes, drop down list boxes, radio buttons, check boxes, and submit buttons. In this section, we describe how to process input from each of these components. The example program input.cbl illustrates the data capture for each of these components (except submit buttons). This sample program can be found in the sample programs included with CobolScript. The first screen of this sample program is shown in Figure 7.1.

All of the HTML form control tags that we discuss in this section have a common attribute called NAME. This attribute is of the form:

NAME=variable_name

Or, alternatively (quotes can be included or excluded from tag attribute values; they must be included, however, when spaces exist in the attribute’s value):

NAME=“variable_name”

where variable_name is the name of the CGI variable that will be passed to the receiving program when the form is submitted. The receiving CobolScript program, specified in the ACTION attribute of the FORM tag, must define a variable for each submitted form control with a NAME attribute in order for the ACCEPT DATA FROM WEBPAGE statement to work correctly.

Text Box Input

Text boxes are created with the <INPUT TYPE=TEXT… > tag. For instance, if our source CGI form submits a text input named field1, defined here:

<FORM ACTION=”/cgi-bin/cobolscript.exe?receive.cbl”>

<INPUT TYPE=TEXT NAME=field1><BR><BR>

<INPUT TYPE=SUBMIT>

</FORM>

Then, our receiving CobolScript program (which will be named receive.cbl, according to the ACTION attribute of the FORM tag above) must define a variable named field1:

1 field1 PIC X(20).

In the example program input.cbl, a text box named field1 is displayed to a web browser when the program is run. When the form is submitted from the web browser, the CobolScript program will get any data in the text box and place it in a CobolScript variable named field1.

Text boxes can also have preassigned values through the use of the VALUE attribute. In a more complex example than the one above, a CobolScript program we’ll call recurse.cbl, that both displays a form and calls itself after accepting submitted input from the form, could have some code like the following:

DISPLAY `<INPUT TYPE=TEXT NAME=field1 VALUE=”`.

IF field1 NOT = SPACES

DISPLAY field1

END-IF.

DISPLAY `”>`.

DISPLAY `<BR><BR>`.

DISPLAY `<INPUT TYPE=SUBMIT>`.

DISPLAY `</FORM>`.

In this case, the text box’s VALUE will be assigned “” (a null value) if field1 is blank (all spaces); otherwise it will be assigned the value of the CobolScript variable field1.

Text Area Input

Text area controls are created with the <TEXTAREA … > tag:

<TEXTAREA NAME=”field2” COLS=20 ROWS=2>

</TEXTAREA><BR><BR>

Our receiving CobolScript program must, in this case, define a variable named field2:

1 field2 PIC X(40).

In the example program input.cbl, a text area with the name field2 is displayed to the web browser when the program is run. When the form is submitted from the web browser, the CobolScript program will get any data in the text area and place it in a CobolScript variable named field2. Special characters like carriage returns and line feeds will be translated into HTML special characters such as &#013; and &#010; This is useful when you need to save the contents of a TEXTAREA to a file and later redisplay them in a web browser. The breaks and tabs will be preserved when you redisplay the HTML.

Because text areas can be large, and CobolScript variables are fixed width, you may find that you want a way to display only the initial populated portion of the text area input. HTML tends to ignore extra spaces, so it’s not usually necessary to eliminate trailing spaces, but you may find it useful when working inside dynamically-sized HTML tables, since trailing spaces are taken into account when table elements are sized. The routine below accomplishes this with a PERFORM..VARYING loop and the use of positional string referencing:

PERFORM VARYING space_location FROM 40 BY –1

UNTIL FIELD2(space_location:1) NOT = SPACE

END-PERFORM.

DISPLAY FIELD2(1:space_location)

List and Dropdown List Boxes

List and dropdown list boxes are displayed with the <SELECT … > tag inside an HTML form, like this:

<SELECT NAME=”field3” SIZE=3>

<OPTION SELECTED>Item1

<OPTION>Item2

<OPTION>Item3

<OPTION>Item4

<OPTION>Item5

<OPTION>Item6

</SELECT><BR><BR>

<B>field4:</B>

<SELECT NAME=”field4”>

<OPTION SELECTED VALUE=Item11>Item 11

<OPTION VALUE=Item22>Item 22

<OPTION VALUE=Item33>Item 33

<OPTION VALUE=Item44>Item 44

<OPTION VALUE=Item55>Item 55

<OPTION VALUE=Item66>Item 66

</SELECT><BR><BR>

To retrieve these CGI fields, our receiving program defines two variables, one for each of the SELECT tags’ names:

5 field3 PIC X(20).

5 field4 PIC X(20).

The SELECT tag is relatively straightforward: The value of each option is the text that immediately follows each OPTION tag, unless a VALUE attribute is specified in the OPTION tag. When an option is selected and the controlling form submitted, the SELECT variable is assigned the value of the option that was selected. By using a list box, you can limit the possible inputs that can be submitted, and therefore more readily direct processing based on these inputs. For instance, we could control processing based on the value assigned to field4 like this:

IF field4(1:6) = `Item33`

DISPLAY `Item33 is currently out of stock`

ELSE

DISPLAY field4 & ` has been ordered for you`

END-IF.

Radio Buttons

Radio buttons are created with the <INPUT TYPE=RADIO … > tag. They allow the selection of a single option from multiple options; when created properly, only one radio item may be selected from all radio buttons that have the same NAME value within a particular form. The VALUE tag is useful because you can put a compressed or numeric value in it and display a different text label in your web page, like this:

<INPUT TYPE=RADIO NAME=field5 VALUE=111>Item 111<BR>

<INPUT TYPE=RADIO NAME=field5 VALUE=222>Item 222<BR>

<INPUT TYPE=RADIO NAME=field5 VALUE=333>Item 333<BR>

<INPUT TYPE=RADIO NAME=field5 VALUE=444>Item 444<BR>

<INPUT TYPE=RADIO NAME=field5 VALUE=555>Item 555<BR><BR>

After the form is submitted, ACCEPT DATA FROM WEBPAGE will copy the VALUE of the radio button to the CobolScript variable with the same name as the buttons, so in this case, the following CobolScript field definition is required:

5 field5 PIC X(3).

Checkboxes

Checkboxes are created with the <INPUT TYPE=CHECKBOX … > tag. They allow multiple options to be selected or deselected from a group of options. When the form is submitted, those items that were checked will have their corresponding CobolScript variables populated with the VALUE specified for that check box item. Here is some example HTML for checkbox controls:

<B>FIELD6:</B> <INPUT TYPE=CHECKBOX NAME=”field6” VALUE=”Item1111”>Item1111<BR>

<B>FIELD7:</B> <INPUT TYPE=CHECKBOX NAME=”field7” VALUE=”Item2222”>Item2222<BR>

<B>FIELD8:</B> <INPUT TYPE=CHECKBOX NAME=”field8” VALUE=”Item3333”>Item3333<BR>

<B>FIELD9:</B> <INPUT TYPE=CHECKBOX NAME=”field9” VALUE=”Item4444”>Item4444<BR>

<B>FIELD10:</B><INPUT TYPE=CHECKBOX NAME=”field10” VALUE=”Item5555”>Item5555<BR>

<B>FIELD11:</B><INPUT TYPE=CHECKBOX NAME=”field11” VALUE=”Item6666”>Item6666<BR><BR>

Each checkbox field must have its own corresponding CobolScript variable, like this:

5 field6 PIC X(20).

5 field7 PIC X(20).

5 field8 PIC X(20).

5 field9 PIC X(20).

5 field10 PIC X(20).

5 field11 PIC X(20).

Using Hidden Fields


Hidden fields are actually just another type of CGI input, but they are special enough to warrant a section all their own. They are HTML form fields that are not visible in the browser window, but are still part of the underlying HTML form. They are useful for storing and passing information to the recipient program, and they can be used to maintain program continuity through a series of CobolScript-created pages without directly displaying all data to the browser window, and without writing to a temporary file. The sample problem tracking system uses hidden fields in the HTML forms it displays; figure 7.2 is a capture of the Update screen.


Figure 7.3 shows the HTML source to the screen in 7.2, complete with hidden HTML form fields. You can see the fields update-record and record-key have a TYPE=“hidden”.

When this form is submitted, the field update-record will pass a value of “T” to the CobolScript variable update-record. The form field record-key will pass a value of 00000007 to the CobolScript variable record-key. These fields are hidden on this form because we do not want them to be edited by the user. The record-key is used to determine which record needs to be updated after the form is submitted. This program is the Problem Tracking System example application (PRB.CBL) that comes with the sample programs included with CobolScript.

When you look at the source of the HTML form in Figure 7.3, you will notice that the hidden field record-key appears on three lines, like this:

<INPUT TYPE=”hidden” NAME=”record-key” VALUE=”

00000007

“>

The HTML is formatted in this way because we used DISPLAYLF to display the group level data item that contained the HTML. Had we used DISPLAY instead of DISPLAYLF, the entire text would have appeared on a single line. More on this below.

Here’s a snippet of the CobolScript group item that contains the hidden field record-key. Here we spread the tag definition across three variables (two of these are implied FILLER variables, but variables nonetheless). This is a useful technique because it allows you to populate the CobolScript variable record-key with a value before displaying the group item:

5 `<INPUT TYPE=”hidden” NAME=”record-key” VALUE=”`.

5 record-key PIC 9(08).

5 `”>`.

Sometimes when interfacing with other systems, particularly those written in Perl, the INPUT fields must be on a single line. In these cases, use DISPLAY than DISPLAYLF to print the relevant group item so that it prints on one line. At any rate, CobolScript is intelligent enough to process HTML forms that contain INPUT tags on single or multiple lines, so you won’t encounter this issue unless you submit CGI data to non-CobolScript programs.

Sending Email from CobolScript Using CGI Form Input

As we discussed in Chapter 6, CobolScript has the capability to send simple emails, and this can easily be linked with data that has been submitted from a form, in order to create an auto-responder. The sample program email.cbl is an example of how to do this. The program is in the sample programs included with CobolScript. Figure 7.4 shows the application screen.

In email.cbl, email is sent using the SENDMAIL statement after fields corresponding to the to-address, from-address, subject, and message have been accepted from CGI input:

MOVE `yourservername.com` TO smtp_server.

SENDMAIL USING to_address

from_address

subject

message server.

When sending an email with this command, you must be sure to supply a valid SMTP server name, which is the name of your sending mail server. CobolScript will then use this server to forward the email to the recipient.


Using CobolScript to Transmit Files

Within HTML, you can provide links to files that can be downloaded by using the anchor tag (<A HREF= … >), but if you do this your users will be able to see the location of the file on your server when they view your HTML source. If you want to hide the location of your files and regulate who downloads files from your site, you can build a CobolScript program to directly send the file to the user’s web browser.


CobolScript can be used to send a file to a client web browser. This is accomplished by sending the appropriate MIME header and then using either the DISPLAYFILE or DISPLAYASCIIFILE commands, depending on whether the file is binary or ASCII text. The user will be presented with a “Save As…” dialog box like the one in Figure 7.5, and will be allowed to save the file.

To use DISPLAYFILE or DISPLAYASCIIFILE, you should first build a program that displays a form that a user will submit when he wants to download a file. Within this form, specify the CobolScript program that will use the appropriate command to transmit the file. Typically this form will contain a submit button, and possibly some additional fields that you will use to validate the user, as in the following:

<FORM ACTION=”/cgi-bin/cobolscript.exe?down.cbl” METHOD=”POST”>

<INPUT TYPE=”hidden” NAME=”user_id” VALUE=”md837653 “>

<INPUT TYPE=”hidden” NAME=”password_id” VALUE=”83fFrR “>

<INPUT TYPE=”hidden” NAME=”file” VALUE=”budgetfile “>

<INPUT TYPE=”Submit” VALUE=”Download”>

</FORM>

When this form is submitted, it will run the program you specify in the ACTION attribute of the FORM tag (down.cbl in this example). Your program can then accept authentication information and decide whether to transmit the file to that particular user based on this information. If you choose to not send the file, you can simply display an error page instead.

After you have validated the authentication information, you can begin transmitting the file to the user. There are two steps to this process. First, you will need to display a special MIME header. This mime header is what prompts the user’s web browser to show the “Save As” dialog box. The file name that you use in your MIME header will be the default file name in the “Save As” dialog box. It is very important that the file size in your MIME header matches the exact file size of the file you wish to transmit; in bytes. If it doesn’t, your file will not be transmitted correctly to the user.

After you have displayed the appropriate MIME header, you can use the DISPLAYFILE or DISPLAYASCIIFILE statement. This will transmit the contents of the file to the client’s web browser after he selects the “Save” button from the “Save As…” dialog.

Here’s a CobolScript code example with the appropriate MIME header and the DISPLAYFILE statement (DISPLAYASCIIFILE could be substituted for DISPLAYFILE below if the file to be transferred is a text file):

MOVE `budget.xls` to xfer_filename

MOVE `octet-stream` to xfer_method

MOVE 420000 TO xfer_filesize

DISPLAY `Content-type: application/` & xfer_method.

DISPLAY `Content-Disposition: inline; filename=` & xfer_filename.

DISPLAY `Content-Description: ` & xfer_filename.

DISPLAY `Content-Length: ` & xfer_filesize.

DISPLAYLF.

DISPLAYFILE download_filename.

By using this technique, you can regulate downloads, and audit which users download your files. You can also build custom text files that will be sent to your users by displaying a MIME header and then displaying individual lines, one line at a time. If you do this, make certain that the amount of data you send matches the Content-Length specified in your MIME header.

Embedding JavaScript in CobolScript Programs

In some cases, you may want to have a portion of your application’s processing take place on the client machine (the browser’s computer). Client-side processing is useful for tasks like edit validations, because user feedback can be more real-time, and can be provided to a user prior to his submitting a form and reconnecting with the web server.

If you want to use client-side processing with CobolScript, we recommend you do it by embedding JavaScript in the HTML displayed by your CobolScript programs. JavaScript is relatively independent of browser manufacturer (it works with current versions of both Netscape® and IE®), runs on the client’s web browser, and is very useful for basic data validation and checking. By embedding JavaScript-enriched HTML in your CobolScript applications, you can also reduce network traffic because checks can be performed on the data before it is submitted to the web for processing. If you’re interested in using JavaScript, a pretty good (and reasonably priced) book for beginners is JavaScript for the World Wide Web, available from Peachpit Press.


Some situations where you might want to take advantage of JavaScript are those that require form fields to be populated or data validation of numeric and alphabetic fields. Figure 7.6 provides an example of a message box generated by JavaScript upon a failed data validation.

The JavaScript function that displays this message box is listed below. It is a small function and can be easily embedded into a CobolScript program that displays HTML to a web browser.

function check_fields(form) {

if

(form.first_name.value==””||escape(form.first_name.value).match(“%”)

!= null){

alert(“You must enter an alphabetic first name.”);

form.first_name.focus();

form.first_name.select();

return false;

}

}

CobolScript lends itself very well to displaying web pages, primarily because the nature of group-level data items allows entire HTML code segments to be isolated in your program (or in copybooks) in simple variable definitions. Because of this, you can create group items comprised of FILLER variables that contain your JavaScript code, and then just display the group level data item. By doing this, you can preserve the visual layout of your JavaScript code, and it will be relatively easy to debug from within your CobolScript program.

Following is an example of a group item named web_page_header that contains our JavaScript code from above:

1 web_page_header.

5 `Content-type: text/html`.

5 FILLER PIC X VALUE LINEFEED.

5 `<HTML><HEAD><TITLE>Validate</TITLE>`.

5 FILLER PIC X VALUE LINEFEED.

5 `<SCRIPT LANGUAGE=”JavaScript”>`.

5 `<!—Hide script from old browsers`.

5 ` function check_fields(form) {`.

5 ` if (form.first_name.value == “”`.

5 ` || escape(form.first_name.value).match(“%”) !=null){`.

5 ` alert(“You must enter an alphabetic first name.”);`.

5 ` form.first_name.focus();`.

5 ` form.first_name.select();`.

5 ` return false;`.

5 ` }`.

5 ` }`.

5 ` // End script hiding -->`.

5 `</SCRIPT>`.

Let’s assume that we saved this variable definition, by itself, as a text file with the name HEADER.CPY. Then, this header and JavaScript are freely available to any CobolScript program, and including this file in any CobolScript program’s variable definition is just a matter of using the COPY or INCLUDE statement to reference the copybook in your program code, like this:

COPY `HEADER.CPY`.

1 other_stuff PIC 99.

.

.

.

Now, the header data can be displayed with this small piece of code:

DISPLAYLF web_page_header.

When this statement executes, all of the variables that comprise web_page_header above will be printed to standard output, which in this case means they’ll be sent to the requesting client’s browser window.

Breaking a web page document into separate group-level data items in this manner can make it very easy to maintain, and using copybooks to store these items can be a real timesaver when modifications to the group items have to be made.





Web Programming Tutorial Part 2 - An Introduction to CGI Programming


This tutorial is a good starting point for anyone who wants to learn web programming. We will explain what CGI programming is, and how it is used for web development.



What is CGI?

CGI is an acronym for Common Gateway Interface. It is the most common method of server-side programming on the World Wide Web. CGI is used to process information that is submitted by HTML forms.




How does it work?

When you submit a HTML form, the ACTION tag in the HTML specifies a program to execute on the server. This program is called a "CGI Program". It receives a stream of data from your web browser, parses/decodes the data, processes the data, and sends a stream of HTML back to your browser.


The following is an example of an HTML form with two Text Boxes and a Submit Button. When the Submit Button is pressed, the CobolScript interpreter will execute the veninqry.cbl program. This is very similar to running "cobolscript.exe veninqry.cbl" from the DOS Prompt or an xterm, except that a "?" is used where a " " space would be used in the command prompt.


<FORM METHOD=POST ACTION="/cgi-bin/cobolscript.exe?veninqry.cbl">

<INPUT TYPE=TEXT NAME="vendornumber" SIZE=30>

<INPUT TYPE=SUBMIT VALUE="Find Vendor">

</FORM>


The CobolScript program "veninqry.cbl" will execute the ACCEPT DATA FROM WEB PAGE command.

       01 misc-variables.
          05 ws-content-length           pic 9(05).
          05 vendornumber                pic X(20).
          05 accountcode                 pic X(100).
       main.
           accept data from webpage.
           display `Content-type: text/html`.
           display linefeed.
           display `<HTML><BODY>`.
           display `vendornumber: ` & vendornumber & `<BR>`.
           display `accountcode: `  & accountcode  & `<BR>`.
           display `</BODY></HTML>`.
              :
              :
              :
           stop run.


This command automatically receives the input data stream, parses/decodes the data, and copies the contents of the fields "vendornumber" and "accountcode" from the web page into CobolScript variables named "vendornumber" and "accountcode". Now the program can execute whatever business logic is required. Any HTML that is DISPLAYed by the CobolScript program will be seen in the users web browser. Click here to see some examples of CobolScript programs. You will be allowed to run the programs on our server and view the source code. CobolScript is a very straight-forward web programming language.