IBM ILE RPG CGI Tool Set (CGIDEV2) Library

Version 2005-03-10 20:21:21


Mel Rothman, CEO of Mel Rothman, Inc., wrote these tools when he was an IBM employee in the IBM Custom Technology Center in Rochester, Minnesota.

Mel continues to enhance and support CGIDEV2 on a voluntary, as-available basis. Enhancements and fixes are contributed to IBM at no charge and are distributed by IBM via its Easy400 web site.

IBM is CGIDEV2's owner and copyright holder.

Dr. Giovanni Perotti, IBM Italy, used CGIDEV2 to build the IBM Easy400 site, which contains CGIDEV2 and many additional tools and tutorials written by him.

All the materials on the Easy400 site are available at no charge.


Contents

Disclaimer
Copyright notice
Purpose and benefits
Distribution
Support for CGIDEV2 and other EASY400 Tools
Prerequisites
Sample Programs
The CGISRVPGM2 Service Program
Modules and their subprocedures

Object List

Tips



DISCLAIMER

The following applies to each CGIDEV2 library source code member.

This material is provided by IBM for illustrative purposes only and has not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of this material. IBM provides no program services for this material. All material contained herein is provided to you "AS IS" without any warranties of any kind. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY DISCLAIMED. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSIONS MAY NOT APPLY TO YOU. IN NO EVENT WILL IBM BE LIABLE TO ANY PARTY FOR ANY DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY USE OF THIS MATERIAL, INCLUDING, WITHOUT LIMITATION, ANY LOST PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN IF WE ARE EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

.

COPYRIGHT NOTICE

(C) Copyright IBM Corp. 1999, 2005
All rights reserved.
US Government Users Restricted Rights -
Use, duplication, or disclosure restricted
by GSA ADP Schedule Contract with IBM Corp.

Licensed Materials - Property of IBM


Purpose and benefits

CGIDEV2 provides tools that make it easier to write, test, debug, and maintain ILE CGI programs.

Two types of tools are included:

The sample programs: Major benefits provided by the service program are:

Distribution

CGIDEV2 is distributed without charge from IBM's Easy400 web site.


Access the site for instructional materials, the code itself, instructions, tutorials, and many more useful tools.

Support for CGIDEV2 and other EASY400 Tools


Prerequisites


Sample Programs

The sample programs are:

The sample programs extensively use the subprocedures contained in the CGISRVPGM2 service program.

Because most of the required CGI functions are performed by the CGISRVPGM2 service program, the mainline sample programs' source members are compact.

The CGIDEV2's library's source file members are commented to assist you in understanding their functions. You might want to concentrate on the following QRPGLESRC members:




The CGISRVPGM2 Service Program

Prototypes for CGISRVPGM2's subprocedures are in QRPGLESRC, member PROTOTYPEB.

Binding source is in QSRVSRC, member CGISRVPGM2.

Getting and parsing the browser's input

Two subprocedures are provided for getting input from the browser: GetInput and ZhbGetInput.

ZhbGetInput and its related subprocedures are recommended because they take advantage of the latest and best IBM APIs, are the easiest to use, and are designed to handle up to 16 MB of input from the browser.

It is recommended that you not write CGI programs that expect anywhere near this much input!

The following table describes how ZhbGetInput, GetInput, and their related subprocedures work, and how parsing is performed for each.

GetInput Subprocedure ZhbGetInput Subprocedure
How it processes input GetInput uses the server's QtmhGetEnv and QtmhRdStin APIs. Upon return, browser input, the request method, and content length are found in user-specified variables.

