SRE2003 manual

The SRE2003 Procedure Library

Description of The SRE2003 functions

The following lists the functions contain in the SRE2003 procedure library. Note that filters (such as SRELite2 or SREhttp/2) may have their own set of functions -- in many cases these provide additional capabilities that addon/script creators may find useful.


Some of the more important functions are: SRE_AUDIT, SRE_AUTH_RESPONSE, SRE_COMMAND, SRE_DATADIR, SRE_ERROR_RESPONSE, SRE_REQFIELD, SRE_SERVER, SRE_SERVERNAME, SRE_WRITE_ERROR, and SRE_WRITE_MESSAGE.

Alphabetical list of procedures
ADD_TH add "st", "nd", "rd", or "th" to a number
SRE_ADDCOMMA Add commas to a number
SRE_APPEND_FILE append a string to the end of a file
SRE_AUDIT write lines to the AUDIT.LOG file
SRE_AUTH_RESPONSEreturn an authorization required response
SRE_CACHE manipulate "caches"
SRE_CACHED return whether the current request was satisfied from the cache
SRE_CACHE_DATA work with the SRE2003 database daemon
SRE_CHECK_USERNAME check username & password against authorization
SRE_CHUNK chunk encode a string
SRE_COMPLETED return whether current request has been completed
SRE_CLIENTNAME do a DNS lookup of an IP name
SRE_CLIENTS lookup number, or list, of currently active clients
SRE_COMMAND recieve and send information to the client, etc.
SRE_COUNTVARS manipulate counter variables
SRE_DATADIR return the default (or host specific) data directory
SRE_DATESTAMP compute a time & date string
SRE_ETAG automatically generate an Etag
SRE_EVENTVARS manipulate event variables
SRE_ERROR_RESPONSEreturn a server error response
SRE_EXTRACT returns settings of several SRE2003 variables.
SRE_EXTRACT_USERNAME extract username from authorization header
SRE_FIX_URL construct a fully qualified URL
SRE_GET_URL get contents of URL
SRE_GET_URL_ADV get contents of URL -- advanced version
SRE_GMT compute a GMT time, incorporating an additional offset
SRE_HTML_ENCODE replace special charaters with HTML entity references
SRE_HTML_REPLACE replace comments in an HTML file
SRE_HOSTINFO read & set host information
SRE_LIST manipulate "lists"
SRE_LIST_STATS compute statistics on values stored in a list
SRE_MD5compute and MD5 of a file or string
SRE_MOVE_RESPONSEreturn a resource moved response
SRE_PACK64 unpack a "pack64" encoded string
SRE_PACK64_MAKE create a "pack64" encoded string
SRE_PACKUR unpack a URL-encoded string
SRE_PACKUR_MAKE create a URL-encoded string
SRE_PAUSE check & set PAUSE status of SRE2003
SRE_PMPRINTF write a message to the PMPRINTF window
SRE_REPLACESTRG replaces occurences of a substring
SRE_READ_FILE read the contents of a file
SRE_REPLACEWILD compare strings & replace portions
SRE_REQFIELD returns the value of a request header
SRE_REQUEST_INFO read "id" info for a request.
SRE_SAY write a message to the bottom of the status screen
SRE_SERVER return descriptive name of the server software
SRE_SERVERNAME return the domain name of the server
SRE_SHUTDOWN shutdown SRE2003
SRE_TEMPFILE return a filename for use as a temporary file
SRE_TRACKIT set and get client specific tracking info
SRE_UNCHUNK unchunk a chunk-encoded string
SRE_VALUE read & set SRE2003 variables
SRE_WRITE_ERROR write a message to the error log and to the status screen
SRE_WRITE_MESSAGE write a message to the status screen
SRE_WILD_MATCH multiple wild card string comparisons

Advanced Users Notes SREAPI.TXT contains further details on working with SRE2003.

SRE_DMN.TXT discusses how you to user SRE's functions that create and manipulate daemons, flags, and queues.


The SRE2003 functions: full descriptions

Technical
Note:
Many of these procedures include an id_info parameter. This parameter is a special transaction identifier that is automatically generated by SRE2003. If you have its current value (it is one of the arguments sent to the filter), providing ID_INFO can speed up processing a bit. However, if you do not have it's current value, then you must leave these ID_INFO parameters blank.

ADD_TH: Write "audit messages"
Return a "st", "nd", "rd" or "th" (as appropriate).

Syntax:
    asuffix=add_th(numeric_value)

Examples:

     say 'This is the 21 '||add_th(21)||' birthday'
     app1=add_th(user_ct) ; say 'You are the 'user_ct||app1' visitor'
SRE_ADDCOMMA: Add commas to a number
Insert commas into a long number:
Syntax:
    newval=sre_addcomma(oldval)

Examples:

  newval=add_comma(1512563) 
  which yields:newval = 1,512,563
SRE_APPEND_FILE: Append a string to the end of a file
Append a string to the end of a file (or create the file if it does not exist). Can also be used to overwrite an existing file.

Syntax:
   astat=sre_append_file(filename,astring,ntries,addcrlf,overwrite)

where:
filename the file to append to
astring the arbitrarily long string to append
ntries Optional. How many times to try and open the file (with a 1 second delay between attempts).
The default is 1 (just try once)
addcrlf Optional. If 1, then astring will always be preceded by a crlf (a '0d0a'x):
  • if filename does not end with crlf, a crlf will be added, and then astring
  • if filename DOES end with a crlf, an extra crlf is NOT added
