Switch to Italian
Giovanni's logo
How to provide HTML responses using externally defined HTML
this means Version 2
index
M
power search
blue line
 
This page shows how to
1. Variables

We recommend you use
  1. command cgidev2/setcgilib to setup the development and execution environments in your source library and object (production) library
  2. command cgidev2/crtcgisrc to create a sample source for a new CGI program. You can compile an run such program.
If you do so, you'll find out that the variables are already defined by copying in other source members:

/copy mysrclib/qrpglesrc,hspecs
/copy mysrclib/qrpglesrc,hspecsbnd
            ... etc. ...
/copy mysrclib/qrpglesrc,prototypeb
/copy mysrclib/qrpglesrc,usec
/copy mysrclib/qrpglesrc,variables3
            ... etc. ...


2. Read skeleton html member into memory

Use subprocedure

  • getHtml to load into memory a single externally defined html source member
  • getHtmlifs to load into memory a single externally defined html IFS (stream) file
  • getHtmlifsMult to load into memory in one shot multiple externally defined html IFS (stream) files
Examples for default section and variables delimiters
  • section name start delimiter:   /$
  • variable name start delimiter:   /%
  • variable name end delimiter:    %/

1) getHtml
C                   eval      HtmlSrcLib = 'CGIDEV2'
C                   eval      HtmlSrcFil = 'DEMOHTML'
C                   eval      HtmlSrcMbr = 'EXERCISE'
C                   callp     gethtml(HtmlSrcFil:HtmlSrcLib:HtmlSrcMbr) 

C                   callp     gethtml('DEMOHTML':'CGIDEV2':'EXERCISE') 

2) getHtmlifs
C                   callp     gethtmlifs('/CgidevExtHtml/talk2ifs.html')
See the example in CGI TEMPLATE4.
Note that the directory to be specified as a parameter of the gethtmlifs procedure is the real directory path, not the alias mentioned in a HTTP pass directive.
The recommendation is -in any case- not to use for the IFS html code directories accessed also by the HTTP server.

3) getHtmlifsMult
This subprocedures allows to load into memory multiple externally defined html files. All the sections and records in all the files are read into dynamic storage as though they resided in a single file. If a section name appears more than once, only the first occurrence is used.
This feature allows to maintain as separate HTML files frequently used pieces of HTML code, such as headers, footers, navigation bars, etc.. In several cases, breaking html code into separate modules may greatly reduce both development and maintenance times.
 * Indicators for GetHtmlIfsMult subprocedure
D IfsMultIndicators...
D                 ds
D  NoErrors                       n
D  NameTooLong                    n
D  NotAccessible                  n
D  NoFilesUsable                  n
D  DupSections                    n
D  FileIsEmpty                    n
   ... etc. ...
 * Read externally defined output html files
