5 January 2002

The SRE2002 Procedure Library

Description of The SRE2002 functions

The following lists the functions contain in the SRE2002 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_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 do a DNS lookup of an IP name
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 SRE2002 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_GMT compute a GMT time, incorporating an additional offset
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_PAUSE check & set PAUSE status of SRE2002
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 SRE2002
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 SRE2002 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 SRE2002.

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


The SRE2002 functions: full descriptions

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)

Syntax:
   astat=sre_append_file(filename,astring,ntries,addcrlf)
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)
  • 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 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 SRE2002. Note that "lists" and "queues" are also implemented in SRE2002 -- 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
    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 "id" of the caller. Or, set to 0 to mean "don't bother responding" (typically used with action of WRITE or ADD)
    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')

    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 you have multiple line values stored in the cache). 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_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 AUTHH argument sent to the filter.
    okay: okay=1 if the username and password match what the client provided, Otherwise, okay=0
    Often one would use
    SRE_EXTRACT_USERNAME to extract the "username" of a client, lookup (in an internal database) the password corresponding to this username, and use SRE_CHECK_USERNAME to see if this username/ password combination has been supplied by the client (in the auth_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_id)
    
    transaction_id is optional-- 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')
    
    SRE2002 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 active requests
  • list all 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 SRE2002 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 SRE2002 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.

    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 SRE2002 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 SRE2002 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_AUTOn
  • 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]   [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_AUTO, ETAG_AUTO1, and ETAG_AUTO2 -- SRE2002 will generate an etag for this file.
      • ETAG_AUTO: use the filename, size, and date
      • ETAG_AUTO1: use the filename, size, and date; and use the contents of the file
      • ETAG_AUTO2: use the contents of the file
      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 SRE2002 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 SRE2002 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 SRE2002.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

    • 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 SRE2002 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 SRE2002 will look for Range and If-Range request headers. If a Range: header is found, the SRE2002 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.
      • SRE2002'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. SRE2002 will include a Content-type response header that uses xxx.
      For example:
          type text/plain
      will cause SRE2002 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.
    • SRE2002 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 SRE2002. 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 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'
    • 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
    READ Read the request headers or the request body.

    Syntax:
        status=sre_command('READ HEAD|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
    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 */ rcode=sre_error_response(abs(nsize),,servername,params,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.
    • when an error occurs, a '' is returned. You can check to see if this is a real error by using
            SRE_EXTRACT('READBODY_STATUS')
      which will return one of the following words:
      none if the request is not POST or PUT
      pending request body has not yet been read
      completed 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.

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

    where
       response_line is your desired response line.

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

    Notes:

    • By default, SRE2002 sends a response line of: http/1.1 200 Ok
    • sre_command('RESPONSE ...) always returns a '1'
    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
    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 SRE2002.CFG (say, by running SRE2002 -m from an OS/2 prompt).
    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] [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_AUTO, ETAG_AUTO1, and ETAG_AUTO2 -- SRE2002 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 SRE2002 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 SRE2002 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:
      • SRE2002'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. SRE2002 will include a Content-type response header that uses xxx.
      For example:
          type text/plain
      will cause SRE2002 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
    • SRE2002 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 ACOMMAND (VAR uses amessage, but FILE does not)
    id_info: optional. info used to communicate with daemons.
    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 (SRE2002 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 SRE2002.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 SRE2002.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 SRE2002).

    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. Three types of server errors are supported: Optionally, SRE_ERROR_RESPONSE can write an error messages to the error log file.
    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
  • 408 or TIMEOUT: A time occured while reading request body
  • 410 or GONE: The resource has been permanently removed.
  • 411 or NOLENGTH: Length missing from request body (and not chunked)
  • 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
  • amessage Optional. If specified, this should be a full html response (including <html> ... </html>) 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 the automatically generated message. Also, if type=500, then log_message is written to the SRE2002 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 = a fully qualified file name
       1 = the contents of a variable
    filename_or_var The contents to compute an etag for.
       If in_type=0, this must be a filename.
       If in_type=1, this must be a variable.
    use_crc 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).

    an_etag will be the value of the etag.

    Notes:

    SRE_EXTRACT: returns settings of several SRE2002 variables.
    SRE_EXTRACT is used to obtain values of the SRE2002 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, use 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 will called with datadir as one of the entries in the hostinfo argument.
    DATADIR_DEFAULT The default value of datadir (as set in SRE2002.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 SRE2002 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 SRE2002.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 SRE2002 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 SRE2002.CFG).
    LIMITHEADER Maximum size of headers (including the request line), in kB
    LIMITTIMEINACTIVE Connection specific maximum time, in seconds, for which SRE2002 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 SRE2002 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 SRE2002 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 SRE2002 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 SRE2002 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 "SRE2002 ver 1.10"). This is the same as returned by the function calls SRE_SERVER() .
    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.
    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 AUTHH argument sent to the filter.

    SRE_EXTRACT_USERNAME will extract the "username" from either a BASIC of 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)
    

    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 SRE2002 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_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
    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
    C cookie -- similar to internet, ut 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 SRE2002 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('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
        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_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), SRE2002 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 SRE2002 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 two modes: read and set.

    You can also get the list of currently defined host using hinfo_list=sre_hostinfo('!LIST') -- a space delimited list of hosts are returned (you can then lookup each host using calls to SRE_HOSTINFO)

    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 "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 SRE2002 "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 SRE2002.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 SRE2002), 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 Type of move. Can be 301 302 303 200 or 307 or, equivalently, MOVE TEMP REDIRECT NOTIFY or REPOST.
    selector the selector (or fully qualified uri) to "move" to
    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=packur(pval)

    Example:

        pval='DOG+%26+CAT+%3D%3D+FUN%21+%0D%0A%24+%2F+TIME+%3D+%25+%3F+'
        uval=sre_packur(pval)
    
        and then uval will equal 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_PAUSE: Pause & unpause SRE2002
    Report on pause status of SRE2002; or pause, or unpause, When paused, SRE2002 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 SRE2002
            call sre_pause(1)   -- pause SRE2002
    
    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,wait_sec,stype)

    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)
  • otherwise : return status and contents (as described below)
  • 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 : Return contents only: do not return status info (the first character of stuff is the first character of the file).
    • stype=3 : Same as 2, but try again if file length is 0. This can be useful if the file may be in the process of being closed.
    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 times over wait_sec seconds
  • 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, 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

    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,tid,id_info)

    where:
    avar variable to lookup
    tid optional. The request identifier. If not specified, lookup info for the current request. Or, the tid can be the "id_info" (provided as the 5th argument to the filter) -- using this can speed up processing a bit.
    id_infod optional. The "id_info" (that is provided to the filter). This can speed processing a bit.

    Supported variables include:
    CLIENT return client ip address of this request
    OWN return "own id" of this request
    TRAN return transaction id of this request
    NTH the transaction number (which will be the same for maintained-connection requests)
    SOCK socket of this request
    HOST host name
    SEL selector
    START starttime (date & second)
    PARENTID the thread id of this requests "parent" (a transaction daemon)
    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_replacestring(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:

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

    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 search for. It should not contain any * (wildcard) characters
    template: compare needle to this string. This string usually contains one or more * (wildcard) characters
    replacement: substitute apporpriate wildcarded portions of needle 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 SRE2002.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 SRE2002 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 SRE2002 to shutdown, or see if a shutdown has been signalled (say, by another process).

    Syntax:

            call sre_shutdown(1)   -- tell SRE2002 to shutdown
            isdown=sre_shutdown()   - returns 1 if "shutdown" has been signalled, 
                                      0 otherwise
    
    On SHUTDOWN, SRE2002 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 SRE2002 temporary directory. Also by default, delete any "junk" temporary files that may already exist that have this name.

    Syntax:
        tempfile_name=sre_tempfile(pid,tid,tempdir,del_opt)
    where (all of the arguments are optional):
    pid: process id. If not specified, it will be looked up.
    Actually, this can be any string that is unique to this process.
    tid: thread id. If not specified, it will be looked up
    tempdir: directory where temporary file will reside. If not specified, use the SRE2002 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)
  • tempfile_name will have the form $0000181.034 (i.e.; process 181, thread 34) Alternate filenames have the form $x000181.034 (x is between A and Z)

    Example:

            tname=sre_tempfile()
            tname=sre_tempfile("PX"||dospid(),dostid())
    

    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, and REQ
    OS2 from the os/2 environment. In this case sre_value is just like the VALUE function
    SRESYS SRE2002 "system" variables. These are set when SRE2002 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.
  • SRE2002 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 SRE2002 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
  • 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')
            vv4=sre_value('ADDON_2_V10',,'GLOBALS')
    
    

    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 SRE2002 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 value will depend 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". bgcolor="%99ffee">

    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")