Notes:
  • The default is 0 (do not add crlf)
  • crlfs at the beginning of astring are never removed.
  • if a '1a'x (Ctrl-Z) currently ends the file, it will be removed.
  • If filename does not exist, a crlf is not added at the beginning
  • A crlf is always added at the end of astring (even if one is already there)
  • overwrite Optional. If 1 then instead of appending, overwrite any existing file (that is, delete an older version, and then write astring to filename).
     
    astat will be:
    • if succesful: the size of filename after appending
    • if an error occurs: an error code followed by an error message.
      The error codes are:
    • -1 = could not open file
    • -2 = problem writing to file

    SRE_AUDIT: Write "audit messages"
    Write a message to the audit file (or to the screen or pmprintf window)

    Syntax:
        astat=sre_audit(mess_hdr,message,whereto,brief)

    where:
    mess_name a short string used to form a message header. The message header helps identify the time and origin of the message.
    message the message
    whereto where to write the message to
    brief Optional. If 1, then only use the mess_name in the message header (suppress the time and process identifers).
    astat SRE_AUDIT always returns a 1

    whereto should be a 3 character long string of 0's and 1's

    For example: 101 means write to audit_file and to screen

    Special values of whereto:

    Notes:

    Examples:

      foo=sre_audit('This is a simple message to the audit file')
      foo=sre_audit('PROC1','Starting loop in proc 1 ',0)
      foo=sre_audit('HELP',' generating new help files ','011',1)

    SRE_AUTH_RESPONSE: Return an authorization response to the client
    SRE_AUTH_RESPONSE will send a Basic and/or Digest request for authorization 401 response to the client. Typically, the client's browser will then ask for a username and password, and resend the request.
    Syntax:
        rcode=sre_auth_response(realm_name,servername,dodigest,message,id_info,sht_mess)
    
    where:
    realm_name: the realm name. This is displayed in the username/password request box displayed by the client's browser.
    servername: optional. Used in the text of the response (not typically displayed) If not included, it will be looked up
    dodigest: Possible values:
  • -1 : do NOT include Digest authentication info
  • 1 : include Digest authentication info, and tell client to recompute his Digest authentication key (tell the client his key is "stale") This is especially useful if the clients prior Authorization header did not work.
  • Otherwise: include Digest authentication info (but don't tell client his key is "stale")
  • message: Optional. If specified, this should be a full html response (including < / html > ... </html >)
    Otherwise the body of a response will be created.
    Note that this "body" is only displayed if the client cancels out of filling in the authorization box.
    id_info: Optional the "id_info"
    sht_mess: Optional If specified, and if message is NOT specified, then this should be a short description (it will be placed in a <blockquote>).
    Rcode is the response from a SRE_COMMAND('VAR ..') call. It contains the "response code".

    Note that if the client is http/1.0, then digest authentication info is not sent (regardless of the value of dodigest).

    SRE_CACHE: Write/read entries in a cache
    Caches are used to store semi-permanent variables. Each cache is allocated a fixed number of slots (one slot per variable), As you add variables, eventually all the slots will be taken. At that point, a LRU (least recently used algorithim) is used to remove the oldest variables, thereby freeing up slots for new variables (about 30% of the oldest variables are removed during this "pruning").

    For example, SRE_CACHE is used to implement the MD5, Request, and IPNAME caches of SRE2003. Note that "lists" and "queues" are also implemented in SRE2003 -- caches differ from lists and queues in several ways: you can lookup specific entries, and an LRU algorithim is used to discard old values.

    Syntax:
        val=sre_cache(cache_name,action,varname,avalue,time_to_live,ownid)
    where
    cache_name The name of a cache.
    Examples of cache_names: MD5 IPNAME REQUEST

    Note: if cachename equals !LIST, then a space delimited list of currently active caches is returned.

    action What to do. Possible actions include: CREATE RESET WRITE ADD READ PRUNE REMOVE STATUS LIST
    varname variable name to store in the cache.
    Case insensitive, and must NOT contain spaces.
    avalue value of this variable
    Time-to-live In fractions of a day, is the desired lifespan of the cache entry.
    This can be used to remove cache entries, even if they are not necessarily the "least recently used". It can NOT be used to protect a "least recently used" entry.
    Ownid Optional, it's the daemon_id of the caller (or, you can use the ID_INFO). Or, set to 0 to mean "don't bother responding" (typically used with action of WRITE or ADD).

    Caution:If calling SRE_CACHE from a non-request thread (say, from an initialization procedure), you must create an ownid, or use 0. This is easily done with the SRE_DMN_OWN procedure.
    Example
    /* create an "ownid" */
    ownid=sre_dmn_own(,,'CACHEIT')
    /* code using ownid, such as ...  */
     astat=sre_cache('CHK_404','CREATE',,,,ownid)
    /*    more code    */
    /* and, to recycle resources, remove the ownid */
     foo=sre_dmn_command(ownid,'DISCONNECT') 

    The supported "actions" are:
    CREATE create a cache
    varname should be the length of the cache.
    If varname is not specified, a default size of 500 is used. Returns: 1 on success
    RESET clear all items in acache.
    If varname is specified, reset the size of the cache to varname.
    Returns: 1 on success
    WRITE create, or change value of, varname; using avalue
    Returns either 'OK 'value or 'ERROR 'error_message
    WRITE_CT Same as WRITE, but also write (to an SRE environment variable) the current number of variables currently defined in the cache (after "writing" this variable). The SRE environment variable name will be cache_name_CT.

    For example: If you WRITE_CT a variable to the FOOBAR cache, you can read the total number of variables in the FOOBAR cache using
      kt=sre_value('FOOBAR_CT',,'SRE')

    APPEND and PREPEND If varname does not exist, these are the same as WRITE.
    Otherwise, either append the avalue to the end of the current value of varname, or prepend to the beginning.
    ADD create a numeric variable, or add avalue to existing numeric variable
    Returns either 'OK 'value or 'ERROR 'error_message
    Note that if you try to ADD to a non-numeric value, an error occurs.
    READ return the value of avar. If avar is not defined, return avalue (if avalue is not specified, return ' ').
    Returns the value
    PRUNE remove 30% of the cache, using a LRU algorithim
    Returns 'Ok 'Num_left_in_cache
    REMOVE remove the entry for varname. REMOVED entries are deleted when a PRUNE is issued (till then, they just occupy space, but are not read)
    Return 'Ok removed' or 'Error no entry'
    REMOVE_CT Same as REMOVE, but also write (to an SRE environment variable) the current number of variables currently defined in the cache (after "removing" this variable). The SRE environment variable name will be cache_name_CT.

    For example: If you REMOVE_CT a variable to the FOOBAR cache, you can read the total number of variables in the FOOBAR cache using
      kt=sre_value('FOOBAR_CT',,'SRE')

    STATUS returns 1 line of status info:
    'Active_entries='nactive', Max_entries='cache_size', Last_reset='last_reset
     
    LIST xxx returns list of items in a cache. Syntax depends on the value of xxx:
    If xxx=' '
       #entries_in_cache (crlf)
       varname','last_read_timestamp','expiration_time','#reads','value (crlf)
       ...
    IF xxx='VAL'
       #entries_in_cache (crlf)
       value (crlf)
       ...
    IF xxx='VAR'
       #entries_in_cache (crlf)
       varname (crlf)
       ...
    
    IF xxx='BOTH'
       #entries_in_cache (crlf)
       varname','value (crlf)
       ...
    
    IF xxx='THREE'
       #entries_in_cache (crlf)
       varname','#reads','value (crlf)
       ...
    
    
    Note: if you specify a varname, it will be used as a seperator. For example, using '09'x will use a TAB as a seperator (this is useful if variables stored in a cache might contain multiple lines of text). There is one proviso: you can not use '01'x as a seperator.
    Examples:

    SRE_CACHED: return whether current request was resolved from the request cache
    SRE_CACHED will return a 1 if the current request was resolved using information from the request cache.
    Otherwise, it returns a 0.
    Syntax:
       iscached=SRE_cached()
    

    SRE_CACHE_DATA: work with the SRE2003 data daemon
    The SRE2003 data-cache daemon provides permanent storage of small to moderate sized collections of small data records. It's strengths are relatively quick lookup and recording of data, using a caching mechanism to reduce disk access.

    For a full description, see SRE_DCSH.TXT.

    SRE_CHECK_USERNAME: Check if a username and password match
    SRE_CHECK_USERNAME checks to see if a username and password matches the username and "password" contained in an authorization header.

    Syntax:
        okay=sre_check_username(username,password,auth_header)
    where:
    username: the username to check
    password: the password of this username
    auth_header: the value of the Authorization: request header. This can be obtained either by using the SRE_REQFIELD function, or by using the AUTH argument sent to the filter.
    Alternatively, a SIMPLE type of auth_header is also recognized: SIMPLE username password.
    okay: okay=1 if the username and password match what the client provided, Otherwise, okay=0
    A typical use of this is:

    1. use SRE_EXTRACT_USERNAMEto extract the "username" of a client,
    2. lookup (in an internal database) the password corresponding to this username,
    3. use SRE_CHECK_USERNAME to see if this username/password combination has been supplied by the client (in the authorization header).

    This function is particularly useful when the DIGEST method of authorization is used.

    Example:

          aa=SRE_reqfield('Authorization')
          username=sre_extract_username(aa)
          /* insert code lookup  "username's" password in a database */
          okay=sre_check_username(username,password,aa) 
    
    Note that a password must be supplied (if it's not, a password of ' ' is used).

    SRE_CHUNK: Chunk encode a string
    Convert a text string to a "chunked" string. Typically, one would call sre_chunk several times (say, as content becomes available, you send it to a client), with the final call being the "final" call.

    Syntax:
        cstuff=sre_chunk(stuff,final,trailer)

    where:
    stuff: the string (text or otherwise) to be chunked
    final: if final=1, this is the last chunk (end with a terminator)
    trailer: if final=1, the contents of trailer will be added as "trailers" to the chunked message
    Cstuff is the "chunked" version of stuff, perhaps with the trailer added at the end (as a "trailer")

    Example:

        aa=sre_chunk(a_string)
    

    SRE_COMPLETED: return whether current request has been completed
    SRE_COMPLETED will return a 0 if the current request is still open.
    Otherwise, it returns a 1.
    Syntax:
       iscompleted=sre_completed()
       iscompleted=sre_completed(transaction_tid)
    
    transaction_tid is optional-- if used, it should be the thread id of a transaction (not the transaction's daemon-id).
    . It is used if you want to lookup the completion status of the request running under a given transaction. If not specified, then the "current request" is checked.

    SRE_CLIENTNAME [ipaddress]) : Do a DNS lookup of an IP name
    Returns the ip name of the current client, or of the numeric ipaddress (if ipaddress is specified).
    Syntax:
      cname=SRE_clientname()
      cname=SRE_clientname('151.22.51.76')
    
    SRE2003 uses a "IPname" cache to avoid unnecessary calls to a DNS -- the most recent several hundred IP name lookups (are retained) -- see the description of MAXCLIENTNAMES.

    SRE_CLIENTS Number of active transactions
    SRE_CLIENTS returns the current number of active transactions; where there is one active transaction per connected client. SRE_CLIENTS can also be used to list the currently active transactions.

    Syntax:
    cname=SRE_clients() Total number of active clients
    cname=SRE_clients('!CT_T') Total number of active clients. This uses an SRE environment variable.
    cname=SRE_clients('!CT_R') Total number of active requests. This uses an SRE environment variable.
    cname=SRE_clients('!LIST_TRAN') Returns a list of currently active transactions

    Notes:
  • The transaction id is the thread (under the SRE2003 process) that the transaction daemon is running under.
  • Some active transactions may be waiting for a second or latter request (on a maintained connection), in which case there will be fewer active requests then active transactions.
  • The !CT options retrieve information from SRE environment variables. These are quick to retrieve, but (on rare occasions) they may not be completely up-to-date.
  • The list of currently active transactions will be a CRLF ('0d0a'x) delimited list; the first line will have the number of active tranactions (possibly 0), and the subsequent lines will contain the transaction ids of these active transactions (one per line).
  • SRE_COMMAND: Recieve and send information to the client, etc.
    SRE_COMMAND is used to recieve and send information to the client and to set certain server variables.

    SRE_COMMAND follows the syntax used in several of GoServe's "completion codes" -- many of the GoServe "completion codes" are implemented via calls to SRE_COMMAND (upgraders may want to refer to GOSERVE.DOC for alternative descriptions).

    Syntax:
        STATUS=SRE_COMMAND('ACOMMAND OPTION',amessage,id_info)
    where:

    The following describes the ACOMMAND modes of SRE_COMMAND in greater detail.

    Note that several of these modes (FILE, VAR, CONTROL, NODATA, and STRING) are "completion commands" -- by default, performing the action entails finishing the request (and possibly closing the connection). This default may be modified if you've enabled SEND mode.
    ALIVE Checks to see whether the socket (for this connection) is still alive.

    Syntax:
       sre_command('ALIVE')

    Returns:

    • -3 = SockSelect error
    • -2 = Could not determine current connections socket
    • -1 = Socket has been closed
    • 0 = Socket is inactive
    • > 0 = Bytes pending on socket
    Note that if a client dies, or otherwise uncleanly breaks a connection, then a 0 may be returned. Thus, 0 indicates, but does not guarantee, that the client is waiting.

    Notes:

    • The STILL_ALIVE function can also be used to check connection status.
    AUDIT Write information to the audit log file.

    Syntax:
        vv=sre_command('AUDIT message')

    Will write the message to the SRE2003 audit log file. Example: foo=sre_command('AUDIT FOOBAR used on '||date('n')) Notes: * The SRE_AUDIT function can also be used to write to the audit log file.

    CLOSE The CLOSE command is used to close down SRE2003/SREhttp/2. You can also instruct SRE2003 to attempt to reboot the machine, or to restart SRE2003. Syntax:
        vv=sre_command('CLOSE [REBOOT | RESTART]')

    where ... REBOOT and RESTART are optional -- you can specify one (but not both) of them (or neither of them).

    • RESTART: after closing down, SRE2003 will restart
    • REBOOT: after closing down, SRE2003 will reboot the computer
    Note: for more complicated status monitoring and re-start capabilities, see the SREWATCH.CMD program (that comes with SRE2003).
    CONTROL Compute statistics, and reset counters.

    Syntax:
        vv=sre_command('CONTROL [NOWAIT] [VAR] option')

    The possible options are:

    • RESET [BYTES] [REQUESTS] [RESPONSE] [TRANSACTIONS] [LIMITS] [ERRORS] [BROKEN] [ALL]

      The specified SRE2003 counters and statistics are reset (after auditing, if appropriate). Any or all of the keywords may be given, in any order. RESPONSE refers to the response time record. If ALL is used, all of the items are reset, and the current time is noted as the "time of last reset" -- the last reset time is shown on the display window and in any statistics requests.

    • STATISTICS

      Current statistics and settings are returned. These include:

      1. Transaction, error, limits, byte, and client counts, with response time averages
      2. Certain settings and options (not including audit selections)
      3. The local time of certain events (if an event has not occurred, it is shown as the SRE2003 start time).
    Examples:
        status=sre_command('CONTROL STATISTICS ')
        val1=sre_command('CONTROL RESET LIMITS VAR')

    The result of a CONTROL command is a single string, which may include multiple lines, separated by Carriage Return-Line Feed (CR-LF, ASCII '0d0a'x) sequences. The result string is either placed in a variable or returned to the client:

  • If 'VAR' was specified, the result string is returned to the caller.
  • If 'VAR' was not specified, a document containing the string is returned to the client (just as though the STRING mode of SRE_COMMAND were used), so in this case, CONTROL is a completion command. A response_code' 'byte_sent (or an 'error error_message') is returned to the filter (or to whatever procedure called SRE_COMMAND).
  • The NOWAIT keyword may be used to force the current connection to be closed after any response is sent, even if a persistent connection had been requested.

    Upgraders note:

    The following GoServe CONTROL options are not supported: MOVEAUDIT RESET PEAK SAY
    FILE
  • Syntax
  • NAME
  • CHUNK
  • ERASE
  • ETAG
  • ETAG_APPEND
  • ETAG_AUTOn and
    ETAG_SIMPLE
  • EXPIRES
  • IM
  • MD5
  • NOWAIT
  • NOCACHE
  • NOIF
  • NORANGE
  • QUICKPOST
  • TYPE
  • TE_GZIP
  • NAME
  • Send a file to the client.

    This is similar to the GoServe FILE command, with several new options (such as CHUNK and ETAG) and without the BINARY option.

    Syntax:
       vv=sre_command( 'FILE [CHUNK] [ERASE] [ETAG etag] [ETAG_AUTOn] [ETAG_SIMPLE] [ETAG_APPEND]   [EXPIRES offset] [IM im-type] [MD5] [NOWAIT] [NOCACHE]   [NOIF] [NORANGE] [QUICKPOST] [TYPE content-type] [TE_GZIP] NAME filespec')

    The only required option is   
    NAME filespec
    FILESPEC must be a fully qualified name of an existing file. This file will (possibly after some encodings and instance manipulations) be sent to the client. If the filename includes spaces, filespec should be enclosed within double quote (") characters.

    The remaining options (none of which are required) may be specified in any order. They have the following effects:

    • CHUNK -- send the file using a chunked format, This is ignored if the client does not understand chunking (the client must be http/1.1, or must send a TE: request header that includes chunked).
    • ERASE -- the file is a temporary file, and should be erased after being sent.

    • ETAG eee -- eee is the etag associated with this response.
      If used, an Etag: eee response header will be added.
      For example:
          Etag gxyq1
      will cause a
          Etag: "gxyq1"
      response header to be added.
    • ETAG_APPEND eee2 -- eee2 is appended to the Etag, where Etag can be specified (with an ETAG) or automatically generated (with an ETAG_AUTOn or ETAG_SIMPLE). Typically, eee2 should start with a ;.
    • ETAG_AUTO, ETAG_AUTO1, ETAG_AUTO2, and ETAG_SIMPLE -- SRE2003 will generate an etag for this file.
      • ETAG_AUTO: use the filename, size, and date; and use values of some headers
      • ETAG_AUTO1: use the filename, size, and date;
        and use the contents of the file; and use values of some headers
      • ETAG_AUTO2: use the contents of the file, and use values of some headers
      • ETAG_SIMPLE just use the filename, size, and date;
      On rare occassions, or on sites where simple changes to dynamic resourcess can occur very rapidly (in less then a second), the ETAG generated by ETAG_AUTO may not be unique. In such cases, you can use ETAG_AUTO1 or ETAG_AUTO2, which causes SRE2003 to compute a more complex (and more time consuming) ETAG
      Notes
      • For all values of variants of ETAG_AUTO, the values of the entity-headers are also used.
      • if any of the ETAG_AUTO variants are used, and ETAG eee is also used, then the explicit etag (the eee) is used.
      • ETAG_SIMPLE generates a simple, and perhaps not quite spec, ETAG. It is best used with static resources. In particular, it can be used with resources that may have been placed on your site via a PUT request.
      • If ETAG_APPEND zzz is also included, the zzz will be appended to the automatically generated etag.
      • See the description of SRE_ETAG for details on how SRE2003 computes etags.

    • EXPIRES offset -- add an Expires: response header. offset is when this file expires, as measured from the current time.
      There are several formats for offset:
          xx.yy xx number_of_days, yy fraction_of_a_day
         xxH xx hours
         xxM xx minutes
      For example, the following all mean 12 hours from now:
          EXPIRES 0.5, EXPIRES 12h, EXPIRES 720m

    • IM im_name -- Specify what IM (instance manipulation) module to use. The im_name option is an identifer defined in the IM_TYPES parameter (specified in SRE2003.CFG).

      If IM is not specified, the default IM algorithim (say, the built-in Range extraction algorithim) is used.

      Examples:
          IM STRING_RANGE
          IM DELTAS
          IM 0 (IM 0 means suppress IM )

    • MD5 Create a Content-MD5 response header. This is created after range extraction, but before transaction-encoding GZIP.
    • NOCACHE -- prevents this FILE URI from being added to the request cache. See Appendix 2 (of the main documentation) for more details.
    • NOIF -- do not check for If- request headers.

      If NOIF is not specified, then SRE2003 will look for If-Modified, If-Match, If-Unmodified-Since, and If-None-Match request headers. If any of these request headers are binding, then an appropriate 304 (not modified) response will be returned.

      If NOIF is specified, then this check will not occur (a 304 response will not be automatically generated).

    • NOWAIT -- forces the current connection to be closed after any response is sent, even if a persistent connection had been requested.

    • NORANGE -- do not check for Range request headers.

      NORANGE is ignored when a non-RANGE im_name is specified (either in the IM_DEFAULT configuration parameter, or in an IM option)
      If NORANGE is not specified, then on FILE commands SRE2003 will look for Range and If-Range request headers. If a Range: header is found, the SRE2003 will attempt to return the requested byte ranges in 206 (Partial Content) response.

      If NORANGE is specified, then this automatic generation of a range response will not occur, even though the client may desire such a range.

      Reminder: range responses are automatically generated only with the FILE command (of SRE_COMMAND) -- responses generated using VAR and STRING commands are not checked for Range. Of course, you can always create your own range response using VAR (and adding the appropriate response headers).

    • QUICKPOST --immediately return "anticipated status" information prior to responding to the client. This can speed up throughput, since the filter can exit (releasing memory) prior to completion of response. Though potentially wrong (say, if a client kills a connection) this "anticipated" information is often sufficient for logging purposes.

    • TE_GZIP If supported by the client (as indicated in a TE request header), on-the-fly GZIP the file before sending it to the client.
      • SRE2003's on-the-fly GZIP is done as a transfer-encoding. In general, only http/1.1 clients will be capable of recieving GZIP as a transfer-encoding.
      • The entity tag is computed before GZIPping.
      • The request-cache will flag selectors when a TE_GZIP was specified. On future requests for this selector, if the client understands GZIP as a transfer-encoding, the cache will not handle the request. The idea is that the filter is given a chance to order a transfer-encoding of this request.

    • TEXT -- Treat the response as a text file. Currently, this has one effect: if the file ends with a Ctrl-Z, the Ctrl-Z in stripped.
    • The TEXT option is ignored if the file is larger then 500,000 bytes.
    • In general we do not encourage use of this TEXT option -- it reduces the useability of the request (and content-md5) caches.
    • TYPE xxx -- xxx is the "mimetype" of this resource. SRE2003 will include a Content-type response header that uses xxx.
      For example:
          type text/plain
      will cause SRE2003 to add a
          Content-type: text/plain
      response header.
    Examples:
    • stat=sre_command('file type text/html etag fae94 name d:\sre\index.htm')
    • stat=sre_command('file erase type image/gif name d:\sre\temp\$7681.80')
    • stat=sre_command('file chunk type application/octet-stream e:\arc\fo.zip')
    Notes:
    • The FILE mode of SRE_COMMAND will always return two numbers, seperated by a space -- a status code and the bytes sent.
      For example: 200 15161
    • The filespec may not include an 'upwards reference' sequence ("..\") as such a sequence could possibly allow clients access to any file on the server machine.
    • SRE2003 will generate a header automatically if the TYPE option is specified. You can also use the HEADER option to specify a content-type (note that a content-type specified by the TYPE option will override a content-type specified specified by the HEADER command).
    • The Content-Length and Transfer-Encoding headers are always generated by SRE2003. Don't bother trying to specify them with SRE_COMMAND!
    • CHUNK can also be used with SRE_COMMAND('VAR ...
    • FILE is a "completion code"
    HEADER Add or remove a response header.

    Syntax:
        aa=sre_command('HEADER [ADD|APPEND|DROP|PLACE|REPLACE] [CLEAR] [NOAUTO] [NOTIME] [READ] hdr_name : hdr_value')
    where:
    ADD, APPEND, DROP. PLACE,
    or REPLACE
    • ADD (the default):The header specified in hdr_name is added.
      If a header with this name already exists, a new response header is added. Thus, the client will recieve two (or more) response headers with this name, each with (possibly) different values.
    • APPEND: The header specified in hdr_name is added.
      If a header with this name already exists, value is appended to the end of the already existing value (with a comma seperating the existing value from this value).
      In contrast to ADD, only one response header is sent, with the two (or more) values seperated by commas.
    • DROP Removes a with name specified by hdr_name. Hdr_value is ignored, and the trailing : (after hdr_name) need not be included.
    • REPLACE Similar to ADD, but instead of appending to a pre-existing value, it will replace a pre-existing value.
    • PLACE Similar to ADD, but only if a pre-existing value does not exist (that is, PLACE will not overwrite a pre-existing value ).
    CLEAR Remove all existing response headers. Turn off NOAUTO and NOTIME.
    NOAUTO Optional. If specified, then the automatically generated headers (time, servername, etc.) will NOT be added.
    NOTIME Optional. If specified, then Last-Modified and/or Expires: headers will not be included
    READ Read the current value of hdr_name. When READ is used, all other options (except CLEAR) are ignored.
    The current value is returned as: hdr_name: current_value.
  • if their is no hdr_name response header currently defined, a ' ' is returned.
  • If you do not specify any hdr_name, a space delimited list of currently defined response headers is returned.
  • The various automatically generated response headers can not be READ -- they are generated when the response is sent to the client.
  • hdr_name and hdr_value Define the name of the response header, and it's contents. For example:
       x-new-header: This is my new header

    Examples:

    • foo=sre_command('Header add X1: This is x1 ')
    • foo=sre_command('Header add X2: This is X2 ')
    • ...
    • foo=sre_command('Header drop x2:')
    • foo=sre_command('Header NoAuto Add Simple: this is the only header')
    Notes:
    • NoAuto and NoTime can be included with ADD or DROP. But you should only use it once per response.
    • HEADER DROP only examines the portion of aheader that precedes the first ":".
    • You can specify multiple "aheaders" by concatenating several of them, with each aheader seperated by a '0d0a'x.
      For example:
          rh='Header Add H1: my name is Gus '
          rh=rh||'0d0a'x||'Header Add S1: Her name is Sally'
          foo=sre_command(rh)
    • sre_command('Header ...') always returns a '1'.
    IMINFO Specify some information to be sent to an IM module. See IM_USE.HTM for details on how IM modules can use this information.
    Syntax:
       
    vv=sre_command('IMINFO [CLEAR| [PLACE] [READ] ',im_message)

    where one (or none) of the options may be used:

  • CLEAR = remove prior message(s) and replace with this one. If im_message= ' ', then just clear prior messages(s)
  • PLACE = add this message only if no prior message has been specified
  • READ = read current set of messages to be sent to IM. If READ is used, the im_message argument is ignored
  • otherwise (if no options are specified), add this message (on a new line) after existing messages
  • Examples:
       foo=sre_command('IMINFO ','Strings=Section+1 - Section+2')
        bybbye=sre_command('IMINFO CLEAR')
    NODATA Send a null response.
    Syntax:
        vv=sre_command('NODATA [NOWAIT] [NORESPONSE]')

    No data are to be sent; the response is complete. This command is intended to be used when only a header, or nothing at all, is to be returned to the client.

    If NORESPONSE is specified, then no response line and header will be sent either, even for an HTTP/1.0 or later request; the connection will be closed (unless persistent). This option could be used for testing, or if (say) a faulty client was sending repeat messages.

    The NOWAIT keyword may be used to force the current connection to be closed after any response is sent, even if a persistent connection had been requested.

    Notes:

    • NODATA is a completion command
    QUERY Lookup one, or several, SRE2003 variables.

    This is an alternative to the SRE_EXTRACT procedure.
    Its advantage is that you can lookup several variables at once.
    Their values will be returned in a CRLF ('0d0a'x) delimited list.

    Example

       stuf=sre_command('QUERY ',' Username Servername Request_Line')
       parse var stuf uname'0d0a'x sname '0d0a'x rline


    READ Read the request headers or the request body.

    Syntax:
        status=sre_command('READ HEADER|BODY [ENABLE_CE_GZIP] [SUPPRESS_TE_GZIP]')

    where:
    READ is used to read the request HEADERS, or the request BODY.
    The two options are only used with BODY
    ENABLE_CE_GZIP enables UnGZIP of a request body that is gzipped, and that contains a Content-Encoding: GZIP header.
    SUPPRESS_TE_GZIP disables UnGZIP of a request body that is gzipped, and that contain a Transfer-Encoding: GZIP header.
    status contains the result of the READ.
    If BODY is being read, status will have the following syntax:

    • If no error occurred:
          length||CRLF||request_body
      where length is the length (in bytes) of request_body
    • If an error occured     error_code||CRLF||error_message
      error_code will be a negative value. Its absolute value corresponds to an http error response.
      These include: 400 408 411 413 415 501
    By default, ungzip is done for "GZIP as a transfer encoding", but not for GZIP as a content encoding.
    Example:
         hdrs=sre_command('READ HEADER')
         abody=sre_command('READ BODY ENABLE_CE_GZIP')
         parse var abody nsize '0d0a'x params
         if nsize<0 then do          /* some kind of error on request body read */
            amess=SRE_Extract('REQUEST_ERROR')
            rcode=sre_error_response(abs(nsize),,servername,amess,id_info)
            return rcode
         end

    Notes:

    • when SUPPRESS_TE_GZIP is not specified, and an unknown transfer-encoding is encounted, a 501 Unimplemented response is automatically generated.
    • when ENABLE_CE_GZIP is specified, and an unknown content-encoding is encountered, a 415 Unsupported Media Type response is automatically generated.
    • SRE_EXTRACT('READBODY_STATUS')
      can be used to check, and returns ...
      none the request is not POST or PUT
      pending the request body has not yet been read
      completed the request body was successfully read
      error an error occurred when reading the body, and the connection was closed
    In addition, A REQUEST_ERROR variable contains the "error status" of this connection. It can be checked with SRE_Extract('REQUEST_ERROR').
    REQUEST_ERROR will have a number of possible values, with a value of ' ' meaning "no error".
    RESPONSE RESPONSE is used to change the response line, or to retrieve its current value.

    Syntax:
        aa=sre_command('RESPONSE response line ')

    where
       response_line is your desired response line.

    or ...
        aa=sre_command('RESPONSE')

    Examples:
      aa=sre_command('RESPONSE http/1.1 206 Partial Content')
      the_respline=sre_command('RESPONSE')

    Notes:

    • By default, SRE2003 sends a response line of: http/1.1 200 Ok
    • sre_command('RESPONSE xxx) always returns a '1'
    • sre_command('RESPONSE ') returns the current value of the response line. If the response line has not been modified, this will be the default value of HTTP/1.1 200 Ok
    SET SET is used to set "connection specific" values of several variables.

    Syntax:
        status=sre_command('SET option',avalue)

    where option is one of:
        LIMITTIMEINACTIVE
        LIMITTIMEWAIT
        LIMITTIMETOTAL
        LIMITBODY
        DATADIR
        TEMPFILE
    and
        avalue is the new "connection specific" value

    Examples:
        status=sre_command('SET DATADIR','e:\special\doc')
        status=sre_command('SET LIMITTIMETOTAL ',1000)

    Notes:

    • these do NOT effect the default values -- they only effect the current (possibly multiple request) transaction.
    • EXTRACT can be used to read these "modified" values
    • to permanently change these variables, you must change SRE2003.CFG (say, by running SRE2003 -m from an OS/2 prompt).
    • TEMPFILE is special -- its default value is ' '. If TEMPFILE is set to a filename, SRE2003 will attempt to close this TEMPFILE when the transaction is completed. This avoids problems when a request time's out.
    SEND SEND is used to build multipart messages, or to send pieces of a response as it is being built.

    Syntax:

  • result=sre_command('SEND [NOWAIT][EXPIRES offset] [TYPE content-type] ')
  • ... various FILE, VAR, STRING and other SRE_COMMAND calls ...
  • result=Sre_command('SEND COMPLETE [NOWAIT]')
  • The basic idea is that all "completion codes" (STRING, VAR, FILE, CONTROL, and NODATA) between a 'SEND ' and a 'SEND COMPLETE' will NOT mean "end of response".

    Instead, the start of a response (the response line and response headers) is sent to the client when the first SEND is issued, and the response is completed when a 'SEND COMPLETE' is recieved.

    Typically, the response headers (and perhaps the response line) are specified before the first call to SEND. However, you can specify the type/subtype (and perhaps a boundary string) in the SEND command by including a TYPE modifier.

    Examples:

  • status=sre_command('SEND TYPE text/plain')
  • status=sre_command('SEND TYPE multipart/mixed; boundary=This_string_sePerates')
  • SEND COMPLETE ends the response. For example:
  • response_code=sre_command('SEND COMPLETE')
  • response_code=sre_command('SEND NOWAIT COMPLETE')
  • The NOWAIT option can be used in either the first or final SEND. If used in the first SEND, then a Connection: Close response header is added, and the connection is closed (after a SEND COMPLETE). If NOWAIT is only used on the final send (i.e.; SEND NOWAIT COMPLETE) then the connection will be closed, but a Connection: Close response header will not be sent.

    The EXPIRES option can be used to create an Expire: response header. offset is when this file expires, as measured from the current time.
    There are several formats for offset:
        xx.yy xx number_of_days, yy fraction_of_a_day
       xxH xx hours
       xxM xx minutes
    For example, the following all mean 12 hours from now:
        EXPIRES 0.5, EXPIRES 12h, EXPIRES 720m

    Notes:

    • Within the boundaries of a SEND and a SEND COMPLETE:
      1. All header specifications are ignored (including TYPE), and NOWAIT is ignored. If you want to specify different types for each part of a multipart response, you can use VAR (you can also use VAR to include boundary lines).
      2. The status returned is either the number of bytes sent, or a negative error code.
      3. The ERASE modifier of a FILE command is ignored (temporary files will not be deleted).
    • Reminder: SEND is not used to return responses to multiple requests on a single "maintained" connection. Instead, SEND can be used to return multiple "parts" within a single "multi-part aware" request.
    • You can specify the response-line, and additional response headers, by using (on the first SEND call) the response_line and header arguments in the advanced form of SRE_COMMAND.
    • If you use the TYPE option with SEND, it must be the last option. That is, NOWAIT and EXPIRES must preceed TYPE.
    • When SEND is enabled, all Instance Manipulations (including Range extraction) are disabled.
    STRING STRING is used to send a short string to the client.

    Syntax:
        vv=sre_command('STRING string',header)

  • The single string is returned to the client as a simple text/html response.
  • The header is optional. If included, it should be a short sentence to display at the top of the screen.
  • The STRING command can be used to return a simple message to the client. Multiple lines can be sent, if necessary, by embedding a CR-LF sequence ('0d0a'x) to separate lines.

    Example:
        stat=sre_command('STRING Hello World!')

    Notes:

    • STRING is a completion command
    • The STRING mode of SRE_COMMAND will always return two numbers, seperated by a space -- a status code and the bytes sent.
      For example: 200 15161
    VAR command Return the contents of a "variable" to the client.

    Syntax:
        ff=sre_command(' VAR [NOWAIT][CHUNK] [ETAG etag] [ETAG_AUTOn] [ETAG_APPEND] [QUICKPOST] [MD5] [TE_GZIP] [EXPIRES offset] [TYPE content-type] ', varname]

    The contents of the Rexx variable named by varname will be sent to the client. varname is a standard REXX variable, as it would be written in the filter.

    The optional keywords may be specified, in any order, and have the following effects:

    • CHUNK -- send the contents of the variable using a chunked format
    • EXPIRES offset -- add an Expires: response header. offset is when this file expires, as measured from the current time.
      There are several formats for offset:
          xx.yy xx number_of_days, yy fraction_of_a_day
         xxH xx hours
         xxM xx minutes
      For example, the following all mean 12 hours from now:
          EXPIRES 0.5, EXPIRES 12h, EXPIRES 720m
    • ETAG eee -- eee is the etag associated with this response.
      If used, an Etag: eee response header will be added.
      For example:
          Etag gxyq1
      will cause a
          Etag: "gxyq1"
      response header to be added.
    • ETAG_APPEND eee2 -- eee2 is appended to the Etag, where Etag can be specified (with an ETAG) or automatically generated (with an ETAG_AUTO). Typically, eee2 should start with a ;.
    • ETAG_AUTO, ETAG_AUTO1, and ETAG_AUTO2 -- SRE2003 will generate an etag for this response.
      • ETAG_AUTO: use the current date and the length of string
      • ETAG_AUTO1: use the current date and the length of string, and use the contents of the string
      • ETAG_AUTO2: use the contents of the string
      On rare occassions, or on sites where dynamic resources can occur very rapidly (in less then a second), the ETAG generated by ETAG_AUTO may not be unique. In such cases, you can use ETAG_AUTO1 or ETAG_AUTO2, which causes SRE2003 to compute a more complex (and more time consuming) ETAG
      Notes:
      • For all values of variants of ETAG_AUTO, the values of the entity-headers are also used.
      • if any of the ETAG_AUTO variants are used, and ETAG eee is also used, then the explicit etag (the eee) is used.
      • See the description of SRE_ETAG for details on how SRE2003 computes etags.
    • MD5 Create a Content-MD5 response header. This is created after range extraction, but before transaction-encoding GZIP.
    • NOWAIT -- forces the current connection to be closed after any response is sent, even if a persistent connection had been requested.
    • QUICKPOST --immediately return "anticipated status" information prior to responding to the client. This can speed up throughput, since the filter can exit (releasing memory) prior to completion of response. Though potentially wrong (say, if a client kills a connection) this "anticipated" information is often sufficient for logging purposes.
    • TE_GZIP If supported by the client (as indicated in the TE request header), GZIP the file before sending it to the client.
      Notes:
      • SRE2003's on-the-fly GZIP is done as a transfer-encoding.
      • The entity tag is computed before GZIPping.
      • GZIPed variants of a file are NOT cached (since they are created on the fly, and then erased)
      • In general, only http/1.1 clients will be capable of recieving GZIP as a transfer-encoding.
    • TYPE xxx -- xxx is the "mimetype" of this resource. SRE2003 will include a Content-type response header that uses xxx.
      For example:
          type text/plain
      will cause SRE2003 to add a
          Content-type: text/plain
      response header.
    Example (returning an HTML document to a Web client) :
      /* This is Rexx code */
      mydoc=' Hello world! '          /* may be large */
      stat=sre_command('var type text/html  ', mydoc)     
      return
    Notes:
    • The VAR mode of SRE_COMMAND will always return two numbers, seperated by a space -- a status code and the bytes sent.
      For example: 200 6236
    • SRE2003 will generate a header automatically if the TYPE option is specified. You can also use the HEADER option of SRE_COMMAND to specify a content-type.
    • When using CHUNK, you should NOT include a content-length header, and you SHOULD specify a "transfer-encoding: chunked" header.
    • VAR is a "completion code"

    There is an advanced form of sre_command that can be used with completion codes (such as VAR, FILE and STRING).
         

    Syntax:
      stuff=sre_command(acommand,amessage,id_info,response_line,headers)

    where:
    acommand: a command, such as FILE or VAR
    amessage: a message, which depends on acommand. Some values of acommand do not use amessage (VAR uses amessage, but FILE does not)
    id_info: optional. info used to communicate with daemons. If known, it can speed things up.
    response_line: optional. response line (if acommand is a completion code)
    Example of response_line:
       'HTTP/1.1 301 Moved Permanently'
    Note that you must include the HTTP/x.x token when specifying a response line.
    headers: optional. CRLF ('0d0a'x) delimited list of headers (if acommand is a completion code)
    Example of headers:
       'Foobar: this is foo bar '||
       '0d0a'x||'Barfoo: and this is bar foo'

    Note: headers specified by this argument override headers specified by SRE_COMMAND('HEADER ...'). However, they do not override a content-type header set by a TYPE option.

    Furthermore, don't bother trying to set Content-Length or Transfer-Encoding headers (SRE2003 insists on determining when and how to use these two headers).

    SRE_COUNTVARS: set and get "counter" variables
    This is used to set global counters variables (such as a running count of bytes sent). Several special counter variables are stored in the OS/2 environment for quick (though not totally up-to-date retrieval).
    These "quicklist" variables are: BYTESREADTOTAL BYTESSENTTOTAL TRANSACTIONS REQUESTS LIMITS ERRORS CACHEHITS

    Syntax:
        foo=sre_countvars(varname,avalue,ownid)

    where:
    varname the counter variable. If you begin varname with a "=" (without the ") then "force" a read from the cache (rather then from the enviroment) -- this only applies to the quicklist variables.
    avalue the value to add If avalue is not specified, then return current value of varname
    If avalue = RESET, then reset the counter to 0.
    ownid optional, the clients "own_id". This is used ONLY if you are reading the value of a non "quick list" counter. If not specified, an own_id will be generated automatically.

    SRE_DATADIR: return the default data directory
    SRE_DATADIR will return the default data directory. This may be a host specific directory. In fact, it may be dynamic to the request.
    Syntax:
       sname=SRE_datadir()     
       sname=SRE_datadir('host')    
       sname=SRE_datadir('default')    
    
    If 'host' is specified, then the default host-specifc data directory (as set in SRE2003.CFG, or as specified by a calls to SRE_HOSTINFO) is returned.

    If 'default' is specified, the default data directory is returned (as specified in SRE2003.CFG).

    If no argument is given, then either:

    Notes:

    SRE_DATESTAMP: Create a time & date string
    Compute a datestamp, of the form: Fri, 20 Jul 2001 12:28:09

    Syntax:
        adate=sre_datestamp(filedate,gmtoff)
    where:
    filedate: a date in one of two formats:
  • yy/mm/dd/hh/mm/ss
    Example: 01/11/25/13/32/02
  • mm-dd-yy hh:mn:ss
    Example: 11-22-01 16:52:16
  • If not specified, use the current date and time
    gmtoff: Optional, the offset from GMT time, in seconds. If not specified, SRE_DATESTAMP will lookit up (using the GMTOFFSET computed by SRE2003).

    Examples:

              t1=sre_datestamp()
              edtoffset=14400
              t2=sre_datestamp(,edtoffset)
            
              a=sysfiletree('C:\CONFIG.SYS','aa.')
              parse var aa.1 adate .
              t3=sre_datestamp(adate,edtoffset)
    
            which could yield:
    
               t1:       Fri, 20 Jul 2001 12:30:10 GMT
               t2:       Fri, 20 Jul 2001 16:30:10 GMT
            adate:       01/06/29/16/15
               t3:       Fri, 29 Jun 2001 20:15:00 GMT
    
    Note: See
    SRE_GMT for a more complicated version of SRE_DATESTAMP

    SRE_ERROR_RESPONSE: Return a server error response to the client
    SRE_ERROR_RESPONSE will return send a server error response to the client.
    Syntax:
       rcode=sre_error_response(type,amessage,servername,log_message,id_info)
    
    where all the variables are optional:
    type The type of the error. The currently supported types are:
  • 400 or BAD: Some kind of problem
  • 403 or FORBIDDEN : the server is refusing to honor this request (authorization will not help)
  • 404 or NOTFOUND : The default. Resource can not be found
  • 405 or NOTALLOWED : The method is not allowed
  • 408 or TIMEOUT: A time occured while reading request body
  • 409 or CONFLICT: A conflict with the current state of the resource
  • 410 or GONE: The resource has been permanently removed.
  • 411 or NOLENGTH: Length missing from request body (and not chunked)
  • 412 or PRECONDITION: A precondition failed
  • 413 or LARGEBODY : Request entity too large (i.e.; POST request with huge body)
  • 414 or LARGEURI: Request URI too large.
  • 415 or UNSUPPORTED: Unsupported media type
  • 500 or ERROR : Server error
  • 501 or NOTIMPLEMENTED : not implemented (the server does not support this request method)
  • 503 or BUSY: service unavailable (try again later).
  • 503 xxx: same as 503, with xxx the number of seconds the client should wait before retrying
  • 506 or ALSONEGOTIATES: content negotiation resolves to another content negotiation
  • 510 or NOTEXTENDED: Server does not support extended http method
  • amessage Optional. If specified, this should be a full html response (including <html> ... </html>)
    If not specified, a response message will be automatically generated (depending on the Type and the Log_message).
    servername optional. The DNS (or ip address) of this server. Looked up if not provided.
    log_message Optional. If provided, and if amessage is not provided, then log_message will be added to an automatically generated response.

    Also, if type=500, then log_message is written to the SRE2003 error log file.

    id_info Optional, the "id_info"
     
    Rcode is the response from a SRE_COMMAND('VAR ..') call. It contains the "response code".

    SRE_EVENTVARS: set and get "event" variables
    This is used to store event variables.

    Event variables are variables whose value changes frequently (such as the time the most recent connection was accepted). These are NOT necessarily numeric values (i.e.; it could be a timestamp, or a client a IP address).
    As with Counter variables, a "quicklist" is maintained of events that are also stored in the environment.
    These are: LASTACCEPT LASTIDLE LASTRESET LASTADDRESS

    Syntax:
        foo=sre_eventvars(varname,avalue,ownid)

    where:
    varname the event variable. If you begin varname with a "=" (without the ") then "force" a read from the cache (rather then from the enviroment) -- this only applies to the quicklist variables.
    avalue the value to store If avalue is not specified, then return current value of varname
    ownid optional, the clients own_id. This is used only if you are reading the value of a non "quick list" event. If not specified, an own_id will be generated automatically.
    Notes:

    SRE_ETAG: automatically generate an Etag
    SRE_ETAG is used to automatically generate an Etag, given a file or a variable.
    Syntax:
       an_etag=sre_etag(in_type,filename_or_var,use_contents,more_stuff)
    where:
    in_type What type of input.
       0 = the contents of a variable
       1 = a fully qualified file name
    filename_or_var The filename, or string, to compute an etag for.
       If in_type=0, uses the actual value of filename_or_var
       If in_type=1, treats filename_or_var as a filename, and uses the contents of this file.
    use_contents use_contents controls whether to use the actual contents, of the file or message, when creating an etag.
     0 do no use contents. Instead, use length and date information. This is the fastest alternative. Its disadvantages are that on rare occassions it may not produce a properly unique etag. In addition, it may also produce etags that differ even though the entity's contents are the same.
     1 use contents and and use length and date information. This is the slowest, but most robust alternative. It may also produce etags that differ even though the entity's contents are the same.
     2 use contents only (do not use length and date information) This is robust, and will not not produce etags that differ when the actual contents are the same.
    more_stuff An arbitrary string. This is typically the values of a set of the entity-headers (since etags are formally defined as covering both entity body and entity headers). It will be used, along with the information dictated by use_contents, to generate the ETAG.

    an_etag will be the value of the etag.

    Notes:

    SRE_EXTRACT: returns settings of several SRE2003 variables.
    SRE_EXTRACT is used to obtain values of the SRE2003 variables, several of which are request (or connection) specific. The syntax of SRE_EXTRACT closely follows the GoServe EXTRACT function, with several additional fields supported (and a few not supported).

    Syntax:
        avalue=SRE_EXTRACT(varname,id_info)
    where:
    id_info optional -- the id info of the transaction/request you want information from. If not specified, information about the current transaction/request.
    varname is one of the following variables.
    BYTESREAD the number of bytes received from the network, so far during the current transaction.
    BYTESREADTOTAL the total number of bytes received from the network. You may need to increase the Rexx NUMERIC DIGITS setting if you wish to do arithmetic on this count. 16 digits should be sufficient.
    BYTESSENT the number of bytes sent to the network, so far during the current transaction.
    BYTESSENTTOTAL the total number of bytes sent to the network. You may need to increase the Rexx NUMERIC DIGITS setting if you wish to do arithmetic on this count. 16 digits should be sufficient.
    CLIENTADDR the client's address used for the connection, in numeric form (for example, 12.34.56.78). For a symbolic name for the address, see the CLIENTNAME function.
    CLIENTMETHOD the method (verb) being invoked by the client. For example, "GET" or "POST".
    CLIENTPORT the client's port number used for the connection.
    CLIENTPROTOCOL the protocol being used by the client. For example, "HTTP/1.0".
    CLIENTS the number of clients currently connected.
    DATADIR The connection specific default data directory. You can also use the datadir() function to return this value. In addition, the filter is called with datadir as one of the components of the hostinfo argument.
    DATADIR_DEFAULT The default value of datadir (as set in SRE2003.CFG).
    ELAPSED the elapsed time, in seconds, since the current transaction started (that is, when the network connection was accepted).
    ERRORS the count of errors detected.
    BROKEN the count of broken connections (connections closed by the client)
    FILTER the name of the Rexx filter.
    HOST_NICKNAME the "host nickname" assigned to this "host" If no host nicknames are assigned, returns a ''
    GMTOFFSET the GMT offset (in seconds).
    LASTADDRESS IP address (numeric) of the most recent client
    LASTACCEPT timestamp of the last accepted connection [format: yyyy.mm.dd hh:mm:ss].
    LASTIDLE timestamp of when SRE2003 last entered an idle state, with no connections [format: yyyy.mm.dd hh:mm:ss]. Note that this is only as accurate as the "update rate" (set in SRE2003.CMD).
    LASTSECOND time now, in the same format [yyyy.mm.dd hh:mm:ss] as the other LASTxxxx items.
    LASTSTART timestamp of when this instance of SRE2003 was started [format: yyyy.mm.dd hh:mm:ss].
    LASTRESET timestamp of last RESET ALL "CONTROL" command [format: yyyy.mm.dd hh:mm:ss].
    LIMITS the count of limits exceeded (that is, the count of transactions that were ended due to a limit being exceeded). The limits counted are the total connection timeout (LIMITTIMETOTAL), the incoming data measures (LIMITBODY and LIMITHEADER), and maximum clients exceeded (LIMITCLIENTS). The latter is only counted once for each non-idle burst of connections.
    LIMITBODY Connection specific maximum size of request body (as sent by a POST or PUT request), in kB
    LIMITBODY_DEFAULT Default value of LIMITBODY
    LIMITCLIENTS maximum number of client connections allowed concurrently [1 through 200 -- to increase max size, set the MAXCLIENTS value in SRE2003.CFG).
    LIMITHEADER Maximum size of headers (including the request line), in kB
    LIMITTIMEINACTIVE Connection specific maximum time, in seconds, for which SRE2003 will allow a client to remain connected but inactive (that is, without sending or reading data) [0 through LIMITTIMETOTAL].
    LIMITTIMEINACTIVE_DEFAULT The default value of the above.
    LIMITTIMETOTAL Connection specific maximum time, in seconds, for which SRE2003 will allow a client to remain connected, even if active [LIMITTIMEINACTIVE through 1E+9].
    LIMITTIMETOTAL_DEFAULT default value of the above
    LIMITTIMEWAIT Connection specific maximum time, in seconds, for which SRE2003 will keep a client connection open waiting for a new request. This applies for all http/1.1 requests, and for all http/1.0 requests that contain a 'Connection: keep-alive' header with the previous request [0 through 1E+9].
    LIMITTIMEWAIT_DEFAULT default value of the above
    LISTEN_SOCKET the socket bound to the http port. This is the socket that SRE2003 SOCKLISTEN's to
    NUMSENDS number of VAR, FILE, CONTROL, STRING, and NODATA commands issued after a SEND command (0 if no SEND command was ever issued). Note that the initial SEND will set NUMSENDS=1.
    PEAKCLIENTS the maximum number of clients that were connected simultaneously.
    READWAITTIME average read wait time (seconds).
    READBODY_STATUS The status of a read of the request body. If not POST or PUT, then returns 'none'. Otherwise, returns 'pending','completed', or 'error'.
    REQUEST and
    REQUEST_NUMERIC
    the unique number for this HTTP request. This is incremented as each HTTP request is read. This can differ from the TRANSACTION (connection) number if a connection fails to send a request, or if there is more than one request in a transaction.

    REQUEST is structured as TRANSACTION_NUMBER || REQUEST_AS_LETTER
    REQUEST_NUMERIC is structured as TRANSACTION_NUMBER || REQUEST_AS_DIGITS
    Thus, for transaction # 115, request 1 would yield:
        REQUEST: 115A
        REQUEST_NUMERIC: 1151
    For transaction # 4312, request 3 would yield:
        REQUEST: 4312C
        REQUEST_NUMERIC: 43123

    REQUESTS the number of HTTP requests read since SRE2003 was started.
    REQUEST_ERROR most recent connection error (for this connection) or '', if no connection.
    REQUEST_LINE the request line (for this request).
    For example:GET /INDEX.HTM HTTP/1.0
    RESPONSE_CODE the response code (i.e.; 200, 404, 301). If response not yet send, returns '000'.
    RESPONSETIME average response time (seconds).
    RESPONSEOVER number of connections over which RESPONSETIME and READWAITTIME have been averaged.
    SELECTOR the selector string: the Universal Resource Indicator, as recieved from the client (that is, the leading / is retained, and without url unpacking)
    SERVERADDR the server's address used for the connection, in numeric form (for example, 11.22.33.44). For a symbolic name for the address, see the SERVERNAME function.
    SERVERPORT the server's port number used for the connection (for example, 80 for default HTTP).
    SERVERPROTOCOL always returns "http/1.1"
    SERVERSOFTWARE the level of the server software (for example "SRE2003 ver 1.12d"). This is the same as returned by the function calls SRE_SERVER() .
    STARTTIME The time that this transaction was started
    STARTTIME_REQ The time that this request was started (note that transactions may incorporate multiple requests)
    TEMPFILE The TEMPFILE value. By default, this is ' '. However, you can set it using SRE_COMMAND('SET TEMPFILE',a_file_name).
    TRANSACTION the unique number for this transaction (connection). This is incremented as each client connects to the server. Note that each transaction may yield several requests (though not concurrently).
    TRANSACTIONS the number of transactions since SRE-http was started.
    USERNAME the username, as provided in an Authorization: request header. If no Authorization: request header, this returns ' '.
    Note that you can also use SRE_EXTRACT_USERNAME to obtain the username.
    Notes:

    SRE_EXTRACT_USERNAME: extract the username from an authorization header
    Extract the username from an authorization header

    Syntax:
        username=sre_extract_username(auth_header)
    where:
    auth_header auth_header is the value of the Authorization: request header.
    This can be obtained either by using the SRE_REQFIELD function, or by using the AUTH argument sent to the filter.

    SRE_EXTRACT_USERNAME will extract the "username" from either a BASIC or a DIGEST Authorization: request header. If the auth_header is empty, malformed, or otherwise does not contain username information, then a ' ' is returned.

    Example:

          aa=SRE_reqfield('Authorization')
          username=sre_extract_username(aa)
    
    Note: a SIMPLE type of auth_header is also recognized:
    SIMPLE username password. While asking sre_extract_username is hardly necessary to extract the username, we provide it for completeness.

    SRE_FIX_URL: Make a fully specified url
    Make a fully specified url; such as http://a.b.net/xxx/yyy

    Syntax:
        theurl=sre_fix_url(aurl,servername,serverport)
    where:
    aurl: a relative or absolute url.
    servername: optional. The ip name (domain name) or numeric ip address of the server. If not specified, use the local domain name.
    serverport: optional. The serverport. If not specified, use the local port (if servername not specified), or use port 80.

    theurl will be a fully qualified url.

    Examples (assuming SRE2003 is running on server with a domain name of foo.bar.net):

    
        aa=sre_fix_url('/files/index.htm')
        aa ==> http://foo.bar.net/files/index.htm
    
        bb=sre_fix_url('/animals/images/tiger.jpg','www.funplaces.org')
        bb ==>  http://www.funplaces.org/animals/images/tiger.jpg
    
    

    Notes

  • if aurl starts with http://, then nothing is done
  • The following rules are used
        1) Temporarily remove anything after a ?
        2) Strip any leading /
        3)  Look for a /  
            If no / found, 
               Look for periods.  
                  If > 1 period found, it's an ip address
                  If <2 found, it's a local uri (say, a file on the
                  local server)
            If / is found
              Check stuff before first /.
                 If it has any periods, its an ip address (stuff after
                 is the "selector")
                 If no periods, it's a local url (say, stuff after the / 
                 contains subdirectory & file specifiers)
    
  • SRE_GET_URL: Get contents of a url
    Use socket calls to retrieve the contents of a url.

    Syntax:
        stuff=sre_get_url(aurl,maxchars,verbose,headers)
    where:
    aurl: a relative or absolute url. If it's a relative URL (no domain name), then use the local host and local port.
    maxchars: Optional. Maximum # of characters to read. If not specified, then get up to 10 million
    verbose: Optional. If 1, then pmprintf some status messages
    headers: Optional. A CRLF delimited list of request headers to add to the request.
    Stuff is the full contents (including response line) from the server hosting aurl

    Examples:

       stuff=sre_get_url('family/doglife.html')
       stuff=sre_get_url('foo.bar.net/pictures/maple_tree.jpg')
       stuff=sre_get_url('http://foo.bar.net/pictures/apple_tree.jpg')
       stuff=sre_get_url('www.goo.org:8080/class8/lessons.shtml')
       stuff=sre_get_url('www.goo.org:8080/class8/lessons.shtml')
       stuff=sre_get_url('www.junkstuff.com/biglist.txt',10000,,'X-limit:10 pages')
    
    

    Notes

  • This is a fairly simple procedure -- it uses default timeouts. Thus, it is not very robust against flakey connections, etc.
  • The AURL can start, or not start, with http://
  • To specify a port other then 80, use the standard :nnnn syntax (after the domain name in AURL).
  • SRE_GET_URL_ADV: Get contents of a url -- advanced version
    Use socket calls to retrieve the contents of a url. This version is more robust than SRE_GET_URL -- it will detect and gracefully recover from broken connections and other errors.

    Syntax:

        stuff=sre_get_url_adv(maxtime,maxbytes,type,server,req, ,
             mehost,upwd,mhdrs,verbose,qs,trn_Id,sock_time)

    where ... :
    maxtime Optional. max time (in seconds) to allocate for this request. If this time is exceeded, close the connection and return an error message.
    If not specified, 30 seconds is used
    maxbytes Optional. max bytes to allocate for this request. If this size is exceeded, close the connection and return whatever results you've gotten, with a status code of 6.
    If not specified, 100M is used.
    type Type of request. Typically, HEAD or GET.
    However, three special proprietary types can be specified:
    • DNS = lookup ip address of server. Return the IP address, perhaps with :port appended
    • HEADGET = Use a GET request, but only return the HEAD (or the first 999 characters, whichever is less)
    • DSCGET = Use a GET request, but only return the first 1499 characters
    server the server to send the request to. This can be a dns name, or an ipaddress.

    Alternatively, you can use the following more complete syntax:
       dom_name,ip_address,proxy_address

    where:

    • dom_name : the domain name (or number) to send the request to. If a non-80 port is used, append :port_number (i.e.; foo.bar.net:8082)
    • ip_address : optional, the dotted numeric IP addres for the domain. If not included, a DNS request is done to resolve dom_name to an ip address. (thus, use of ip_address is a time saver), Do NOT append the ip port (if needed, it should be appended to dom_name)
    • proxy_address: Ip address of this proxy. If possible, give the numeric address. If a name is given, then a DNS request is done (thus, use of a numeric address is a time saver) If the proxy is using a port other then 80, append :port_number to the proxy_address (even if it's numeric).
      For example: foo.bar.net:8080 or 152.15.22.16:8080

    Notes:

    • If you are NOT using a proxy server, leave proxy_address blank. For example: foo.bar.net, 189.12.51.62
    • If you specify a proxy, then IP_address is ignored
    • dom_name is required, even if it's the same as the ip_address (it is used to form a Host: header)
    req the request string.
    For example, the /mydir/index.sht portion of http://foo.bar.net/mydir/index.sht
    upwd Optional. Username password,
    If specified, a Basic Authentication request header will be added.

    These should be seperated by a space.
    For example: Joe Xegi3

    Alternatively you could add an explicit header, in mhdrs, using:

                 aa=sre_pack64_make(strip(username)':'strip(passwd))
                 mdirs='Authentication: Basic '||aa
    mehost Optional. the callers domain name or ip address. This is used in a REFERER request header,
    mhdrs: optional A crlf delimited list of headers, where each line has the form
    Header_NAME: a string
    verbose Verbosity of intermediate output. Intermediate output is written to the PMPRINTF "window" (which can be displayed using PMPRINTF.EXE).
    • 0 = NO intermediate output (the default)
    • 1,2, or 3 signal various levels (minimal, some, too much)
    qs A two component argument, containing: the queue to send results back on, and the semaphore to use for forcing timeouts.

    This is not required if this is "called as a procedure", though the semaphore component of the argument can be used (though it is less likely to be useful)

    The queue component is required if this is "called as a daemon"; the semaphore component is not required, but if available it will be used (it makes much more sense to use the semaphore when calling as a deamon).

    The syntax of qs_info must be:
        Queue_name semaphore_name
    For example: QCH_0193 /SEM32/SRE2003_32_02

    The optional semaphore_name should be an open and posted 32 bit semaphore.

    When launched as a daemon, this procedure will poll this semaphore before all socket calls, and if is not posted (or if it has been closed), then an immediate timeout is forced. If you do not include a semaphore_name, then you won't be able to force a timeout. Otherwise, if you do not specify a semaphore, everything else will work (though the polling will not occur).
    trnid Not required if a procedure call. a transaction thread id. Should be unique to this transaction -- it's used to identify the response when returned through a queue. Therefore, it is not needed when calling this as a procedure.
    sock_time max time per socket call This must be less then tottime. If not specified, 30 seconds is used.
     
    Returns:
    • If no error:
    • When called as a procedure:
      If maxbytes is not binding: 0' 'ip_address||'0d0a'x||stuff
      If maxbytes is binding: 6' 'ip_address||'0d0a'x||stuff

    • When called as daemon, sre_get_url_adv will push
      trnid||' 0 '||ip_address||'0d0a'x||stuff
      or, if maxbytes is binding, trnid||' 6 '||ip_address||'0d0a'x||stuff
      to queue_name

    • Note: stuff is response from the server
    • If error:
    • Procedure call: return an error-code
    • Daemon call: push transaction||' '||error_code||' '||error_message
    • Error codes:
              0 = no error 
              1 = ioctl error
              2 = connection error
              3 = problem encountered in sockrecv 
              4 = sockgethostbyname error 
              5 = coding error in this procedure
              6 = maxbytes limit is binding 
    Examples:
     Call as procedure:
        moo=sre_get_url_adv
              (50,'GET','foo.bar.net,125.22.251.2','/abc/alpha.htm','mysite.net',, 
               'myname mypwd',,1,,,20)
    
     as procedure, using a proxy:
    
       oo=sre_get_url_adv(50,'DNS','proxy.wow.com')
       parse var oo . aproxy '0d0a'x .
       moo=sre_get_url_adv(50, ,
               'GET','foo.bar.net,,'||aproxy,'/abc/alpha.htm','mysite.net',, 
               'myname mypwd',,1,,,20)
    

    SRE_GMT: Compute a new GMT time
    Given a time & date string, and an offset, compute a new GMT time.

    Syntax:
        newtime=sre_gmt(offset,basetime,outtype,gmtoffset)
    where:
    offset: offest in days, hours, seconds, or minutes
    basetime: in several formats
    outtype: format of output
    gmtoffset: Optional, the size of gmt offset (in seconds). If not provided, it will be looked up.
    newtime the new time (incorporating the GMT offset and "user supplied" offset), in the desired format

    Details

    Offset Add an offset to the "current time". Format can be:
    • days : the default. Use a real number. i.e.; 1.3 (1.3 days), or 0.05 (1/20 day)
      Or, or you can add a d; say, 1.3d
    • hours: use an integer followed by an h. i.e.; 1h
    • minutes: an integer followed by an m. i.e.; 60m
    • seconds: an integer followed by a s. i.e.; 3600s
    The default offset is 0 (no offset)

    If not specified (or '' is specified) then compute current GMT time (for supplied basetime)

    basetime: The time to add the offset to. The input format can be any of the following (SRE_GMT will recognize the format)
    julian 728882.887731 (days since 0/0/00 . fraction of day)
    internet Sat, 12 Aug 1996 21:18:20 GMT
    old internet Saturday, 12-Aug-96 21:18:20 GMT
    ansi c Sat Aug 12 21:18:20 1996
    query datetime 08-12-96 21:18:20
    sysfiletree 96/08/12/21/18 or 96/09/12/21/18/22
    If not specified, the default is to use the current time
    Outtype The output format
    I (the default) internet style
    J julian, from 0/0/00
    JS julian, from 1/1/1990.
    Note: JS time equals J time + 726467.
    C cookie -- similar to internet, but use 12-Aug-1994 (suitable for expires field of set-cookie)
    F sysfiletree
    GMT_OFFSET
    • If 0, do NOT add a GMT offset (and do NOT add the GMT to I or C outtype)
    • If >0, then use this as the GMT offset (in SECONDS)
    • If not specified, use the TZ environment variable (via the SRE2003 sre_gmtoffset function)

    Examples:

        say sre_gmt(,728882.88773)
        say sre_gmt(.12,'Sat, 12 Aug 1996 21:18:20 GMT','J')
        say sre_gmt(.12,'Sat, 12 Aug 1996 21:18:20 GMT','JS')
        say sre_gmt('18000s','Saturday, 12-Aug-96 21:18:20 GMT')
        say sre_gmt('300m','Sat Aug 12 21:18:20 1996 ')
        say sre_gmt('5h','96/08/12/21/18','C',0)
        say sre_gmt('5h','03/08/12/21/18','C',0)
        say sre_gmt(,,'F',0)
      yields ....
        Tue, 13 Aug 1996 02:18:19 GMT
        728883.216064
        2415.216064
        Tue, 13 Aug 1996 07:18:19 GMT
        Tue, 13 Aug 1996 07:18:19 GMT
        Tue, 13-Aug-1996 02:17:59
        Wed, 13-Aug-2003 02:17:59
        01/11/25/16/54
        
    Note:
    SRE_DATESTAMP is a simpler version of this procedure.

    SRE_HTML_ENCODE:replace special charaters with HTML entity references
    SRE_HTML_ENCODE will replace reserved HTML characters with their entity references.

    Syntax:
       newmess=sre_html_encode(oldmess)

    Precisely,
    all instances of ... are replaced by
    < &lt;
    > &gt;
    & &amp;
    " &quot;
    Also, any character with ascii value > 127 is replaced with &#nnn;

    SRE_HTML_REPLACE: replace comments in an HTML file
    SRE_HTML_REPLACE is used to replace special HTML comments with a string. SRE_HTML_REPLACE is a useful tool for peforming simple server side includes.

    Syntax:
       nustuff=sre_html_replace(stuff,sub1,...,sub15)

    where:
    stuff a string containing html
    sub1,...,sub15    Up to 15 substitution strings.

    Each subN has the structure:
       code_to_replace replace_with_string

    For example, if sub1 equals:
        #LINK <a href="/hello.htm">Hello world!</a>
    then any occurence (in stuff) of:
        <!-- #LINK --> will be replaced with
        <a href="/hello.htm">Hello world!</a>

    Notes:

    SRE_HOSTINFO: read & set host information
    SRE_HOSTINFO is used to read the host-nickname and default data directory for a host name. Host names are typically domain names (such as foo.bar.net), but they can also be dotted IP addresses (such as 125.221.51.2), or "intranet" addresses (such mymachine).

    To support multi-hosting (one server supporting multiple domains), SRE2003 uses the idea of a "host nickname". Every request is compared against the list of defined hosts. If a match is found, the host-nickname and the default data diretory are returned. The filter can then use this information to determine where to get a file from, where to store logging information, etc etc etc.

    Although SRE2003 supplies the filter with this information (see section 5a of the main documentation), you can also use SRE_HOSTINFO to look it up. Furthermore, although you can use the INITHOST.RXX initialization procedure INIT_PROC (see INITHOST.RXX in the BIN subdirectory) to define Host entries, you can also use SRE_HOSTINFO.

    SRE_HOSTINFO has several modes:

    SRE_LIST: Write/read entries in a randomly accessible list
    Lists are used to store semi-permanent variables. Each list is allocated a fixed number of slots (one slot per variable), As you add variables, eventually all the slots will be taken. At that point, a LIFO (last in first out) algorithim is used to free up space -- with one value removed. Items on a list are NOT referenced by variable name, though they can be read by position number (however, this position number will change as items are added to the list).

    Syntax:
        val=sre_list(list_name,action,avalue,ownid)

    where:
    list_name The name of a list.
    Examples of list_name: BYTES TOTAL_TIME START_TRANSMIT_TIME
    action Possible actions: CREATE RESET PUSH QUEUE POP PEEK READ STATUS LIST
    avalue A value to store. If you intend to use SRE_LIST_STATS on this list, these values must be numeric.
    ownid optional, it's the own_id of the caller. Or, set to 0 to mean "don't bother responding" (typically used with action of PUSH or QUEUE)
    The supported actions are:
    CREATE create a list aval is the length of the list. If aval is not specified, a default of 600 is used. Returns: 1 on success
    RESET clear all items in alist If avalue is specified, reset the size of the list to avalue. Returns: 1 on success
    PUSH add aval to top of list (will be first out on a pop) Returns either 'OK 'value or 'ERROR 'error_message
    QUEUE add aval to bottom of list (will be last out on pops) Returns either 'OK 'value or 'ERROR 'error_message
    POP pop top value from list (remove the value). If list is empty, return '' or the value of aval.
    PEEK look at top value from list (do not remove) If list is empty, return '' or the value of aval.
    READ nnn look at the nnn'th value from list; where 1 is the bottom value (the last value before list is emptied)
    STATUS returns 1 line of status info:
    '#_entries='nentries', Max_entries='list_size
    LIST returns list of lists, using
        #entries_in_list (crlf)
        value (crlf)
        ...

    Notes


    Examples:
        foo=sre_list('REQUEST','QUEUE',request_line,0)
        nextval=sre_list('DELETEME','POP')

    SRE_LIST_STATS: Compute statistics on values stored in a list
    SRE_LIST_STATS is used to compute simple statistics on values stored in a list. Of course, this should only be used with lists that are known to contain ONLY numeric values!

    Syntax:
        val=sre_list_stats(list_name,action,nentries,ownid)

    where:
    list_name name of list. Examples include: BYTES TOTAL_TIME START_TRANSMIT_TIME If the list_name doesn't exists, error
    action stat to compute. Currently supported: NUM MEAN MAX MIN SD SUM.
    If nentries specified, NUM is <= NENTRIES
    nentries Number of entries to use. If not specified, then use all entries available in the list.
    ownid optional.
    Examples:
        foo=sre_list_stats('TOTAL_TIME','MEAN',100,own_id)

    SRE_MD5: Compute an MD5 hash
    SRE_MD5 is used to compute the MD5 of a string or a file.
    SRE_MD5 also maintains a "cache", which can help with both speed and stability.

    Syntax:
        md5val=sre_md5(var_or_file,file_flag,nocache)
    where:
    var_or_file: either a variable containing the string you want the hash of, or a fully qualified file name
    file_flag: If 1, then var_or_file is a file name. Otherwise, var_or_File is a variable.
    nocache: if 1, then do NOT look in the SRE2003 "MD5 of files" cache. This can be used to force recomputation of the MD5 of a file.

    Examples:

           amd5=sre_md5('hello world ')
           bmd5=sre_md5('D:\CONFIG.SYS',1)
    

    Notes

    • The size of the "MD5 of files" cache is set by the MAXMD5S variable in SRE2003.CFG
    • SRE_MD5 uses procedures in SRXFUNC.DLL
    • When the MD5 cache is enabled, then SRE_MD5 will "serialize" the computation of MD5s.
      This helps system stability: the MD5 procedures in SRXFUNC.DLL can sometimes CRASH THE PROCESS (i.e.; kill SRE2003), a phenomemnon that seems to happen when its functions are called simultaneously.

      Thus, use of SRE_MD5 (rather then the SRXFUNC functions directly), in conjunction with MD5 cache, will bolster system stability (as well as possibly improve speed).

    SRE_MOVE_RESPONSE: Return an resource-moved response to the client
    SRE_MOVE_RESPONSE is used to send a this resource has been moved response to the client.
    Syntax:
       rcode =sre_move_response(movetype,selector,servername,port,age,sel0)
    
    where
    movetype (optional) Type of move. Can be 301 302 303 200 or 307 or, equivalently, MOVE TEMP REDIRECT NOTIFY or REPOST.
    If not specified, a 301 (permanent move) response is returned to the client.
    selector the selector (or fully qualified uri) to "move" to. If no domain name (or IP address) is specified in selector, and servername and port are not specified, then the redirection is back to this site (that is, to the servername and port of this request).
    servername(optional) If no ip address listed in the selector argument, "servername" is used
    port (optional) If specified, redirect to this port (otherwise, redirect to the standard http port)
    age (optional) Length of time proxy caches should store this response (in seconds)
    sel0 (optional) The "original selector". It is used only with NOTIFY (it is written in the body of the response).
    and
    rcode the return code from SRE_COMMAND('VAR ..)

    SRE_NOTFOUND_RESPONSE: Returns a not found response to the client
    SRE_NOTFOUND_RESPONSE returns a not found (403,404, or 410) response to the client.
    Syntax:
       rcode=sre_notfound_response(type,message,servername,sel,id_info)
    
    where:
    type Either 403,404 or 410. Or, FORBIDDEN, NOTFOUND, or GONE 403 or FORBIDDEN = the server is refusing to honor this request (authorization will not help) 404 or NOTFOUND= The default. Resource can not be found 410 or GONE = The resource has been permanently removed.
    message Optional. If specified, this should be a full html response (including < / html > ... </html >)
    Otherwise the body of a response will be created (depending on type).
    servername optional. Looked up if not provided
    sel Optional. The requested resource (if not provided, it will be looked up)
    id_info Optional. The "id_info"
    Rcode is the response from a SRE_COMMAND('VAR ..') call. It contains the "response code".

    SRE_PACK64: Unpack a "mime-encoded" string

    Syntax:
        text_val=SRE_pack64(encoded_string)

    SRE_PACK64_MAKE: Create a mime-encoded string.
    Create a mime-encoded string.

    Syntax:
        encoded_string=sre_pack64(some_text)

    SRE_PACKUR: Unpack a URL-encoded string:

    Syntax:
        uval=sre_packur(pval)

    Example:
    pval='DOG+%26+CAT+%3D%3D+FUN%21+%0D%0A%24+%2F+TIME+%3D+%25+%3F+'
    uval=sre_packur(pval)

    yields
    uval=DOG+&+CAT+==+FUN!+$+/+TIME+=+%+?+

    Note that + are NOT converted to spaces!

    You can use
    uval=sre_packur(translate(pval,' ','+'))
    to convert + to spaces (do + conversion first, otherwise you might transform true "+" characters into spaces).

    SRE_PACKUR_MAKE: Create a URL-encoded string:

    Syntax:

  • pval=sre_packur_Make(uval)

    URL-encode the most common special characters, and all characters with ascii values <32 or > 127.

    These most common special characters are:
         Character   hex-value
         ----------------------
             tab        09
            space       20
            "           22
            <           3c
            >           3e
            [           5b
            \           5c
            ]           5d
            ^           5e
            `           60
            {           7b
            |           7c
            }           7d
            ~           7e
    
  • pval=sre_packur_Make(uval,1)

    When a 1 is used as a second argument, a more aggressive URL-encoding is computed. In particular, the percent (%), forward slash (/), semi-colon (;), comma (,), plus (+) and hash (#) characters are also URL encoded.
    Since these characters can have special meaning in URLS, this feature should be used carefully!

  • pval=sre_packur_Make(uval,2,'xyz')

    Only encode the characters in the 3rd argument (the xyz). This is useful if you just want to encode spaces, or some other small set of characters.

  • Example::
    uval='DOG+&+CAT+== FUN! +$+/+TIME+=+%+?+'
    pval=sre_packur_make(uval)

    pval will equal:
    DOG+&+CAT+==%20FUN!%20+$+/+TIME+=+%+?+
    Note that spaces are converted to %20, but + are not converted.
    Hence, for this example you probably should use:
    pval=sre_packur_make(uval,1)
    pval will equal:
    DOG%2B%26%2BCAT%2B==%20FUN!%20%2B$%2B%2F%2BTIME%2B=%2B%25%2B%3F%2B

    SRE_PAUSE: Pause & unpause SRE2003
    Report on pause status of SRE2003; or pause, or unpause, When paused, SRE2003 will not accept new connections (but will continue processing current connections).

    Syntax:

            pstate=sre_pause()   -- pstate=1 if curently paused, 0 otherwise
            call sre_pause(0)   -- unpause SRE2003
            call sre_pause(1)   -- pause SRE2003
    
    SRE_PMPRINTF:
    Write a message to the PMPRINTF window.

    SRE_PMPRINTF basically uses the PMPRINTF function, but it first checks for some possible bugs; for example, it won't try to write overly long lines.

    Note: to view the PMPRINTF window, you can use the PMPRINTF program

    Syntax:

         call sre_pmprintf(message)
      or
         foo=sre_pmprintf(message,all)
    

    where:
    message: is the text message to write to the pmprintf window
    all: optional. If message is > 110 characters, write on several 80 character lines

    Examples:

           call sre_pmprintf('a message here')
           foo=sre_pmprintf(' this is a long message .... ',1)
    
    

    SRE_READ_FILE:
    Read a file. Returns file length and date, and file contents; or returns an error code.

    Syntax:
      stuff=sre_read_file(filename,n_tries,stype,stripcz,nchars,offset)

    where:
    filenamefile to read
    n_tries Optional
    # of times to try to open file (if temporarily locked).
    If not specified, only 1 attempt is made to open the file.
    stypeOptional
    Effects what is returned.
  • 1 : status only -- do not return contents
  • 11: same as 1, but do not close the file
  • 2 : contents only, or '' if an error occurred
  • 3 : same as 2, but try harder (retry if file exists but is 0 length). Also, if file does not exist, wait a second and try again
  • 4 : Same as default (' '), but use FILEREXX procedures
  • 5 : Same as 2, but use FILEREXX procedures
  • otherwise : return status and contents (as described below)
  • stripcz Optional
    If 1, then strip trailing Ctrl-Z (and anything that may follow).
    nchars Optional. If specified, this number of bytes will be read from filename.. If filename is less then or equal to nchars bytes long, then all of the bytes in filename will be read.

    Note that the size variable reported (say, if status='') is the size of the file, and not the number of bytes read from the file.
    offset Optional. Where to start reading after. Thus, an offset of 10 means the 11th character of the file is the first character read.
    If offset is greater then the file size, a ' ' or a -4 error message is returned (depending on stype).
    If offset + nchars > file_size, return the final file_size - offset characters.
    stuffstatus code and contents of file, or an error response

    The structure of stuff is:
    If file was
    successfully read
    file_length file_date fully_qualified_filename '0d0a'x
    file_contents

    Notes:

  • file_length can be 0 (in which case there is nothing after the '0d0a'x.
  • file contents can be anything (binary or text, with or without additional '0d0a'x).
  • Exceptions:
    • stype=1 or 11 : Return "status" only: do not return file_contents (there will be nothing after the '0d0a'x).
    • stype=2 or 3 : Return contents only: do not return status info (the first character of stuff is the first character of the file).
    file could
    not be read
    error_code error_message

    The error_codes are always negative valued integers:

  • -1 = no such filename
  • -2 = filename exists, but size was not produced
  • -3 = unable to open this file, even after trying several n_tries times
  • Exceptions:
    • stype=2 or 3 : Return a blank string.

    Notes:

    • There is a one second delay between attempts; hence n_tries is essentially the max seconds to keep trying to open filename.
    • If stype=2 or 3, there is no way to distinguish between an error, and an empty or 0-length file. If you use stype=2 and the returned value is '', it is a good idea to try again with a stype=0 call.
    • Error code -2 occur when stream(filename,'c','query size') returns ''. This should never happen (if the file does not exist, a -1 is immediately returned).
    • Error code -3 occurs when stream(filename,'c','open read') returns NOTREADY.
    • The file_date is returned as nnn.ffff, where nnn is days since Jan 1 1990), and fff is a fraction of a day (accurate to 1 second, when 0.fff is multiplied by 86400).
      For example, 01-20-02 21:27:32 will be 4402.89412037
    • The FILEREXX procedures, used in stype of 4 or 5, will read locked files (files that are opened-for-writing by other processes). This can be convenient if you want to read the current contents of dynamic files (such as log files).

    Examples:

     parse value sre_read_file('fname.1',4) with ilen fdate fname2 '0d0a'x content
     if ilen<0 then signal error_read
    
     content=sre_read_file('fname.1',4,2)
     if content='' then signal error_read  
    

    SRE_REQFIELD: Read request headers
    Reads one (or several) request header(s).

    Syntax:
        avalue=SRE_reqfield(header_name,ith,id_info)

    where:
    header_name the name of a request header.
    For example: "User-Agent", "Authorization", "If-Modified-Since", or "X-Option1"
    Header_name is case insensitive
    ith Optional. Ith instance of this header_name. If not speciifed, all instances of header_name will be concatenated and returned.
    id_info Optional. Including the "id_info" (say, as supplied to the filter) will speed things up a bit.
    Actually, header_name can be a space delimited list of names.
    For example:
        oo=SRE_reqfield('TE ACCEPT-ENCODING')
    Note that you can NOT combine "list of headernames" with "ith instance"

    When asking for several headers, each header will be seperated by a '01'x character. Thus, in the above example you could use:
        parse var oo is_te '01'x accept_enc
    to obtain the "TE" and the "ACCEPT-ENCODING" request headers.

    Note:

    SRE_REQUEST_INFO
    Read "id" info for a request.

    Syntax:
        aval=sre_request_info(avar,usetid,id_info)

    where:
    avar variable to lookup. If avar is not specified, then return the id_info variable for this request.
    usetid optional. The thread-id of the request you need information about.
    If not specified, lookup info for the current request.
    id_info optional. The id_info (say, as is provided to the filter). This can speed processing a bit.

    The supported variables include:
    !LIST return comma delimited list of request-number transaction-tid request-tid,
    For example:251C 12 26,353A 15 23
    !LISTALL Return a crlf delimited list of:
    clientIP,own_id, transaction_daemon_id,socket,starttime,host_nickname,transaction_tid,transaction_num,request_num,selector
    CLIENT the client's IP address
    OWN the own_id
    TRAN the transaction's daemon_id
    NTH the transaction number (which will be the same for several requests delivered over a single maintained-connection)
    SOCK the TCP/IP socket
    HOST host nickname
    REQ the request number, in nnnAA format
    SEL selector
    START starttime (date & second)
    PARENTID the thread-id of this request's "parent" (the thread-id of the transaction daemon that is handling this request)
    Note that these variables all refer to either the current request, or to the request pointed to be usetid.
    Also note that these are "abbreviation matches". For example, CLIENTADDR is the same as CLIENT.

    Example:

  • parse value sre_request_info('CLIENT SOCK START ') with aclient ',' asock ',' started_at
  • Notes:

    SRE_REPLACESTRG: Replaces substrings in a string
    Replace one, or all, substrings in a string with a new substring.

    Syntax:
        newstring=sre_replacestrg(astring,target,putme,type,exact)
    where:
    astring: the string to change
    target: the substring to replace
    putme: the substring to use as a replacement
    type:
  • not specified : replace first occurence of target
  • BACKWARD : replace last occurence of target
  • ALL : replace all occurences of target
  • exact: if 1, then do not capitalize during search (exact match only)
    newstring will be astring with occurences of target replaced by the putme

    Example:

            nustg=sre_replacestrg('This is too big ','too','very')
                 yields: 'This is very big '
            nustg=sre_replacestrg('This is also small, also ','also')
                 yields: 'This is small, also '
            nustg=sre_replacestrg('This is also small, also ','also',,'ALL')
                 yields: 'This is small, '
            nustg=sre_replacestrg('Is Also small, also','also',',maybe','ALL',1)
                 yields: 'Is Also small, maybe'
    
    

    Notes

  • If putme is not specified, then simply remove occurences of target
  • In contrast with SRE_REPLACEWILD, sre_replacestrg does not recognize wildcards.
  • SRE_REPLACEWILD:
    SRE_REPLACEWILD checks if the non-wildcarded portion of "template" matches the "needle". If so, copy the portions of the needle "covered" by wildcards in the template to the corresponding wildcarded portions of the "replacement". Note that the non-wildcarded portions of the replacement do NOT have to match the needle or template!

    This permits quite extensive transformations of the needle.

    Syntax:
        new_string=SRE_REPLACEWILD(needle,template,replacement)
    where:
    needle: the string to examine. It should not contain any * (wildcard) characters
    template: compare needle to this string. template usually contains one or more * (wildcard) characters
    replacement: substitute portions of needle, that are wildcard matches to template, into the corresponding wildcarded portions of replacement
    If replacement is not specified, set replacement=template
    new_string will equal:

  • ' ' = no match (the template was NOT a match to the needle)
    or,
  • string_with_replacements = the "replacement", with suitable replacements.
    Note that if the needle and the template are exact matches, then return the replacement as is (*'s and all)
  • Examples:

                   needle =  /proj1/mine/joe.htm  
                 template =  /proj1/*
              replacement =  /work2/project8/ver1/*
               would yield:  /work2/project8/ver1/mine/joe.htm
     
                needle=   /proj1/eek/mine/joe.htm
               template=  /proj1/*/joe.htm
            replacement=  /work2/project/*/joe.htm
            would yield:  /work2/project/eek/mine/joe.htm
    

    Note

  • In contrast with SRE_REPLACESTRG, sre_replacewild does not replace all target substrings with replacement substrings.
  • SRE_SERVER: return descriptive name of the server software
    SRE_SERVER will return a short descriptive name of the server. In particular, it will return the value of either the SERVER_SOFTWARE, SERVER_SOFTWARE_SHORT, or FILTER_VERSION parameters (that are set in SRE2003.CFG).
    Syntax:
        sname=SRE_server(which)

    where which is optional, and should be one of:

  • N= The value of the SERVER_SOFTWARE parameter. This is the default.
  • S or H= The value of the SERVER_SOFTWARE_SHORT parameter.
  • F= The value of the FILTER_VERSION parameter
  • NF, SF= The concatenation of a pair of these parameters
  • SRE_SAY: Write message to bottom of status screen
    Write to the bottom of the SRE2003 status screen. The message will also be written to the PMPRINTF window.

    In general, we recommend using SRE_WRITE_MESSAGE instead of SRE_SAY.

    Example:
        call sre_say("this is my message to you, rudy. ")

    SRE_SERVERNAME: return the domain name of the server
    SRE_SERVERNAME will return the servername. This may be a host specific servername.
    Syntax:
        sname=SRE_servername()
        sname=SRE_servername('default')

    If 'default' is specified, then the "canonical" (default) servername for this computer is returned: either as determined from TCP/IP calls, or as set in the SERVERNAME_USE configuration parameter.

    For what TCP/IP reports as the servername, check (using SRE_VALUE) the SRESYS variable SERVERNAME_CANONICAL

    SRE_SHUTDOWN:
    Tell SRE2003 to shutdown, or see if a shutdown has been signalled (say, by another process).

    Syntax:

            call sre_shutdown(1)   -- tell SRE2003 to shutdown
            isdown=sre_shutdown()   - returns 1 if "shutdown" has been signalled, 
                                      0 otherwise
    
    On SHUTDOWN, SRE2003 will stop accepting new connections, and will give current connections up to 90 seconds to finish.

    SRE_TEMPFILE:
    Returns a name for use as a temporary file, said name being (by default) in the SRE2003 temporary directory.
    SRE_TEMPFILE can also delete a "junk" temporary file that may already exist and that has a suggested temp file name.

    Syntax:
    There are two modes: thread-specific file name mode, and random file name mode

    • Thread-specific (recommended for creating short-life temporary files)
          tempfile_name=sre_tempfile(str1,str2,tempdir,del_opt)
    • Random (recommended for creating archive and backup files)
          tempfile_name=sre_tempfile(qname,harsh,tempdir)

    Parameters usage:

    • Thread-specific mode -- all of the arguments are optional
      str1 a ?, or a unique identifier (unique to the process). It is used to form the first part (left of the .) of the tempfile name.
      • If ?, a temporary filename will be randomly generated
      • If not specified, the current process id is used
      • Otherwise, str1 is used
      str2 a "unique to thread" id. If not specified, the current thread id is used. It is used to form the second part (right of the .) of the tempfile name.
      tempdir directory where temporary file will reside. If not specified, use the SRE2003 TEMP directory.
      delopt
    • 0 or not specified: delete existing temp file.
      If undeleteable, try alternate names
    • 1 : delete existing temp file.
      If undeleteable, return ' ' (do not try alternate name)
    • 2 : if file exists, try alternate names (do NOT delete)
    • 3 : if file exists, return ' '
      (do not delete, and do not try alternate names)
    • Random-name mode the 2nd and 3rd arguments are optional
      qname a filename that contains at least one ?. If relative filename, it will be relative to the tempdir parameter (or to the SRE2003 TEMP directory, if tempdir is not specified).

      A non-existent file name that matches the pattern in qname will be looked for.
      If such a non-existent filename is found, it is returned.
      If there are no non-existent files matching this pattern, harsh determines what to do.

      harsh if harsh is a ? , then the oldest file matching the pattern in qname is deleted, and its file name is returned.
      Otherwise, a blank (a ' ') is returned.
      tempdir directory where temporary file will reside. If not specified, use the SRE2003 TEMP directory.

    Examples:

            tname=sre_tempfile()
            tname=sre_tempfile("PX"||dospid(),dostid())
            tname=sre_tempfile('?')
            tname=sre_tempfile('?','CSH','F:\WWW\TEMP\CACHE\',3)
            tname=sre_tempfile('FOO.???','?')
    

    SRE_TRACKIT: set and get "tracking" variables
    For more details on tracking, see Appendix 5 (of the main documentation).

    Syntax:
        aval=sre_trackit(varname,avalue,record_id,record_name,ownid)

    where
    varname the "tracking" variable to set/get
    value the value. If '', then "get" value; otherwise set the value
    record_id the id of the record to read variables from. If not specified, use the current thread id.
    record_name optional. Record_name if included, will be compared to the "assigned name" for this "record" -- an error is returned if there is no match.
    ownid optional. You can include this "ownid" if READING tracking info from a request thread (i.e.; from a filter) Or, set to 0 to suppress reply (i.e.; on !CLEAR or a variable set)
    Notes:

    Examples:
    • foo=sre_trackit('READHEAD','END' ,mytid,mytid,0)
    • foo=sre_trackit('VAR1 VAR2 ','125 MARS',25)
    • aval=sre_trackit('VAR10',,,,ownid)

    SRE_UNCHUNK:
    UnChunk a chunked message.

    Syntax:
        stuff=sre_unchunk(cstuff,inct)
    where:
    cstuff: a chunked message
    inct if 1, add trailers (if any are found at the end of the message) at beginning of returned value (trailers blank_line entity).
    stuff will be the "unchunked" version of cstuff, with trailers possible added to the beginning.
    Note that trailers (if added) always end with a blank line.

    SRE_VALUE:
    Lookup a variable in one of several "environments".

    Syntax:
        avalue=sre_value(varname,value,enviro,ownid,transaction_id)
    where:
    varname: variable name to get or set
    value: value to set. If empty, then lookup value
    enviro: where to get value from. There are six environments:
    OS2, SRESYS, SRE, GLOBALS, SRELARGE, SREBEST, and REQ
    OS2 from the os/2 environment. In this case sre_value is just like the VALUE function
    SRESYS SRE2003 "system" variables. These are set when SRE2003 is started. In general, they are not meant to be changed "on the fly".
    SRE The default. A general sre variable. These are semi-permanent SRE variables --once set, they can be read by later transactions.
  • They can also be read quickly.
  • Their values can not be over 200 characters long,
  • Their values MUST NOT contain non-text characters.
  • Value setting and reading are not serialized. Thus, SRE variables should be set by just one daemon, but they can be read by many simultaneously running daemons.
  • SRE2003 reserves the following SRE variables for internal use:
    TRAN_INFO_CT, REQ_INFO_CT
    CLIENTNAME_CACHE, HOSTNAME_CACHE
    several versions of REQ_nn_INFO (where nn are integer "thread ids")
    CT_varname (where varname is one of: BYTESREADTOTAL BYTESSENTTOTAL TRANSACTIONS REQUESTS LIMITS ERRORS BROKEN CACHEHITS)
    EVENT_varname (where varname is one of: LASTACCEPT LASTIDLE LASTRESET LASTADDRESS PEAKCLIENTS )
  • GLOBALS Very similar to sre variables. The only difference is that the GLOBALS environment is isolated from the SRE environment; when using GLOBALS one does not have to worry about accidentally changing internal SRE2003 variables.

    Hence ...

    • there are no reserved global variables.
    • GLOBALS is well suited for use by casual programmers (such as script writers)
    SRELARGE A general sre variable. These are semi-permanent SRE variables --once set, they can be read by later transactions.
  • Their values do NOT have a size or contents restriction (they do NOT have to contain only text characters).
  • However, they are not as quickly retrieved as SRE variables
  • Value setting and reading ARE serialized. Thus, SRELARGE variables can be both set and read by several simultaneously executing daemons.
  • As of this implementation, they are stored using the SRE_VAR daemon
  • SREBEST A general sre variable. Use either SRE or SRELARGE, depending on the length and contents of the value. Basically, if the length is less then 132 characters, and all the characters are text, then store the value using the SRE environment. Otherwise, store the value using the SRELARGE environment.
    REQ transient, request specific variables. These are removed after a request is completed.

    Hence:

  • Their values can be large, and have no contents restriction
  • As of this implementation, they are stored using the "transaction daemon" that services the request
  • ownidOptional. The "own id", used for daemon communication. This is optional; if not provided, an "own id" will be created
    transaction_id: only use if enviro=REQ.
    If specified, then this is the daemon_id of the transaction for which you want request specific info (note that transaction daemons launch request daemons in a sequential fashion; a transaction is responsible for one request at a time, but it may be responsible for several sequential requests over the same connection)
    If not specified, then use the transaction associated with the current request -- this REQUIRES that sre_value be called from a procedure running under a request daemon (that is, be called by the filter or a script launched by a filter, but not by a "support" daemon).

    Examples:

            vv=sre_value('DPATH',,'OS2')
            vv2=sre_value('TEMP_DIR',,'SRESYS')
            vv3=sre_value('SMALL_VAR_1','this is a small var ','SRE')
            vv4=sre_value('FILE_X',charin('C:\CONFIG.SYS',1,1000),'SRELARGE')
            vv5=sre_value('REQ_Z','request is running ','REQ')
            vv6=sre_value('ADDON_2_V10',,'GLOBALS')
            vv7=sre_value('RECENT_USERS',,'SREBEST')
    
    
    

    Note: OWNID and TRANSACTION_ID are ignored when reading or writing to the OS2, SRE, and SRESYS "environments".

    SRE_WRITE_ERROR
    Write an error message (up to 2 lines, 70 characters per line).
    Syntax:
       astat=sre_write_error(error_message,nofile,doprint)

    Where:

    Examples:
        call sre_write_error('Foo1: got a BAR error')
        call sre_write_error('This silly error message will also be pmprintfed',,1)

    SRE_WRITE_MESSAGE
    Write a text message string to the message-area of the SRE2003 status screen. The string can be up to 140 characters long; characters from 71 to 140 will be wrapped onto a second line. Characters beyond the 140th are discarded.

    Syntax: foo=sre_write_message(messge_string,toaudit)

    Where:

    Examples:
        call sre_write_message(' Hello cruel world? ')
        call sre_write_message(' Not ready to quit ',1)

    SRE_WILD_MATCH:
    Wild card match, with comparison against prior wild card match

    Syntax:
        resu=SRE_WILD_MATCH(needle,haystack,oldresult,suppress_noslash)
    where:
    needle: what to look for
    haystack: what to compare it to. Haystack may contain numerous * wildcard characters
    oldresult: prior return from sre_wild_match; or ' ' (if no prior match was made)
    suppress_noslash: if 1, suppress the "no slash" special feature (see below)
    resu: The returned value depends on oldresult...

    • If needle is exact match to haystack: resu will equal -1
    • If needle does not match haystack (even with wild card checking): resu will equal 0
    • If needle wildcard matches haystack, and oldresult='': returns match information.
      This match information can be used as the "oldresult" in subsequent calls to sre_wild_match.
    • If needle wildcard matches haystack, and oldresult<>'' (oldresult is the result of a prior call to sre_wild_match),
      1. compare the current match to the "oldresult" match
      2. if current is "better", return the match result
      3. otherwise (current match is not an improvement), return 0
    Note: a "better" match has more matching characters early in the string

    Basically, -1 means "exact match", 0 means "no match" or "not better match" (if oldresu not specified, 0 always means "no match"), and everything else means "better wild card match".

    Example:

       a.1='This is *'
       a.2='This is a *'
       a.3='This is a funny * story'
       a.4='* is * '
       a.5='Th* fun*'
       a.6='This is funny *'
    
       say "Enter string : "
       parse pull ans
       oldresu=''; isit=0
       do mm=1 to 6
          resu=sre_wild_match(ans,a.mm,oldresu)
          if resu=-1 then do
             isit=mm
             leave
          end
          if resu=0 then iterate
          isit=mm
          oldresu=resu
       end
       if isit=0 then
           say " no match "
        else 
          say " match= "a.isit
    
    

    SPECIAL FEATURE

    if haystack ends with a |, then no "slash" is allowed in the final wildcarded portion of the needle. That is, the portion of the needle "covered" by the final (or only, if there is just one *) in the haystack can NOT contain a / or a \. If it does, it's a NO MATCH

    For example, using a needle of: animal/cats/food.1
    The follwing haystacks yield:

             animal/*candy  --  no match
             anim*/*.1      --  match
             animal/*.1|    --  no match (* covers cats/food, which contains a /)
             anim*/food*|   --  match (final * covers ".1")
             */cats*|       --  no match (final * covers "/food.1")
    


    Updated 4 Sept. 2002