The very early versions of the "classic" HTTP server operated only in %%MIXED%% mode. If you do not use %%MIXED%% mode (and, you shouldn't), you can skip the following paragraph that explains how GetInput uses the FixMixed subprocedure to handle it. You can also skip the "Escape Sequence Handling" discussion following this table.

GetInput calls the FixMixed subprocedure, which checks the CGI_MODE environment variable. If CGI_MODE is %%MIXED%% or %%MIXED/MIXED%%, FixMixed uses the CGI_EBCDIC_CCSID and CGI_ASCII_CCSID environment variables to determine the proper CCSIDs, builds a translation table using the CDRCVRT system API (Convert a Graphic Character String), and converts any escaped characters from their ASCII code points to the corresponding EBCDIC character (if the escape sequence occurs in a variable's name) or the corresponding EBCDIC escape sequence (if it occurs in a variable's value). See Escape sequence handling, below. If CGI_MODE is not %%MIXED%% OR %%MIXED/MIXED%%, FixMixed does nothing.

ZhbGetInput uses the server's QzhbCgiParse, QtmhGetEnv, and QtmhPutEnv APIs.

It stores the browser's input in dynamically allocated structures in the service program, enabling subsequent high speed retrieval by the subprocedures listed below in this table.

ZhbGetInput can handle up to 32767 input variable instances containing large quantities of data (it's internal buffer is dynamic and can grow up to 16 MB). Each variable can be up to 64000 bytes in length. For variables expected to be between 37268 and 64000 bytes in length, ZhbGetVarPtr must be used. Otherwise, ZhbGetVar, ZhbGetVarUpper, or ZhbGetVarPtr can be used.

ZhbGetInput returns the number of unique variable names found (variables with multiple occurrences count as one).

If the REQUEST_METHOD is POST, the contents of the QUERY_STRING environment variable are returned in a variable and the QUERY_STRING environment variable is set to null.

Note: For both the original HTTP Server and the HTTP Server Powered by Apache, QzhbCgiParse requires that the CGI_MODE environment variable not be %%MIXED%% of %%MIXED/MIXED%%. If this condition is not met, a message is forced into the debugging file and the program continues until it fails.

Valid parsing subprocedures CvtDb alone or in combination with CgiVarCnt, CgiVarVal, and CgiVarValUpper.

Alternatively, CgiVarCnt, CgiVarVal, and CgiVarValUpper can be used without CvtDb.

ZhbGetVarCnt, ZhbGetVar, ZhbGetVarUpper, ZhbGetVarPtr, ZhbCountAllVars, ZhbGetVarDetails
Handling multiple occurrences of the same variable

The same variable can appear multiple times in a document's input. Examples include select boxes with the MULTIPLE attribute and input forms that contain rows of repeating input variables.

CvtDb cannot handle multiple occurrences.

Use CgiVarCnt to find out how many times the variable occurs.

Then, retrieve each occurrence's value with CgiVarVal or CgiVarValUpper.

Use zhbgetvarcnt to find out how many times the variable occurs.

Then, retrieve each occurrence's value with ZhbGetVar, ZhbGetVarPtr, or ZhbGetVarUpper.

Escape sequence handling

Skip this section if you are not using %%MIXED%% mode. It is here only because the code is still included for compatibility reasons. Nobody should be using %%MIXED%% mode!

This section addresses a problem that existed in very early versions of the HTTP server, when the only CGI_MODE was %%MIXED%% (it didn't even have a name then).

HTTP (HyperText Transfer Protocol), requires that requesters (browsers) send certain characters as 3-character escape sequences (%HH), where HH is the two hexadecimal characters for the ASCII character.

For example, a comma is %2C, where 2C is the comma's ASCII code point. If the CGI_MODE environment variable is %%MIXED%% or %%MIXED/MIXED%%, the HTTP server does not translate the %2C to %6B, the comma's EBCDIC code point. When %2C subsequently is converted to an EBCDIC character, it is not a comma.

The FixMixed subprocedure corrects this problem.

Although FixMixed is not directly referenced by the sample programs, it can be used if necessary.

Externally described output HTML

This feature allows CGI programs to build dynamic HTML using externally described data in a manner similar to display file DDS. The external data, which can be in a stream files or source physical file members, contains named sections, the equivalent of record formats.

The records within a section, contain substitution variables, which like DDS variables, are filled in at run time when the section is written.

The externally described HTML is processed by the service program subprocedures described below under "Externally described HTML subprocedures."

Most HTML changes can be made in the stream files or source members without modifying or recompiling the CGI program.

A section record, which defines where a section begins, starts with a section delimiter in column 1, followed immediately by the section name. An optional end section delimiter can follow the section name. The default section delimiter is /$ without an ending section delimiter. Different delimiters can be used by passing them as optional parameters to the GetHtmlIfsMult, GetHtmlIfs, or GetHtml subprocedure.

The default section delimiter was decided upon during the early development of CGIDEV, CGIDEV2's predecessor. /$ sometimes fails with CCSIDs (coded character set identifiers) other than those used in the United States.

Delimiters that make the section record into a valid HTML comment work much better. For example:

  <!-- _top -->

uses

'<!-- _'
as the starting delimiter and
' -->'

as the ending delimiter.

A special section name, noname, is used for any records that appear before the first section record in the first file.

Substitution variable names are enclosed between two delimiters. The defaults are /% and %/; different delimiters can be used by passing them as optional parameters to the GetHtmlIfsMult, GetHtmlIfs, or GetHtml subprocedures.

Substitution variable values are set with the UpdHtmlVar or UpdHtmlVar2 subprocedure.

Variable substitution is performed by the WrtSection subprocedure. If a substitution variable's value has not been set, WrtSection substitutes either the default string, **Missing Data**, unless overridden by a string passed via WrtSection's NoDataString parameter.

In the following example, when the HTML in the tablerow section is written, the string /%days%/ is replaced by the value of the days field and the string /%hours%/ is replaced by the value of the hours field.

Note that section names and substitution variable names are not case-sensitive.

RPG source

callp     UpdHtmlVar('DAYS':days)
callp     UpdHtmlVar('hours':hours)
callp     WrtSection('tablerow')

HTML source

Note that in this example, the default section delimiter, /$, is being overridden by <AS400>.

<AS400>tablerow
<TR>
<TD>/%days%/</TD><TD>/%HOURS%/<TD>
</TR>
...next section

Externally described HTML subprocedures

Externally described HTML subprocedures - maximums

Description Maximum
Source record length
For GetHtmlIfs and GetHtmlIfsMult: About 32765 bytes per line; for GetHtml: 240 bytes (228 bytes for source data)
Total number of records. This is not a "per file" number. If GetHtmlIfsMult is used, the sum of the records read from all files may not exceed this number. 32767
Number of unique substitution variables (each may appear multiple times in the source) 32767
Number of occurrences of substitution variables in the externally described HTML As many as will fit in 32767 HTML records as long as there are no more than 32767 unique substitution variable names.
Substitution variable name length 30 characters
Substitution variable value 1000 characters
Substitution variables' delimiter's length 20 characters
Number of sections 1000
Section name length 50 characters
Section name delimiters' length 10 characters
Number of bytes of HTML that can be buffered before writing to the browser or a stream file Approximately 2 terrabytes. This many bytes will take a very long time to process. It is recommended that you not try to test it.

Subprocedures for formatting and sending HTML messages to the browser

When errors are found in the user's input, it is often necessary to send one or more messages to the browser. Formatting and outputting such messages can be tedious, repetitive, and error-prone.

Subprocedures for creating and reading HTTP cookies

Environment variable subprocedures

Debugging subprocedures

The debugging subprocedures use physical file CGIDEBUG, which has two fields: a time stamp and a 500 byte text field.

Error detection and reporting

The sample programs and the service program, use a program status data structure template and a program status subroutine to trap and report program status errors. They:

General purpose counter subprocedure

The Countp subprocedure keeps track of counts (e.g. page hits) using a keyed physical file, CGICOUNT. A key (page name, program name, etc.) is passed to Countp. It adds one to the existing count for that key and returns the updated counter. If the key doesn't exist, a record with its count initialized to 1 is added to the file and 1 is returned to the caller.

Data handling subprocedures

Persistence subprocedures

CL commands subprocedures

Random numbers subprocedures

Saving and restoring state information

Because: methods for storing and retrieving state information are required.

iSeries user spaces objects are ideal for this purpose: Sample program CGIDEV2/STATE is a simple example of this technique.

User space subprocedures


IFS subprocedures


Modules and their subprocedures

The following table lists the source members that comprise CGISRVPGM2. Brief descriptions of each member's subprocedures are included.

Module Subprocedures
XXXCGIPARS Subprocedures that use IBM's new-in-V4R3M0 QzhbCgiParse API for getting and parsing input from the browser. Examples of these subprocedures appear in the TEMPLATE3, TEMPLATE4, TEMPLATE5, DSPENCODE2, PERSIST, and STATE sample programs.

It is recommended that these subprocedures be used for getting and parsing browser input.
ZhbGetInput
Uses the QzhbCgiParse API to get the browser's input and place it into a set of dynamically allocated internal arrays for subsequent high performance use by the ZhbGetVar, ZhbGetVarUpper, ZhbGetVarPtr, and ZhbGetVarCnt subprocedures.

ZhbGetInput must have been run before using any of the remaining subprocedures, below.
ZhbGetVarCnt
Returns the number of times a variable appears in the browser's input.
ZhbGetVar
Returns the value of a variable's nth occurrence in the browser's input.
ZhbGetVarPtr
ZhbGetVarPtr provides a way to process browser inputs that exceed ZhbGetVar's maximum size of 32767 bytes. It returns a pointer to the variable's nth occurrence in the browser's input. A output parameter contains the variable's size in bytes. The data can then be processed with based variables.
ZhbGetVarUpper
Same as ZhbGetVar, but converts the data to upper case.
ZhbCountAllVars
Returns number of occurrences of all variables in the CGI input. ZhbGetInput must have been run before calling this subprocedure.
ZhbGetVarDetails
Returns detailed information for the nth variable of all variables counted by ZhbCountAllVars. Returns the variable's name, value, and occurrence.
XXXCGIVARS Parsing subprocedures that were written before QzhbCgiParse became available in V4R3M0. Examples of these subprocedures appear in sample programs TEMPLATE, TEMPLATE2, and TEMPLATE3.

For getting and parsing browser input, it is recommended that you use ZhbGetInput and its related subprocedures rather than these subprocedures .

CgiVarCnt
Returns the number of times a cgi variable's name appears in the browser's input.
CgiVarVal
Returns the value of the nth occurrence of a cgi variable in the browser's input.
CgiVarValUpper
Same as CgiVarVal, but converts the data to upper case.
XXXCOOKIES Subprocedures for writing and reading HTTP cookies.
CrtCookie
Builds and creates a standard HTTP set-cookie response header in the form:
Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
The user can specify the cookie's name, value, path, domain, whether it is secure, and when it expires in time stamp format. If an expiration time stamp is specified, CrtCookie converts it to the form required by the cookie standard.
GetCookieByName
Returns the value of a cookie having a specified name. Since a cookie's name can occur more than once, the user can specify which occurrence is wanted. If the occurrence does not exist, GetCookieByName returns a null string.
XXXCOUNT
Countp
General-purpose counting routine for keeping track of and reporting the number of times a specified function has been performed.

Uses database file CGICOUNT. Input is a string used as CGICOUNT's key. Output is the incremented count associated with that key.

XXXCVTDB
CvtDb
A simplified interface to the HTTP server's QtmhCvtDb API.

It is recommended that ZhbGetInput and its related subprocedures be used instead of Cvtdb.
XXXDATA Subprocedures for manipulating data.
Char2Hex
Converts a character string to its hexadecimal representation. For example: ABC is converted to C1C2C3.
Hex2Char
Converts a hexadecimal character string to its character representation. For example: C1C2C3 is converted to ABC.
C2N2 (preferred)
Converts a character string to a packed 30.9 number.

Call subprocedure ChkNbr to validate the string before calling C2N2.
C2N (old, not preferred)
Converts a character string to a floating point number.

Call subprocedure ChkNbr to validate the string before calling C2N.

Because floating point numbers often have precision problems, it is recommended that C2N2, which returns a packed result and runs faster, be used instead of C2N.
ChkNbr
Checks a character string to determine whether it can be converted to a number.

When errors are found and the appropriate optional parameters have been used, ChkNbr adds messages to the service program's message arrays.
xlatWCCSIDs
Uses CCSIDS to translate varying length strings up to 32767 characters in length
Uppify
Converts a character string to upper case.
XXXDEBUG Subprocedures for working with the debugging file, CGIDEBUG.
IsDebug
Returns a one-character value indicating whether debugging is on ('1') or off ('0').

Debugging is controlled by CGIDEV2's CGIDEBUG command.
SetNoDebug
Sets a global indicator variable in the service program that controls whether the debugging subprocedures do any work.

Because SetNoDebug sets a global variable in the service program, all CGI programs running in the same activation group are affected in the same way by the most recent execution of SetNoDebug.

Setting the indicator on significantly improves performance, but results in no debugging output being produced by any of the activation groups programs.

It is recommended that SetNoDebug(*on) be used only when all the CGI programs in an activation group have been tested thoroughly and performance is of utmost importance.
WrtDebug
If debugging is on or the force parameter is set to *on, writes its input into the CGIDEBUG file.
WrtPsds
Uses WrtDebug with the force option to writes into the CGIDEBUG file, the program status information passed to it as input.
WrtJobDbg
If debugging is on or the force parameter is set to *on, writes the qualified job name into the CGIDEBUG file.

In addition to the debugging procedures described above, the CGIDEBUG command is used to:

  • turn debugging on or off,
  • display debugging status,
  • display or clear the CGIDEBUG file's member
XXXDOCMD
DoCmd
Accepts a command string and returns a return code. Uses QCMDEXC to execute the command and returns 0 (okay) or 1 (error).
XXXENVVARS

Subprocedures for working with environment variables

GetEnv
Accepts an environment variable name and the system-standard error data structure and returns the environment variable's value.
PutEnv
Accepts a string that defines an environment variable and the system-standard error data structure. Creates or updates the environment variable.
ContLen
Returns the content length environment variable's contents as a 4-byte signed integer.
XXXERRNO
Errno
Returns C's errno environment variable as an integer
ErrnoTxt
Accepts a C Errno as a 4 byte integer and returns the associated error text
XXXFIXMIXED
FixMixed
Used by the GetInput subprocedure to convert ASCII escape sequences to EBCDIC escape sequences if the CGI_MODE environment variable is %%MIXED%% OR %%MIXED/MIXED%%.

It should not be necessary to call FixMixed directly and ZhbGetInput should be used instead of GetInput.
XXXHTMLMSG
AddMsg
Adds a message and its indentation level to the messaging arrays stored in the service program.
ClrMsgs
Clears the messaging arrays and sets their count to 0.
CfgMsgs
Overrides the default names used by WrtMsgs when sending message data to the browser.

The default names are msgtext (field name for the message text), msgstart (section name for start of messages), msgl1 (section name for level one messages), msgl2 (section name for level 2 messages), msgl3 (section name for level 3 messages), and msgend (section name for end of messages).
GetMsgCnt
Returns the number of messages currently stored in the message arrays.
WrtMsgs
Writes the messages from the message arrays to the browser, using the variable and section names noted in the discussion of CfgMsgs, above.
XXXIFS
ChkIfsObj2
Checks for the existence of and accessibility to an IFS object
XXXINPUT
GetInput
Receives and returns the browser's input data, the number of bytes received, and the request method used. Uses the server's QtmhGetEnv and QtmhRdStin APIs.

It is recommended that the newer and more powerful ZhbGetInput be used instead of GetInput.

GetInput:
  • retrieves the REQUEST_METHOD environment variable.
  • if GET, the QUERY_STRING environment variable's contents are placed into the input data buffer
  • if POST, the CONTENT_LENGTH environment variable is retrieved, content_length bytes are read from standard input, and those bytes are placed into the input data buffer
  • The number of bytes received and request method are returned as variables.
XXXPERSIST
GetSessionId
Builds a session id that can be used with the Accept-HTSession response header for achieving CGI persistence. The session id comprises the 6-digit job number concatenated with up to 9 random digits.

It is recommended that persistent CGI be used only when commitment control is required. Otherwise, there are fewer problems and better performance with non-persistent CGI. CGIDEV2's CrtUsrSpc and RtvUsrSpcPtr subprocedures greatly simplify the tasks of storing and retrieving state information across multiple interactions with a user.
XXXRANDOM
random
Returns a 4-byte unsigned integer (up to 10 digits, maximum value of 2147483646) whose value lies between the two values passed as inputs. The minimum input value is 1; the maximum input value is 2147483646.
randomString
Returns a varying length random string up to 1024 bytes in length formatted as requested by the user. The caller specifies the following parameters (only the first is required):
  • the number of characters to return
  • the format (upper case, lower case, mixed case, with or without digits) of the first character
  • the format of the remaining characters
  • what characters are considered to be upper case
  • what characters are considered to be lower case
  • what characters are considered to be digits
XXXTIME
TimerStart
Stores the current software timer's value in the CGISRVPGM2 service program.
TimerElapsed
Returns the number of seconds that have elapsed since the last call to TimerStart. If TimerStart has not been run, TimerElapsed runs TimerStart and returns zero. Otherwise, it does NOT reset the timer start value.
XXXUSRSPC
CrtUsrSpc
Creates a user space in a caller specified library. The user space name, which is the subprocedure's return value, is randomly generated. Makes the user space automatically extendible.

Defaults or user specified values are used for public authority, text, initial size and extended attributes.

Returns in parameters the user space's pointer and a 7 character message ID (blank if no errors; otherwise a message ID).
RtvUsrSpcPtr
Returns a pointer to an existing user space. If the user space or its library cannot be found, a null pointer is returned.
XXXWRKHTML
ClrHtmlBuffer
Clears the HTML output buffer.

This is useful
  • when program logic dictates that you need to output something other than what has already been buffered
  • to ensure at the beginning of your program that the buffer contains no data from a previous, abnormally ended program execution
CrtTagOpt
Outputting selection lists can be difficult with externally described HTML when the <OPTION> tag to receive the SELECTED attribute varies depending on the value of data fields in the CGI program.

The CrtTagOpt subprocedure makes this easier.

CrtTagOpt's inputs are: an <OPTION> tag's value attribute and the associated text. If the optional third parameter is passed, and it matches the first parameter, the SELECT attribute is added to the formatted <OPTION> tag.

CrtTagOpt's output is a fully formatted <OPTION> tag.

For example:

CrtTagOpt('AZ':Arizona) returns <option value="AZ">Arizona</option>

CrtTagOpt('AZ':Arizona:'AZ') returns <option value="AZ" SELECTED>Arizona</option>

CrtTagOpt('AZ':Arizona:'MN') returns <option value="AZ">Arizona</option>

Encode
Sometimes it is necessary to display HTML tags as data, without having the browser process them as active HTML.

The Encode subprocedure converts a varying length input field to a varying length return value, in which any occurrences of the special HTML characters " & < or > are converted to their corresponding HTML character entities, &quot; &amp; &lt; and &gt;.

Encode2

The Encode2 subprocedure, similar to Encode, converts a varying length input field to a varying length return value, in which any occurrences of the special HTML characters are converted to their corresponding HTML character entities. Encode2 retrieves the list of characters and related character entities from an IFS file. For more details, see the encode2 prototype in QRPGLESRC member PROTOTYPEB.

EncodeBlanks
Sometimes it is necessary to display multiple consecutive blanks without having the browser convert them to a single blank.

The EncodeBlanks subprocedure converts a varying length input field to a varying length return value, in which any occurrences of the blank character is converted to a non-breaking space, &nbsp;.

GetHtml
GetHtml retrieves and formats externally described HTML from a source physical file.

It is recommended that GetHtmlIfs or GetHtmlIfsMult be used instead. See, "GetHtmlIfs and GetHtmlIfsMult," below, for more information.

GetHtml accepts the source physical file's name, library name, and member name.

An optional parameter can be passed to override the default starting section delimiter from /$ to a delimiter of your choice (e.g. <AS400>).

An optional parameter can be passed to add an ending section delimiter (e.g. </AS400>).

Optional parameters can be passed to override the default delimiters for variable names from /% and %/ (e.g. <var> and </var>).

GetHtml reads the file and builds internal arrays that are used later to send HTML sections, including variable substitutions, to the browser.

To enhance performance, if the CGI program is persistent or is running in a named activation group, the source physical file is not reread if its time stamp has not changed from when it was last read.

GetHtmlBytesBuffered
Returns the number of bytes of HTML buffered but not yet sent to the browser nor written into a stream file. This count is reset to 0 when the data are output, either to the browser with WrtSection('*fini') or to a stream file with WrtHtmlToStmF.

The maximum number of bytes that can be buffered is approximately 2 terrabytes.

GetHtmlIfs and GetHtmlIfsMult
These subprocedures retrieve and format externally described HTML from IFS stream files.

GetHtmlIfs is the older subprocedure and can access only one stream file.

GetHtmlIfsMult is newer, and can access one or more stream files. In addition, GetHtmlIfsMult returns a data structure of indicators that tells you whether it was successful, and if not, why.

Storing externally described HTML in the IFS has the following advantages:
  • There is no real limit to the length of a line
  • By mapping the IFS to a PC's drive letter, you can easily use HTML editing and/or generating tools
  • GetHtmlIfsMult allows multiple IFS stream files to be read as if they are one. Therefore, common HTML can be stored in one or more files, and HTML for a particular file can be stored in its own file. At run time, all the files are read and processed as one.

GetHtmlIfs
Accepts the name of an IFS stream file that contains externally described HTML.

Optional parameters for overriding the default delimiters for section names and variable names are the same as those for GetHtml.

GetHtmlIfs reads the file and builds internal arrays the are used later to send HTML sections, including variable substitutions, to the browser.

To enhance performance, if the CGI program is persistent or is running in a named activation group, the stream file is not reread if its last changed time stamp has not changed from when it was last read.

GetHtmlIfsMult
Accepts the names of one or more IFS stream files that contain externally described HTML. The files are read in the order specified and are processed as if they comprised one file.

This subprocedure is useful when multiple CGI programs build similar pages that contain common headings, menu bars, navigation bars, footings, etc. The common HTML can be stored in one or more externally described HTML files, and each CGI program's unique HTML can be stored in its own file. Each CGI program uses GetHtmlIfsMult to read the common file(s) and its own file.

Optional parameters for overriding the default delimiters for section names and variable names are the same as those for GetHtml.

GetHtmlIfsMult reads the files and builds internal arrays the are used later to send HTML sections, including variable substitutions, to the browser.

To enhance performance, if the CGI program is persistent or is running in a named activation group, the stream files are not reread if all of the files' last changed time stamps have not changed from when they were last read.

RtvHtmlRcd
Retrieves a single record by relative record number from the externally described HTML.

Input parameters are section name (or *NONE) and a relative record number.

If a section name is specified, the relative record number is within the section.

If the section name *NONE is specified, the relative record number is within all the HTML.

RtvSubsVarInfo
Retrieves information about substitution variables from the externally described HTML.

Input parameters are section name (or *NONE) and a sequence number.

If a section name is specified, the sequence number refers to the variable's relative position in the section.

If the section name *NONE is specified, the sequence number is relative to all the HTML.

UpdHtmlVar

Adds or updates variable names and values stored in dynamically allocated arrays in the service program. An optional parameter is used to initialize the arrays. These arrays are used to perform variable substitutions when HTML sections are written.

UpdHtmlVar2

Works like UpdHtmlVar but passes a pointer and a length to enable up to 16 MB of substitution data.

WrtHtmlToStmf

Writes, then clears, the contents of the service program's high performance, dynamically allocated HTML buffer into a user-designated stream file.

To minimize the time during which an existing file would be unavailable, WrtHtmlToStmf

  • Creates a temporary file and writes the HTML into it
  • Unlinks the target file if it exists
  • Links the target name to the temporary file
  • Unlinks the temporary file name.

If anyone is using the original file, the system defers the unlink activity until the last user finishes using it. Then, since the file has no links, the system deletes it.

WrtNoSection

Writes data, without using sections or performing variable substitution, to a high performance, dynamically allocated buffer in the service program. The buffer is emptied and sent to the browser when the special section named *fini is written. Alternatively, the WrtHtmlToStmf subprocedure can be used instead of WrtSection(*fini) to empty the buffer's and write its contents into a user-designated stream file.

WrtSection

Writes one or more sections of HTML to a high performance, dynamically allocated buffer in the service program. The buffer is emptied and sent to the browser when the special section named *fini is written. Alternatively, the WrtHtmlToStmf subprocedure can be used instead of WrtSection(*fini) to empty the buffer's and write its contents into a user-designated stream file. WrtSection's nonewline parameter can be specified to force it not to append a newline character (x'15') to each HTML record.


Object List

This is a brief description of the objects that comprise the ILE RPG sample programs, their source, and related tools and files.

Programs and commands

CGIDEBUG command, CGIDEBUG program, and CGIDEBUG data area; CLRDEBUG program.
The CGIDEBUG command controls the built-in debugging facilities (*ON *OFF *DSP *DSPDATA *CLRDATA). Program CLRDEBUG is used by CGIDEBUG to delete all records from the target debugging file when a file lock prevents CLRPFM from clearing it.
CGISRVPGM2 service program
Performs most of work done by its calling CGI programs. Many of its tools can also be used by non-CGI programs.
DSPENCODE2 program
CGI program that displays character entity data from files used by the encode2 subprocedure.
DSPVERSION program; VERSION data area
CGI program that displays CGIDEV2's current version
PERSIST program
Sample persistent CGI program.
RANDOMNBRS program and command
Sample non-CGI program and command that demonstrates how to create an HTML stream file using externally described HTML and CGIDEV2 subprocedures. This is useful for information that is updated periodically but remains static between updates. This technique avoids the performance costs of running a CGI program every time the information is requested. It uses HTMLSRC source physical file member RANDOMNBRS. To use this demonstration program, run the command from the command line or from a batch program to create a stream file in a directory served by your server. Then use a browser to display the stream file. Then repeat and observe the updated static page.
RMVSRCRCDS non-CGI program and command.
The RMVSRCRCDS command removes specified records from a source file member. The command processing CL program is RMVSRCRCDS. It calls RPG program RMVSRCRPG. Use the RMVSRCRCDS command to remove comments and/or code from copies of sample programs in order to use them as starting points for new programs.
STATE program
Sample non-persistent CGI program that uses a user space to save and restore state information.
TEMPLATE, TEMPLATE2, TEMPLATE3, TEMPLATE4, TEMPLATE5 programs
Sample non-persistent CGI programs. TEMPLATE5 is the preferred sample because it uses the latest, most functional, and best performing CGIDEV2 subprocedures and underlying IBM CGI programming APIs.

Source physical files

Member names and contents can be found in the source files themselves.

Data files

CGICOUNT
File used by Countp subprocedure (general purpose counter).
DATASTRUCT
Externally described data structure used by the TEMPLATE program.
HOURSOP
Hours of operations file used by sample programs TEMPLATE, TEMPLATE2, TEMPLATE3, TEMPLATE4, TEMPLATE5, and PERSIST programs.
CGIDEBUG
Debugging data file used to receive internally generated debugging output from CGIDEV2's subprocedures as well as output from your programs using the WrtDebug, WrtPSDS, and WrtJobDbg subprocedures.

Other objects

TEMPLATE2 *BNDDIR
Contains references to service programs QHTTPSVR/QZHBCGI and CGIDEV2/CGISRVPGM2. This binding directory is referenced in RPG source member HSPECSBND, which is copied into most of CGIDEV2's programs and programs you may derive from them.
VERSION *DTAARA
Contains the current version's date and time. Used to determine whether you have the latest version. CGI program DSPVERSION can be used to display the data area's contents.

Tips

PDM user defined options to create modules, programs, etc.

Useful PDM User-Defined Options
Option Purpose Command
AJ Work with HTTP server's jobs (change JOB parameter to your server's name) WRKACTJOB SBS(QHTTPSVR) JOB(YourHttpServer'sName)
BD Work with binding directory entries (cursor on a binding directory object) WRKBNDDIRE BNDDIR(&L/&N)
CN Create program (named activation group same as program name. Use F4 to prompt for a different activation group name.) SBMJOB CMD(CRTPGM PGM(&L/&N) MODULE(&L/&N) ACTGRP(&N)) JOB(&N)
CP Create program (new activation group) SBMJOB CMD(CRTPGM PGM(&L/&N) MODULE(&L/&N) ACTGRP(*NEW)) JOB(&N)
CR Create bound RPG program using directives in the H-Specs SBMJOB CMD(CRTBNDRPG PGM(&L/&N) SRCFILE(&L/&F) SRCMBR(&N) DBGVIEW(*SOURCE)) JOB(&N)
DB Start debugger STRDBG PGM(&L/&N) UPDPROD(*YES)
ED End debugger ENDDBG
ML Create an ILE-CL Module SBMJOB CMD(CRTCLMOD MODULE(&L/&N) SRCFILE(&L/&F) SRCMBR(&N) DBGVIEW(*SOURCE)) JOB(&N)
MR Create an ILE RPG Module SBMJOB CMD(CRTRPGMOD MODULE(&L/&N) SRCFILE(&L/&F) SRCMBR(&N) DBGVIEW(*SOURCE)) JOB(&N)
RX Start a REXX procedure STRREXPRC SRCMBR(&N) SRCFILE(&L/&F)