C                   eval      IfsMultIndicators = gethtmlifsmult(
C                             '/CgiDevExtHtml/StdTop.Html +
C                             /CgidevExtHtml/StdRunTime.Html +
C                             /CgidevExtHtml/StdMsg.Html +
C                             /CgidevExtHtml/StdPssr.Html +
C                             /CgidevExtHtml/Talk2Stuff.Html +
C                             /CgidevExtHtml/StdEnd.Html')
        
See the example in CGI TEMPLATE5.

Note 1. Subprocedures getHtmlifs and getHtmlifsMult can also load HTML source members as part of the /QSYS.LIB/... directory.
See the following example:
 * Read externally defined output html files
C                   eval      IfsMultIndicators = gethtmlifsmult(
C                             '/CgiDevExtHtml/StdTop.Html +
C                             /QSYS.LIB/MYLIB.LIB/HTMLSRC.FILE/X.MBR')
        

Note 2. When using getHtmlifs or getHtmlifsMult subprocedure, make sure that the IFS files containing the external HTML code can be read from the HTTP server user profile QTMHHTP1 (the one adopted when running CGI). This can be done in one of the following ways (in the examples below, we assume that QPGMR owns the files, but this is not relevant at all):
Data --Object Authorities--
User Authority Exist  Mgt  Alter  Ref 
*PUBLIC  *RX
QPGMR *RWX X X X X
or
Data --Object Authorities--
User Authority Exist  Mgt  Alter  Ref 
*PUBLIC  *EXCLUDE
QPGMR *RWX X X X X
QTMHHTP1 *RX


Examples for user-defined delimiters (see also this page).

First example:

  • section name start delimiter: "<!-- Sec_"
  • section name end delimiter (optional): " -->"
  • variable name start delimiter: "<var400>"
  • variable name end delimiter: "</var400>"
C                   eval      HtmlSrcLib = 'CGIDEV2'
C                   eval      HtmlSrcFil = 'HTMLSRC'
C                   eval      HtmlSrcMbr = 'TALK2'
C                   callp     gethtml(HtmlSrcFil:HtmlSrcLib:HtmlSrcMbr:
C                             '<!-- Sec_':
C                             ' -->':
C                             '<var400>':
C                             '</var400>')

Second example:

  • section name start delimiter: "<as400>"
C                   callp     gethtmlifs('/CgidevExtHtml/talk2ifs.html':
C                             '<as400>')

 * Indicators for GetHtmlIfsMult subprocedure
D IfsMultIndicators...
D                 ds
D  NoErrors                       n
D  NameTooLong                    n
D  NotAccessible                  n
D  NoFilesUsable                  n
D  DupSections                    n
D  FileIsEmpty                    n
   ... etc. ...
 * Read externally defined output html files
C                   eval      IfsMultIndicators = gethtmlifsmult(
C                             '/CgiDevExtHtml/StdTop.Html -
C                             /CgidevExtHtml/StdRunTime.Html -
C                             /CgidevExtHtml/StdMsg.Html -
C                             /CgidevExtHtml/StdPssr.Html -
C                             /CgidevExtHtml/Talk2Stuff.Html -
C                             /CgidevExtHtml/StdEnd.Html':
C                             '<as400>')


3. Assign values to html variables

This must be done using subprocedure updHtmlVar.
This subprocedure assigns a value to all the instances of a given html variable name.
Note 3. The value to be assigned must be a character string (numeric fields must be converted or edited to character strings, see examples number 4 and 5).

Inputs
  • variable name
  • variable value
  • action (optional)
    • '1' = replace this variable if it exists, otherwise add it (default)
    • '0' = clear arrays and write this one as the first
  • trim instructions (optional)
    • %trim - trim left and right (default)
    • %triml - trim left only
    • %trimr - trim right only
    • %trim0 - don't trim

Examples:
  1. Clear all html variables and assign to html variable custname the value contained in character field CusNam:
    C                   callp     updHTMLvar('custname':CusNam:'0')

  2. Assign to html variable custaddr the value contained in character field CusAdr:
    C                   callp     updHTMLvar('custaddr':CusAdr)

  3. Assign to html variable custaddr the value contained in character field CusAdr without trimmimg it:
    C                   callp     updHTMLvar('custaddr':CusAdr:'1':'%trim0')

  4. Assign to html variable ordertotal the value contained in numeric field (9 2) TotThisOrd using an edit code:
    C                   callp     updHTMLvar('ordertotal':
    C                             %editc(TotThisOrd:'J'))                  
           About edit codes

  5. Assign to html variable ordertotal the value contained in numeric field (9 2) TotThisOrd using an edit word:
    C                   callp     updHTMLvar('ordertotal':
    C                             %editw(TotThisOrd:' ,   ,  0.  '))       

    See this living example.


  For vary large output variables (max 16 Mb) you may use subprocedure updHtmlVar2.
In this subprocedure, instead of passing the name or the value of the substituting variable, you will pass a pointer to it and its length.
Inputs
  • variable name
  • pointer to the substituting string
  • length of the substituting string
  • action (optional)
    • '1' = replace this variable if it exists, otherwise add it (default)
    • '0' = clear arrays and write this one as the first
  • trim instructions (optional)
    • %trim - trim left and right (default)
    • %triml - trim left only
    • %trimr - trim right only
    • %trim0 - don't trim

Examples:
 *========================================================================
 * CASE 1 - An IFS stream file that was read into allocated memory
 *        - the allocated memory is pointed by "allocPntr"
 *        - the length of the allocated memory is in variable "allocSize"
D allocPntr       s               *
D allocSize       s             10i 0
 /free
      updHtmlVar2('longdata':allocPntr:allocSize);

 *========================================================================
 * CASE 2 - A fixed length variable "outVar1"
D outVar1         s            2500
 /free
      updHtmlVar2('longdata':%addr(outVar1):%size(outVar1));
      //  OR
       updHtmlVar2('longdata':%addr(outVar1):%len(%trimr(outVar1)));

 *========================================================================
 * CASE 3 - A variable length variable "outVar2"
D outVar2         s           32767     varying
 /free
      updHtmlVar2('longdata':%addr(outVar2)+2:%len(outVar2));
      //  OR
      updHtmlVar2('longdata':%addr(outVar2:*data):%len(outVar2));
        



4. Write html sections and send the output buffer

This must be done using subprocedure wrtsection.
One can write one or multiple sections in a single call.
Important.
Once all sections have been written, do not forget to send the output buffer to the client. This must be done by writing a pseudo section named *fini.

Example:

 * Write a single section
C                   callp     wrtsection('start')
 * Write two sections
C                   callp     wrtsection('part1 part2')
 * Send the output html to the remote browser
C                   callp     wrtsection('*fini')

Note 4. Section names are not case sensitive. A section name is a 50 char max alfanumeric string. Only english letters are supported.

Note 5. Subprocedure wrtSection supports two optional parameters:

  • NoNewLine indicator.
    Set it to *on to tell wrtsection NOT to insert a newline character x'15' at the end of each HTML output line. This may be useful when binary data are being sent to the browser.
  • NoDataString value.
    What to do when a substitution variable is encountered and no value has been set up with UpdHtmlVar.
    If not specified, output variables left without substitutions display the default "**Missing Data**".
Examples:
D NoDataString    c                   '<b>*** no substitution! ***</b>'
 * Write a section without newline characters
C                   callp     wrtsection('mysection':*on)
 * Write a section with non-default warning for
 * missing substitution variables
C                   callp     wrtsection('mysection':*off:
C                             NoDataString)

Note 6. WARNING - wrtSection(*fini) will not perform and return an error message in file CGIDEBUG if the outbut buffer size exceeds 16 Mb.

5. Special output procedures

Subprocedure wrtNoSection
writes data for the browser without using substitution variables or sections.
This subprocedure can be used when a large block of data is to written. This is more likely to happen when writing non-textual data such as images.
The following example shows how to read an external IFS file (an HTML page, an image, or what you need) and how to insert it into the CGI output buffer:
D IfsInpBuff      s          10000a   varying
D InpBuffLen      s             10i 0
D IfsObj          s            255a
D FileHandle      s             10i 0
D ReturnInt       s             10i 0
D BytesIn         s             10i 0
* ... ... ...
* Read an IFS object into "IfsInpBuff"
C                   eval      IfsObj = '/mypath/mysubpath/myobj.xxx'
*   1-Open the IFS file
C                   eval      FileHandle = open(%trim(IfsObj)
C                               : O_RDONLY + O_TEXTDATA)
*   2-Read the IFS file
C                   eval      BytesIn = read(FileHandle
C                               : %addr(IfsInpBuff)
C                               : %size(IfsInpBuff))
*   3-Close the IFS file
C                   eval      ReturnInt = close(FileHandle)
C                   eval      IfsInpBuff = %trim(IfsInpBuff)
* Insert the string read into the CGI output buffer
C     ' '           checkr    IfsInpBuff    InpBuffLen
C                   callp     WrtNoSection(%addr(IfsInpBuff):
C                             InpBuffLen)

WARNING - Be careful not to exceed the 16 Mb limit of the output buffer. If that limit is exceeded, wrtSection(*fini) will fail.


Subprocedure clrHtmlBuffer
clears any HTML output that has been buffered but has neither been sent to the browser nor written into a stream file. This is useful when program logic dictates you need to output something other than what has already been buffered.
C                   callp     clrHtmlBuffer           

Subprocedure getHtmlBytesBuffered
  • Returns the number of bytes in the output HTML buffer.
  • This number is incremented each time output is written with WrtSection or WrtNoSection.
  • It is reset to 0 when either WrtSection('*fini') or WrtHtmlToStmf is run.
  • If this number is allowed to grow to more than 16 MB, the CGI program will fail.
    Could be useful to stop creating an output page when its size exceeds a reasonable limit.
    D buffsize        s             10i 0
    C                   eval      buffsize = getHtmlBytesBuffered

  • Subprocedure getHtmlBufferP
  • Returns the pointer to the output HTML buffer and the number of bytes used in the output HTML buffer.
  • This is expecially useful for debugging.
     D OutBuffer       s          32767    based(OutbufferP)
     D OutBufferInfo   ds
     D  OutBufferP                     *
     D  OutBufferLen                 10u 0
     C                   eval      OutBufferInfo=callp(GetHtmlBufferP)

  • Subprocedure crtTagOpt
  • Returns an HTML tag <option value="...">...</option>
    for use within a <select ...> list.
  • Of course, this is not the only way to create selection lists.
    /$strselect
    <table>
    <tr><td>Please select desired date:</td></tr>
    <tr><td><select name="date">
    /$option
    /%optionvalue%/
    /$endselect
    </select>
            </td></tr>
    </table>
            
         D dates           s             15    dim(3)
         D i               s             10i 0
         D optionValue     s            200    varying
          /free
    
               wrtsection('strselect');
               for i=1 to 3;
                  optionValue=CrtTagOpt(%char(i):dates(i));
                  updhtmlvar('optionvalue':optionValue);
                  wrtsection('option');
               endfor;
               wrtsection('endselect');
    
            

    We have a program that demonstrates the use of subprocedure CrtTagOpt: