1 March 2001 SRE-http ver 1.3h Documentation: SRE-http's procedure library. SRE-http version 1.3 uses uses OS/2 "macrospace" to store many of its procedures. In addition, as a multi-threaded program, it uses the environment, queues, and semaphores to transfer information between threads. This document discusses both these aspects of SRE-http. In the first section, we discuss procedures that competent REXX programmers may find useful when writing addons for SRE-http. These procedures are stored in a "dynamic macrospace library file" called SREFPRC.RXL. When SRE-http is first run (that is, when GoServe is started, and the first request arrives), SRE-http will load this library into macrospace. The second section discusses SRE-http use of the environment, threads and semaphores for inter-thread communication. Note that several of these procedures may not be needed on your site. If so, you can save a little bit of space by "removing them from macrospace". For details, see the discussion of the REMOVE_PROCS variable in INITFILT.DOC. Please note that SRE-http uses REXXLIB for various purposes. REXXLIB is found at http://www.quercus-sys.com/rexxlib.htm. Our licence with Quercus allows users of SRE-http to freely use REXXLIB (you do not need to register it) as part of SRE-http. However, if you use REXXLIB for your own programs, you are supposed to pay for it (the license is only for use with programs we distribute). If you write "addons" for SRE-http that use REXXLIB, I'm not sure where that falls; but to be safe, I assume that you are supposed to register (the original cost was $25.00, though as of March 2001 it may be available for free). ------- ---------- --------- ------------ ------- SECTION 1: Using SRE-http's macrospace library. ------- ---------- --------- ------------ The following describes many of the procedures contained in the SRE-http macrospace library. If you are a serious REXX programmer, you may want to look at the source code (contained in various .SRF files) for further descriptions. Note that there are some procedures placed into macrospace by SRE-http that are not intended for general use; these are not described in this document. Some preliminary notes: 1) What is macrospace? Macrospace can be thought of as a system-wide dynamic link library. That is, procedures stored in macrospace are available to all REXX programs, not just SRE-http. Thus, if some other program "clears" macrospace, SRE-http may fail -- and vice versa! 2) Where's the source code? The source code for these procedures consists of a number of files with the extension .SRF; all stored in the SRE-http "library" directory (perhaps \GOSERVE\LIB). 3) What do we need to work with macrospace procedures? Nothing -- just call them the way you call any external OS/2 procedure. Note that SRE-http uses procedures in REXXLIB.DLL to "load" SREFPRC.RXL into macrospace. For simple manipulations of macrospace, you can use MSPACE.CMD (look for it in the library directory). 4) A caution on using these procedures: There are four general cases where one might use these procedues: 1) In an SRE-http addon (or a pre-filter, or mid-filter, procedure) 2) In a CGI-BIN script 3) In a post-filter procedure 4) In a stand-alone program (that is NOT running in the same process as SRE-http) Several of these procedures use GoServe to provide information, or use "request specific" information. These procedures will not work if called from one of the "higher numbered" cases. For example, several of these procedures use the GoServe EXTRACT function, typically to determine the current serverport. Extract will NOT work in a CGI-BIN script, or in a stand alone program. Where appropriate, the "cases" where the procedure can/cannot be used are noted in the Restrictions: portion of the following descriptions. 5) Another Caution In some cases, inappropriate use of these procedures can CRASH GOSERVE -- so do pay attention to the "restrictions"! 6) On the use of "dynamic macrospace procedures". As of version 1.2N, SRE-http uses "dynamic macrospace". Dynamic macrospace means that many of the procedures are not loaded until they are needed; which helps save space, and facilitates minor upgrades. There is one "gotcha" -- if you call one of these procedures from an external program (that's not in the GoServe process), it is possible that you will get a "could not find SRE_LIBDIR error". If this occurs, you just need to SET SRE_LIBDIR=goserve_lib_directory (say, SET SRE_LIBDIR=D:\GOSERVE\LIB). Make sure you do this SET from the same OS/2 session you are runnning this external procedure from,or put it in your config.sys file. ------- ---------- --------- ------------ Description of general purpose macrospace procedures ------- ---------- --------- ------------ Calling Syntax: File/url-resolution related procedures: status =SREF_GOS(acmd,varname,dorange,hdrs) open_time=SREF_OPEN_READ(afile ,seconds_to_try_for , howopen ) afile_string=SREF_GRAB_FILE(afile,seconds_to_try_for) newfiles=SREF_CONJUREF(basedir,basenames,extlist,minfree,mintime) newct=SREF_LOOKUP_COUNT(ctfile, needle, augment , substring , noadd) filename=SREF_DO_VIRTUAL(defdir,aurl,envstring,docheck,trans,homedir,hnick) mimetype=SREF_MEDIATYPE(filename,port) newurl=SREF_FIX_URL(local_url,servername,serverport) String related procedures: newstring=SREF_REPLACESTRG(haystack,needle,replacement, type , exactmatch) newstring=SREF_WILDCARD(original, needle replacement,doexact) matchinfo=SREF_WILD_MATCH(needle,haystack,old_matchinfo,suppress_noslash) ablock=SREF_EXTRACT_BLOCK(haystack ,alabel ,delim1, delim2, delim3) newval=SREF_INSERT_BLOCK(haystack,alabel,add_string,after,delim1,delim2) astring=SREF_PACK64(packed_64_string) stg_packd_64=SREF_MKPACK64(astring) md5_hash=SREF_MD5(astring,isfile) astring=SREF_UNCHUNK(chunked_string,trailers) stg_chunked=SREF_CHUNK(astring,trailers) astring=SREF_UNGZIP(gziped_string) stg_gzipped=SREF_GZIP(astring) img_elems=SREF_DIGITS(astring,digname,ndigits,frame,nobr,options) score=SREF_COMPWORD(needle,haystack) Variable/time/version lookup procedures: value=SREF_VALUE(varname,newval,env,optinfo) value=SREF_QUEUE(queuename,action,aval,port) aval=SREF_CGIVARS(cgi_bin_variable) timestr=sref_gmt(offset,basetime,outtype,gmtoffset) juldate=SREF_JULDATE(mode, time_string) filter_name=SREF_VERSION(port) errmess=SREF_ERROR(amessage,do_pmprintf) Internet info & retrieval procedures aresult=SREF_HOST(ipaddress) aval=SREF_BROWSER_INFO(field,browser,envstring) stuff=SREF_GET_URL(url,maxchar,verbose,headers) stuff=SREF_HOST_INFO(myaddr0,nhosts,envstring) cookie_value=SREF_GET_COOKIE(cookie_name,nth) res=sref_dynamic_pwd(appname,newlocation,privset2,duration,respfile,clientaddr) Daemon related procedures status=SREF_DMN_LAUNCH(daemon_name,file_name,optional_arg) status=SREF_DMN_EXIST(daemon_name) value=SREF_DMN_ASK(daemon_name,an_argument,max_wait) request_info=SREF_DMN_WAIT(daemon_name,max_wait) an_argument=SREF_DMN_VALUE(request_info) status=SREF_DMN_REPLY(request_info,reply_stuff) status=SREF_DMN_KILL(daemon_name) Miscellaneous status=SREF_MAILIT(address_list,message,smtp_gateway,sender_address) rcode=SREF_MULTI_SEND(message,mime_type,howsend,file_flag,verbose) foo=SREF_EXPIRE_RESPONSE(aoffset,alength,atype,noauto) foo=PMPRINTF_SREF(astring,nofile,port) results=SREF_FIND_INDEX(target,qname,varname,nth,loc_only,timeout) Short descriptions: SREF_GOS: Send information to client in a http/1.1 compatible way. SREF_OPEN_READ: Open a file, with waiting if the file is currently locked SREF_GRAB_FILE: Open file (with waiting), and then read it in to a string variable SREF_CONJUREF: Cleanup temporary directory, and then derive new filenames SREF_SEARCH_FIXED: Binary (or wildcard) search of fixed-length record file SREF_LOOKUP_COUNT: Lookup and increment an SRE counter file SREF_DO_VIRTUAL: Map a URL to a virtual directory SREF_MEDIATYPE: Determine mime type of a file SREF_FIX_URL: Create fully qualified URL from local URL SREF_REPLACESTRG: Replace occurences of needle, in haystack, with replacement SREF_WILDCARD: Deterimine if needle is a "wildcard" match of haystack SREF_EXTRACT_BLOCK: Extract a delimited block of text from a string SREF_INSERT_BLOCK: Insert block of text between delimiters SREF_PACK64: Convert a "pack64" format string to original characters SREF_MKPACK64: Convert a string to its "pack64" equivalent SREF_MD5: Make an MD5 "digest" of a string, or of a file SREF_UNCHUNK: Unchunk a "chunked" string SREF_CHUNK: Create a chunked string SREF_UNGZIP: Unzip a "gzip" compressed string SREF_GZIP: Create a "gzip" compressed string SREF_DIGITS: Returns a list of IMG elements that point to digit .GIFs SREF_COMPWORD: Matches a "needle" to a "haystack" -- return a 1-100 score. SREF_VALUE: Value of a variable from an OS/2 or SRE-http "environment" SREF_QUEUE: Read,write, and manipulate an SRE-http "queue" SREF_CGIVARS: Get the value of one of the CGI-BIN environment variables SREF_GMT: Compute a new GMT time, given an offset in fractional days SREF_JULDATE: Return absolute fractional date (since 0/0/1) SREF_VERSION: Return version of SRE-http SREF_ERRROR: Read/record an error message SREF_HOST: Return IP address given name (or vice versa) SREF_BROWSER_INFO: Get spec-info on a browser SREF_GET_URL: Go to a web server and GET a URL (the complete contents) SREF_HOST_INFO: Return the "host nickname", given a servername SREF_GET_COOKIE: Get value of a cookie SREF_DYNAMIC_PWD: Prompt the client for a "dynamic password" SREF_DMN_LAUNCH: Launch a daemon SREF_DMN_EXIST: Check if daemon's queue and semaphore are open SREF_DMN_ASK: Query the daemon for some information, wait for reply SREF_DMN_WAIT: Daemon uses this to listen for queries SREF_DMN_VALUE: Used by daemon to parse queries SREF_DMN_REPLY: Used by daemon (to reply to SREF_DMN_ASK) SREF_DMN_KILL: Kill a daemon's queue and semaphore SREF_MULTI_SEND: Send a sequence of documents SREF_MAILIT: Send mail via an SMTP server SREF_EXPIRE_RESPONSE: Modify the automatically generated expiry response header PMPRINTF_SREF: A front-end (with error checking)for PMPRINTF SREF_FIND_INDEX: Find a match in an SRE-Data file (requires SRE-Data addon) --------------------------------------------------------- Longer Descriptions (alphabetically sorted) ========================================================= ------- ---------- --------- ------------ PMPRINTF_SREF: A pre-process for the REXXLIB PMPRINTF routine. PMPRINTF_SREF is used throughout SRE-http as a means of reporting run-time status information. PMPRINTF_SREF typically calls the PMPRINTF procedure, which will then display results in a PMPRINTF window. PMPRINTF_SREF will check for a few overflow conditions, thereby avoiding sys3175 errors. In addition, PMPRINTF_SREF checks the SREF_PMPRINTF_LINE_LENGTH and SREF_PMPRINTF_LOG_FILE environment variables. These variables, set in SREFMON.CMD, control the maximum line length to be displayed (longer lines will wrap), and whether or not to log results to an SRE-http audit file Usage: CALL PMPRINTF_SREF(astring,nofile,port) where astring : the string to write nofile : optional. If 1, then suppress writing to the PMPRINTF_LOG_FILE. port: optional, the port of the server Restrictions: If called from a non-addon, you MUST include the port. ------- ---------- --------- ------------ SREF_BROWSER_INFO Return information about a browser. Usage: aval=sref_browser_info(field,browser,envstring) where field: the field to get information on: browser: optional: a "user-agent" identifying string. If this is not included, then the user-agent request header is used. envstring: only needed if called from non-addon (see restrictions) Output: The result The following fields are supported, with possible values noted. Note that if no information is available for an item. Or, a number < 0 is returned to signify an error: -1 = BROWSERS.IDX file unreadabld -2 = Can not find entry for this user-agent -3 = No value for this field, for this user-agent -4 = BROWSERS.IDX file not found user_agent = User-agent of browser browser = Vendor of the Browser cookies =Cookie capable? YES or NO. security = Type of security. NO, SHTTP, or SSL. tables = Understands tables (YES NO) date = The date this table entry was entered or most recently modified. YY/MM/DD redirectlimit = Maximum length of redirection string. Integer between 255 and 8000 maxlinklen = Maximum characters in url Integer between 255 and 8000 Citation: This procedure uses browser.idx, which is based on information from: http://website-1.openmarket.com:80/browsertest/prob/bt-maker.cgi?DataFile Hint: Since browsers are coming and going, you may want to check the SRE-http home page for new versions of BROWSERS.IDX. Or, you can generate a new version of BROWSERS.IDX with BROWSERS.CMD (run it from an OS/2 command prompt). BROWSERS.CMD can also be called as an SRE-http addon. It will read BROWSERS.IDX and display information about your browser's capabilities. Examples: tableok=sref_browser_info('TABLES') docook=sref_browser_info('COOKIES') security1=sref_browser_info('security','IBM WebExplorer DLL /v1.03') Restrictions: if called from a non-addon, you must supply an "environment string". This will have the form SREF_nn_, where nn is the current port (i.e.; nn=80). ------- ---------- --------- ------------ SREF_CGIVARS(Varname) Usage: aval=sref_cgivars(cgi_bin_variable) Returns: value of the CGI_BIN variable (if available) Note that:SCRIPT_NAME, PATH_INFO, PATH_TRANSLATED, and REMOTE_IDENT, PATH_INFO, PATH_TRANSLATED, and QUERY_STRING are not available. When one of these variables is requested, a ' ' is returned Note that this will NOT look in environment, but will determine the values each time. In other words, this not designed for use in cgi-bin scripts (you should use x=value(varname,,'os2environment) instead); it is designed for use in INTERPRET includes and in directly called REXX server side programs). Example: aval=sref_cgivars('server_software') Restrictions: should ONLY be called from an SRE-http addon. ------- ---------- --------- ------------ SREF_CHUNK: Chunk a string Usage: chunked_string=sref_chunk(astring,final,trailers) Create a "chunked" string; which is suitable for http/1.1 transfer. FINAL should be 1 if this is the last of a sequence of chunked strings (or if this is the "first of one"). *** Failure to include a "final" chunked sequence is an error! *** The trailers argument is optional. When present (at it should only be included when final=1) the value of trailer (typically crlf'ed delimited set of trailers) is added to the end of the chunked message. Restrictions: none ------- ---------- --------- ------------ SREF_COMPWORD: Compare two words and return a score Usage: score=sref_compword(needle,haystack) where: needle : the word to compare haystack : the word to compare against SREF_COMPWORD will compare the needle against the haystack and return a score that indicates how closely they match. A score of 100 means "perfect match", while a score of 0 means "no match". SREF_COMPWORD uses a simple pattern matching algorithim (based on looking for many possible substrings of the needle in the haystack). The greater the number of substrings, and the closer they are in letter position, the better the match. Note that the definition of which word is the needle and which is the haystack is somewhat arbitrary. However, it can make a difference in the score! Examples: ascore=sref_compword("FORIM1","FORMULA") ascore=sref_compword("FORIM1","THEMR1") ascore=sref_compword("FORIM1","EXACT1") would yield scores of 0.170, 0.034, and 0.016 (respectively) In contrase: ascore=sref_compword("FORMULA","FORIM1") ascore=sref_compword("THEMR1","FORIM1") ascore=sref_compword("EXACT1","FORIM1") would yield scores of 0.124, 0.037, and 0.016 (respectively) Restrictions: none ------- ---------- --------- ------------ SREF_CONJUREF : Create/delete temporary files Usage: newfiles=sref_conjuref(basedir,basenames,extlist,minfree,mintime) basedir: directory to clean up (if > 10 files, remove all files > mintime hours old) basenames: list of (up to 4-char) file-stems to be used (a random element will be added) extlist: list of up to 10 extension to be added to this file-stems So, if base= ZDOG,ZMOM and EXTLIST is FOO,CAT,001 then this will create ZDOGxxxx.FOO, ZMOMxxxx.CAT and ZMOMxxxx.001, where xxxx is some 4 digit random # (guaranteed to cause unique file names to be selected) (note replication to generate as many names as longest list) minfree: Try to get this much space free by deleting files from basedir (in kb) mintime: But don't delete anything less than this hours old Return: If newfiles=0, then could not create (say, minfree was violated) Else, comma delimited list of file names that can be used as temporary files. CAUTION: Be careful what you choose as your basedir (you could automatically delete important stuff if your basedir is not strictly a "temporary files" directory). Restrictions: none ------- ---------- --------- ------------ SREF_DMN_LAUNCH, SREF_DMN_EXIST, SREF_DMN_ASK, SREF_DMN_WAIT, SREF_DMN_VALUE, SREF_DMN_REPLY, SREF_DMN_KILL: A set of procedures to use with daemons. The several SREF_DMN_ procedures are used to launch, communicate with, and kill deamons. Daemons are semi-permanent threads running under the GoServe process. Among other advantages, they offer a convenient means of storing data for quick retrieval, provide system monitoring capabilities, and allow one to perform non-time sensitive actions efficiently. Section II of this document discusses daemons in greater detail. For a complete description of how to use these SREF_DMN_ procedures, please see DAEMONS.DOC. ------- ---------- --------- ------------ SREF_DIGITS Usage: txtstring=SREF_DIGITS(amess,digit_name,nd,useframe,nobr,opts,imgdir) where: txtstring : a text string containing a sequence of and around the IMG elements (that comprise the message) opts : a string to be included in the IMG elements. For example: ' ALIGN=CENTER VALIGN=TOP' ' VALIGN=MIDDLE WIDTH=12 HEIGHT=12 ' In other words, opts can be a list of any IMG element modifers. Note that this "opts" list is included in all IMG elements, including "frame" elements. imgsel : the "counter_image_dir" selector. If not specified, a value of "DIGITS" is assumed. imgdir : Absolute path pointed to by the imgsel. If not specified, the DIGITS subdirectory of the GoServe data directory is used. For details on how to use SREF_DIGITS, see COUNTER.DOC ------- ---------- --------- ------------ SREF_DO_VIRTUAL: Convert a url into an fully qualified file name. Usage: filename=sref_do_virtual(defdir,aurl,envstring,docheck,trans,homedir,hnick) where: defdir: Default drive&directory to use. If not supplied, the default data directory is used (see restrictions below) aurl : A url (of the form /A1/A1/FILE.EXT) to convert to an fully qualified file name. envstring: An "environment variable prefix". If not supplied, one will be built (based on the current http port, as supplied by GoServe) -- but see restrictions below. docheck: If 1, then check to see if the file exists. If it doesn't, return 0. trans: A unique transaction number. If not supplied, the current transaction number is used (as supplied by GoServe). homedir: The "home directory" replacement string for the ~ character (may be host specific) If no homedir argument, the home_dir environment variable is used. hnick : Host nickname -- used to identify the "host". It is used to identify "host sensitive" virtual directory entries. If docheck=0, or if docheck=1 and a file with the constructed name exists. returns a fully pathed file name based on the url and either defdir or a match between aurl and the virtual file list. If docheck=1 and this match does not exist, returns a 0. Examples: * newfile=sref_do_virtual(,'/herfiles/wedding1.jpg) If "herfiles" does not match a virtual directory, then newfile=ddir/herfiles/wedding1.jpg * giants=sref_do_virtual('d:\teams','/stars/willymays.html') If no virtual directory match to "stars", then giants=d:\teams\stars\willymays.html filename=sref_do_virtual(defdir,aurl,envstring,docheck,trans,homedir,hnick) * mymad=sref_do_virtual('d:\journals','fun/mad.doc',,1,,,'SITE2A') First useentries for the SITE2A host, and then "generic entries". If mad.doc does not exist, return a 0. * realdir=sref_do_virtual(,'WWW2/') The virtual directory corresponding to "selectors" under WWW2/ Caution: the virtual file list may contain http://xxx.yyy.zzz/abc entries. These are understood by the main SRE-http routine, but NOT by this procedure. If such a match occurs, SREF_DO_VIRTUAL will return a 0. Caution2: as illustrated in the fourth example, if you wish to match a directory to a virtual directory (without matching any specific filename), you MUST end the "aurl" argument with a /. Restrictions: if not called from an addon, you MUST supply ENVSTRING (i.e.; if the server is running on port 80, then ENVSTRING='SREF_80_'). If called from a post-filter procedure or an stand alone program, you must supply (in addition to envstring) the defdir, the trans (you can use an arbitrary number), and the homedir. You do not need to supply the host_nickname (if not supplied, host-specific entries will not be used). ------ ---------- --------- ------------ SREF_DYNAMIC_PWD Usage: res=sref_dynamic_pwd(appname,newlocation,privset2,duration,respfile,clientaddr) where appname: recommended. the "application" calling this. Used to identify a "shared secret". If not specified, a value DYNPWD is used. Note that APPNAME is also used in responses. newlocation: recommended. The uri to invoke when client hits the submit button. Default value is "/" privset2 : REQUIRED. the space delimited list of "secret" privileges. It should contain an entry of the form APPNAME:shared_secret duration: optional. duration of a timestamp, in days (and fractions of day) (default value is 1 day) respfile: optional.the "response file" containing the md5 procedure. If not specified, DYNPWD.RSP, in the datadir(), is used. clientaddr: client's numeric ip address. Optional, if missing, will get if with a GOSERVE extract and resp='' if a valid password is found or resp='200 '||length(response) if no valid password is found, sref_dynamic_pwd asks the client to supply one -- this is the response code for this "response" To enable dynamic passwords, you must write an "sre-http" addon that calls the SREF_DYNAMIC_PWD procedure (SREF_DYNAMIC_PWD is loaded into macrospace when needed). For further details, please see DYNPWD.DOC. ------ ---------- --------- ------------ SREF_ERROR: Read/record a request specific error message. Usage: errmess=sref_error(amessage,do_pmprintf) where: amessage= Optional. If supplied, amessage will be recorded. do_pmprintf= Optional. If greater then or equal to 0, amessage will also be written to the pmprintf window (using pmprintf_sref) Return: The current error message for this request (possibly an empty string) Each request has a "error-message" variable associated with it, which is initialized to an empty string when the request arrives. SREF_ERROR can read from, or write to, this variable. When no arguments are given (i.e.; errmess=SREF_ERROR()), then the current value is returned; if there have been no errors or warnings (that is, no calls to SREF_ERROR by SRE-http) a null string is returned. When amessage is specified, the current value of the error-message variable is returned, and it is then set to be amessage. In addition, amessage will be written to the SRE-http error log (i.e.; D:\GOSERVE\DATA\ERROR.LOG). Lastly, if do_pmprintf is greater then or equal to 0, amessage will be written to the pmprintf window (pmprintf_sref is used). Restriction: can only be called from an addon. ------ ---------- --------- ------------ SREF_EXPIRE_RESPONSE: Build a response header that does not have an immediate expiration. *** USE OF SREF_EXPIRE_RESPONSE IS NO LONGER RECOMMENDED -- *** *** USE SREF_GOS instead! *** Usage: foo=sref_expire_response(aoffset,alength,atype,noauto,pragvalue) aoffset is fraction of day to add to current date/time. This will be converted to gmt (assuming gmt variables have been set, as described in goserve.doc). If aoffset<0, then an "expires" header will Not be written. Default is 0.04 alength is the size of the document being sent. Default is 0 atype is the mime type. Default is text/html noauto= Y or N: If Y, or if missing, then suppress auto - headers. pragvalue=value to use in a Pragma: header. If 0, suppress Pragma header. If not specified, a Pragma: no-cache header is added. Restriction: can ONLY be called from an addon. ------ ---------- --------- ------------ SREF_EXTRACT_BLOCK : Extract a "labeled block" from a string. Usage: ablock=sref_extract_block(haystack , alabel , delim1 , delim2 , delim3) Extract a block from haystack, defined by a Labeled block, where the label has the form delim1 label delim2 multi-line_string delim3 xxx Default values of delim1={, 2=} 3={ Note that labels must have NO embedded spaces. Example: if haystack= this is text to select and label=SELECT, delim1=', and delim3='