home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 35 Internet
/
35-Internet.zip
/
srev13h.zip
/
srefiltr.80
< prev
next >
Wrap
Text File
|
2002-01-13
|
101KB
|
2,950 lines
/* Sre-http main program, ver 1.3h
Copyright for the world, 1997,1998,1999,2000. Daniel Hellerstein.
Liability,etc. strictly denied (see the READ.ME file);
but feel free to use and modify this freeware code as you see fit
(no compensation required, but attribution is deemed proper and fitting).
See SREINIT0.CMD for some startup parameters */
/* ---------Get stuff sent from GOSERVE program -----------------*/
parse arg source, request , seloriginal,MOREINFO
'RESPONSE HTTP/1.1 200 Ok.' /*http/1.1 is now the default response */
/*** UNcomment this for debugging purposes
'read header var foob '
say " SOURCE: " source
say " request: " request
say foob
*******/
enctypes='SRE_A SRE_B SRE_BF SRE_BFC' /* currently supported encryption types */
/* set to 1 to enable some debug-tracing -- set to 0 to disable */
dodebug=0
aa=value("SREF_DEBUG",dodebug,'os2environment')
/*set exception handler */
signal on syntax name goterr;signal on error name goterr
signal on halt name goterr;call on failure name goterr2
request0=request ; selrec=seloriginal
parse var source myaddr port transaction who whoport . /* Often useful */
parse var request verb uri protocol . /* split up the request line */
reqnum=extract('request')
crlf='0d0a'x
if dodebug=1 then do
aa=''
if moreinfo='' then aa=left(seloriginal,25)
say "!DEB:MA1 "||left(transaction'-'reqnum,10)' 'left(time('l'),11)' 'aa
end
verb=translate(verb)
uri=strip(uri)
/* initialize? */
call init_sre
key_preface=value("SREF_KEY_PREFACE",,'os2environment')
never_publicurls=value("SREF_NEVER_PUBLICURLS",,'os2environment')
proxy_cache=value('SREF_PROXY_CACHE',,'os2environment')
parse var proxy_cache proxy_cache '_' .
proxy_cache=strip(proxy_cache)
user_logon_Proc=translate(strip(value('SREF_USER_LOGON_PROC',,'os2environment')))
wild_sels_ok=value('SREF_WILD_SELS_OK',,'os2environment')
enable_encryption=value("SREF_ENABLE_ENCRYPTION",,'OS2ENVIRONMENT')
default_encryption=value("SREF_DEFAULT_ENCRYPTION",,'OS2ENVIRONMENT')
/* Check for basic grooviness */
if left(protocol,4)\='HTTP' & protocol\='' then do
response_status=sref_response('badreq', 'specified a protocol that was not HTTP',servername)
clientname0=who
signal do_post_filter
end
if request=" " then return 'NODATA NoWait NoResponse' /* netscape sometimes does this */
if abbrev(upper(request),'GETIP')=1 then return 'NoDATA NoWait'
/* special head request -- used by monitoring/rebalancing addons */
main_server=value('SREF_MAIN_SERVER',,'os2environment')
if main_server='' then main_server=myaddr
if transaction>1 then do
if upper(verb)='HEAD' & who=main_server & abbrev(upper(seloriginal),'!PING')=1 then do
aa=sref_do_ping(seloriginal) /* might exit */
end
end
/* Get host, datadir, and servername info */
amess=''
if moreinfo<>'' then do
parse var moreinfo servername','host_nickname',' ddir .
if abbrev(upper(uri),'HTTP://')>0 then do
parse var uri . '//' . '/' uri
if uri='' then uri='/'
parse var seloriginal . '//' . '/' seloriginal
end
end
else do
amess=get_host_info(protocol)
end
servername=strip(servername); host_nickname=strip(host_nickname);ddir=strip(ddir)
if amess=-1 then do
foo=sref_response('400 Bad Request','HOST not provided by http/1.1 client',myaddr)
response_status=sref_response('badreq', 'http 1.1 client did not include host information',servername)
clientname0=who
signal do_post_filter
end
/* check if load balancing needed */
backupserverlist=value('sref_backupserverlist',,'os2environment')
loadthreshold=value('sref_loadthreshold',,'os2environment')
if abbrev(upper(seloriginal),'!NOBALANCE')<>1 & abbrev(upper(seloriginal),'!FORCE')<>1 ,
& loadthreshold>0 then do
verbose=get_value('VERBOSE',0)
servdir=value(enmadd||'SERVDIR',,os2e)
foo=sref_backupserver(backupserverlist,loadthreshold,host_nickname,seloriginal,servdir,verbose)
if foo<>"" then do
response_status='302 0'
clientname0=who
signal do_post_filter
end
end /* load balancing not allowed */
/* Take care of special ! directives, and set several parameters, such as:
force_auth force_norecord specific_mime del_send quick_run */
call modify_seloriginal
if enable_encryption=0 then is_encrypt=0
range_at_end=value('SREF_RANGE_AT_END',,'os2environment')
if range_stuff='' & range_at_end=1 then do /* check for ;range ? */
iss=pos(';',seloriginal) /* check for ;range info in selector? */
if iss>0 & pos('?',seloriginal)=0 then do /* if ssp, don't do it */
range_stuff=substr(seloriginal,iss+1)
seloriginal=left(seloriginal,iss-1) ; selrec=seloriginal
end
end
call tidy_up /* set a few more parameters */
IF RANGE_STUFF<>'' & VERBOSE>3 THEN
foo=pmprintf_sref('RANGE info= 'range_stuff,,port)
/* -- now process the request */
/* 1) call a pre-filter (it might EXIT back to GoServe)
The pre-filter should check for completion!
Note that pre-filter is ALWAYS called, even if cached transfer occurred
(assuming that you've set goserve's "call filter anyways" parameter */
if pre_filter="FIRST" then do
prefilter_result=do_prefiltr(' ')
parse var prefilter_result status ',' prefilter_result
a=done_it(status,"Pre-filter processed: "||prefilter_result)
if a=1 then do
signal do_post_filter
end
end
/* 2) MAKE SURE THE REQUEST IS STILL ACTIVE!!
(IF CACHING OCCURED, IT MIGHT NOT BE !! */
aa=done_it(0,'From cache: '||seloriginal)
/* already been completed (possibly from prefilter) -- look for "no record" flags */
/* Note: if already completed, then don't worry about sreproxy caching */
if aa=1 then DO
if force_norecord=1 then return ' ' /* a !norecord request */
/* is it a public url with NORECORD option */
aline=wait_queue('PUBURL',seloriginal)
parse var aline . aline .
if pos('NORECORD',aline)>0 then return ' '
/* check access file for nopostfilter */
aline=wait_queue('ACCESS',seloriginal,allow_access)
parse var aline istat ',' accprivs ',' accopts ',' .
accprivs=space(strip(upper(translate(accprivs,' ','09'x))),1)
accopts=space(strip(upper(translate(accopts,' ','09'x))),1)
if wordpos('NO_POSTFILTER',accopts)>0 then return ' '
/* postfilter not suppressed ... do it */
response_status='200 '||extract('bytessent')
signal do_post_filter
END
/* 2b) check for Expect: 100-Continue */
if protocol<>'HTTP/1.0' then do /* not needed for http/1.0 clients */
oo=upper(reqfield('Expect'))
if strip(oo)='100-CONTINUE' then do
a1='100-continue not supported'
foo=sref_gos('VAR type text/html NOCACHE RESPONSE 417%20Expectation%20Failed NAME A1 ',a1)
signal do_post_filter
end
end
if dodebug=1 then 'header add x-debug-1: 'seloriginal
/* 2c) get superceding realm info? */
realm.=''
no_srealm=value('SREF_NO_SUPERCEDING_REALM',,'os2environment')
if no_srealm<>1 then do
parse var no_srealm is1 is2 ; is2=strip(is2)
srealm=''
if is2<>0 then do
srealm=wait_queue('SREALM',seloriginal,,1)
end
if srealm<>'' then do
parse var srealm realm.!realm (crlf) realm.!rule (Crlf) realm.!access (CRLF) ,
realm.!alias (crlf) realm.!puburls (crlf) realm.!virtual
if dodebug=1 then 'header add x-sre_realm: 'realm.!realm
end
/*
say seloriginal
say host_nickname " SREALM: " realm.!realm
say " -- rul "realm.!rule
say " -- ac "realm.!access
say " -- al "realm.!alias
say " -- pub "realm.!puburls
say " -- vir "realm.!virtual
*/
end
/* 3) Is it one of the public_urlS ??. IF so, skip logons,
etc (but do aliases and ssi's). */
sel=seloriginal
if never_publicurls<>1 then do
foo=get_value('PUBURL_FILE')
if foo='' then do
aline=0 /* no file, hence no publicurls */
end
else do
if realm.!rule<>'' then do /* use realm match */
if realm.!puburls<>0 then /* is a pub url */
aline=realm.!rule' 'realm.!puburls
else
aline=0
end
else do
aline=wait_queue('PUBURL',seloriginal)
end
end
if aline<>0 then do /* matched a public url! */
do_htaccess=0 ; is_encrypt=0 ; is_public=1; CACHE_YES=2 /* proxy cache must revalidate */
privset=get_value('public_privs')||' PUBLIC_URL '
stuff=sref_public_urls(sel,aline,ddir,home_dir,verbose,specific_mime,host_nickname)
parse var stuff litmatch norecmatch amessage
litmatch=strip(litmatch)
if strip(norecmatch)=1 then no_postfilter=1
if litmatch=1 then do /* sref_public_urls responded to literal puburls */
pr=get_value('ACCEPT_RANGE')
foo=sref_gos(amessage ' MAXAGE 1 !RANGE 'range_stuff,,pr,,enmadd, ,
protocol,,,,host_nickname,no_postfilter)
signal do_post_filter
end
if value('SREF_ALWAYS_CHECK_PRIVS',,'os2environment')=1 then call add_privs_pub /* get privs? */
call fix_privset /* remove repeats, find secret privs */
signal do_alias /* do the verb (skip logons, access check, etc */
end
end /* neverpublicurl */
/* 4) Not a public_url; Do we check for logon rights, etc. */
/* 4a) check for unallowed ip */
username=' '
owners=get_value('OWNERS')
badips=get_Value('UNALLOWEDIPS')
mdo=0
if badips=1 then do
mdo=sref_badips(who,enmadd,host_nickname)
is_public=0
end
if mdo=1 then do /* he is a bad ips, but we let owner and inhouse override it */
IS_PUBLIC=0 /* CAN'T BE CACHED BY PROXY ! */
if wordpos(who,owners)=0 then do /* not an owner */
call goodips(who)
res1=result
if res1=0 then do /* not an inhouseips */
'NODATA NOWAIT NORESPONSE '
/* response_status=sref_response('unauth', 'You are not permitted access to this web server ',servername) */
signal do_post_filter
end
else do
if verbose>0 then foo=pmprintf_sref(' Note: 'who' is a badips and inhouseips -- ignoring badips! ',,port)
username=who
end
end
else do
if verbose>0 then foo=pmprintf_sref(' Note: 'who' is badips and an owner -- ignoring badips! ',,port)
username='OWNER'
end
end
/* 4b) Do a DNS check ? */
dns_check=get_value('dns_check')
if dns_check="YES" then do
IS_PUBLIC=0
if clientname0=0 then
clientname0=sref_clientname(who,mysem,myqueue,basesem,enmadd,transaction)
if clientname0=who then do
audit ' Denied access to ' who
response_status=sref_response('unauth', 'No client name found, access to this web server is denied. ',servername)
signal do_post_filter
end
end
/* 4c) Check user/pwd/privilege list */
call get_log_params
IF CHECKLOG<>'NO' THEN IS_PUBLIC=0 /* IF LOGON REQUIRED, then no public cache */
/* do logons, etc ... */
if wordpos(who,owners)>0 then do /* owners are treated with kid gloves */
privset="SUPERUSER INHOUSE "||inhouse_privs /* also give inhouse privs */
CALL get_user_privs 1,1 /* get user privs */
username="OWNER"
end
else do /* non owners get the third degree? */
if dologon=1 then do /* yup, book 'em */
logon_fail_file=get_value('LOGON_FAIL_FILE')
logon_limit=value('SREF_LOGON_LIMIT',,'os2environment')
userinfo=do_logon(who,inhouse_privs) /* if no match, exits (for new pwd or say sorry) */
if gotauser=0 then do
response_status=userinfo
signal do_post_filter
end
parse var Userinfo lstat username privset
username=strip(username)
/*very tough--only inhouse allowed (explicit or as a privilege)?*/
if checklog="INHOUSE" & wordpos('INHOUSE',privset)=0 & wordpos('SUPERUSER',privset)=0 then do
response_status=sref_response('unauth', 'Sorry, access currently limited to in-house users ',servername)
signal do_post_filter
end /* not inhouse */
/* If here, username/password found welcome ! */
if verbose>1 then foo=pmprintf_sref(host_nickname '// 'seloriginal' :request from: ' username '(privs: ' privset,,port)
end /* dologon =1 */
/* If here, then no logons required (dologon=0 */
else do
CALL get_user_privs 1 /* go get inhouse, user; but NOT ownname privileges */
end /* check if logon rwquired */
end /* not superuser */
/* 5) Logon permitted. Add more privileges? */
call add_privs_2 /* add privileges to non puburls */
/* 5a) extract secret privileges, and remove redundant privileges */
call fix_privset
/* 6) now check ACCESS file */
if realm.!rule<>' ' then do /* use realm info */
aline='1 , '||realm.!access
end
else do
aline=wait_queue('ACCESS',seloriginal,allow_access)
end
parse var aline istat ',' accprivs ',' accopts ',' urlrealm ',' afail_file ',' adv_opts ',' adv_opts_2
accopts=space(strip(upper(translate(accopts,' ','09'x))),1)
accprivs=space(strip(upper(translate(accprivs,' ','09'x))),1)
/* privileges required (non *, and allow_access disabled */
IF ACCPRIVS<>' ' & POS('*',ACCPRIVS)=0 & abbrev('YES',allow_access)=0 THEN do
IS_PUBLIC=0
end
afail_file=strip(afail_file)
if urlrealm="" then do
if value('SREF_REALM_1ST_PRIV',,'os2environment')=1 then urlrealm=word(accprivs,1)
end
/* Note: access is checked for all request (checked above for public_Urls)
istat=0 for all non-matched urls */
/* should we disallow */
ok1=0
if wordpos('SUPERUSER',privset)>0 then ok1=1
if ok1=0 then do
select
when allow_access="YES" | allow_access="YES_NOCHECK" then
ok1=1
when allow_access="INHOUSE" & isinhouse=1 then
ok1=1
otherwise
if istat<>0 then DO /* if istat=0, then sref_ask_auth below */
/* add own-resource privilege? */
addreso=get_value('ADD_RESOURCE_NAME')
if addreso=1 theN DO
PARSE UPPER VAR SELORIGINAL ACTION '?' .
accprivs=accprivs||' '||action
end
ok1=check_privs(privset,accprivs)
end
end
end
reqprivs=accprivs /* used by sreproxy, via srefgos */
if reqprivs='' then reqprivs='*'
/* if ACCESS to this url not permitted, let client try "another" user name,
OR send a response file */
if ok1=0 then do /* not okay -- ask authorization? */
access_fail_file=get_value('ACCESS_FAIL_FILE')
if access_fail_file=0 | access_fail_file=-1 | access_fail_file=' ' then do
afail_file=access_Fail_file /* -1 and 0 suppress access fail file */
end
else do
if access_fail_file<>1 then
if afail_file=' ' | afail_file=0 then afail_file=access_fail_file
end
if afail_File=1 | afail_file=' ' then afail_file=0 /* 1 in access_fail_file -- if no specific fail file, use auth */
select
when afail_file=0 then do /* just ask authoriaztion */
response_status=sref_ask_auth(the_realm,urlrealm,servername,isstale)
end
when afail_file=-1 then do /* terse denial */
response_status=sref_response('unauth','Access denied',servername) /* flat out denial */
end
otherwise do /* access fail file */
brealm=the_realm
if urlrealm<>' ' & urlrealm<>0 then brealm=urlrealm
awebmaster=get_value('WEBMASTER')
response_status=sref_fail(servername,seloriginal,afail_file,verbose,brealm,'access failure',awebmaster, ,
'No access privileges to this resource',1, force_auth,the_realm,urlrealm,myqueue,tempfile)
end
end
signal do_post_filter
end
/* if here, access privileges were satisfied */
/* 6a) lookup/set permissions for this url */
call lookup_permissions
/* 6b) get advanced options */
call get_adv_opts /* get advanced options */
/* check for encryption advanced option */
if enable_encryption<>0 then do
is_encrypt=sref_adv_opts_encrypt(is_encrypt,adv_opts,default_encryption)
end
/* 6c - if encryption required, check for appropriate privileges */
/* if is_encrypt on of the encrypts, then a
?ENCRYPT "secret permission" MUST be available for this user */
epwd=''
if wordpos(is_encrypt,enctypes)>0 then do
do mm=1 to words(privset_secret)
fwrd=translate(strip(word(privset_secret,mm)))
if abbrev(fwrd,'ENCRYPT:')=0 then iterate
parse var fwrd . ':' epwd ; epwd=strip(epwd)
is_encrypt=is_encrypt':'epwd
if enable_encryption>1 then
foo=sref_value('ENCRYPT',is_encrypt,'REQ',reqnum,,enmadd)
leave
end
if epwd='' then do /* no permission, ask for username */
response_status=sref_ask_auth(the_realm,urlrealm,servername)
SIGNAL DO_POST_FILTER
end
end
/* 7) call prefilter */
/* call a pre-filter (it might EXIT back to GoServe) */
if pre_filter="YES" then do /* if FIRST, then prefilter was called BEFORE logon */
prefilter_result=do_prefiltr(privsetboth)
parse var prefilter_result status ',' prefilter_result
a=done_it(status,"Pre-filter processed: "||prefilter_result)
if a=1 then do
signal do_post_filter
end
end
/* 8) do aliases */
/* 8a) is it for the DEFAULT "home page"
(relative to datadir, No virtual directory lookups! */
if sel=' ' then do
sel=sref_get_default(default,ddir,verbose,myqueue) /* always relative to datadir */
selrec='DEFAULT='||sel
got_def=1
end
else do
if substr(sel,1,1)='?' then do /* simple, or with options */
sel=sref_get_default(default,ddir,verbose,myqueue)||sel /* default MUST be an HTML document */
selrec='DEFAULT='||sel
got_def=1
end
end
/* check for redirection DEFAULT */
if got_def=1 & abbrev(upper(sel),'HTTP://')=1 then do
dog=isa_move(sel,servername,serverport)
if dog<>0 then do
signal do_post_filter
end
end
/* 8b) Now see if the ACTION is really an alias for some other action */
do_alias: nop /* jump here if public_url */
if check_alias<>0 then do /*see if 'action' is an alias for something else*/
if realm.!rule<>' ' then do /* use realm info */
if realm.!alias=0 then
aline=0
else
aline='1 'realm.!alias
end
else do
aline=wait_queue('ALIAS',sel)
end
parse var aline istat newsel
if istat>0 then do
sel=strip(newsel)
if verbose>1 then foo=pmprintf_sref(" Alias # resolves to: " sel,,port)
is_alias=1
end
/* 8c) redirection? or absolute file */
if dodebug=1 then 'header add x-debug-2: 'is_alias ', 'sel
if is_alias=1 then do
dog=isa_move(sel,servername,serverport)
if dog<>0 then do
signal do_post_filter
end
/* 8d) is this a "send non-data directory file" action (OBSOLETE, use of virtual directories recommended)*/
if abbrev(upper(sel),"!TRANSFER=")=1 then do
parse var sel action '?' awords
response_status=SREF_send_non_datadir(upper(action),,
tempfile,verbose,transaction,servername,host_nickname,,
specific_mime,advopt_mime)
signal do_post_filter
end
/* 8e) TCN? */
if abbrev(upper(sel),"!NEG")=1 then do
negstuff=sref_do_negotiate(seloriginal,verbose,enmadd,home_dir,servername, ,
host_nickname,ddir,home_dir,transaction,,
tempfile,sel,is_public,protocol,semqueue)
if negstuff=0 then do
response_status= not_found_response(seloriginal,' Variant list not found ',' ')
selrec=' '
signal do_post_filter
end
if negstuff=-1 then do /* could not resolve; response handled in sref_negotiate */
signal do_post_filter
end
/* otherwise, first line is the negotiated "sel", then mimetype,
remaining lines are new headers */
parse var negstuff sel '0d0a'x newdir '0d0a'x tadvopt_mime ,
'0d0a'x vlv '0d0a'x ,
varylist '0d0a'x alternates '0d0a'x reqheads
if tadvopt_mime<>'' then advopt_mime=tadvopt_mime
contentloc=sel
doingneg=1
realm.!rule='' /* can't use one daemon results */
adv_opts=adv_opts||'0d0a'x||strip(reqheads)
ddir=newdir
/* but-- check to see if this is a negotiable resource */
foo=wait_queue('ALIAS',sel)
parse upper var foo . aa .
if strip(aa)='!NEGOTIATE' then do /* 506 error */
response_status=sref_response('alsonegotiates', 'The selected variant of a negotiable resource is another negotiable resource',servername)
signal do_post_filter
end
end /* !negotiate */
end /* isalias=1 */
end /* checkalias */
/* 9) See if a "home_dir" flag (a ~) is present. If so, replace it */
parse var sel action '?' awords
foo1=pos('~',action)
if foo1>0 then do /* do ~ for home_dir replacement, with $ option */
action=sref_home_dir(action,home_dir)
action=strip(action,'l','/')
end
if pos('?',sel)>0 then
sel=action||'?'||awords
else
sel=action
/* The next stuff is for GET & HEAD requests (non cgi, non addon) only, so skip otherwise */
if (verb<>"GET" & verb<>'HEAD') | left(sel,1)="!" then signal do_verb
if pos("CGI-BIN/",upper(sel))>0 | pos('?',sel)>0 then signal do_verb
/* 10) Check sel to see if it's a /xx/yyy/ or /xx/yyy selector. */
/* (only valid for get/head, non-cgi requests */
sel=strip(sel)
selautoname=sel /* may need to reset sel (see GET & HEAD verb processing below) */
/* 10a: /xxx/yyy */
noexttype=upper(get_value('NOEXT_TYPE'))
if noexttype<>"NONE" & right(sel,1)<>'/' then do /* it doesn't end with a / */
if lastpos('.',sel) <= lastpos('/',sel) then auto_name_type=1 /* and has no extension */
end
/* 10b) /XXX/yyy/ */
if right(sel,1)='/' then auto_name_type=2
if auto_name_type>0 & pos('*',sel)>0 & wild_sels_okay>0 then auto_name_type=0
goautoname: /* hop here if no match, sel ends with / or noextension */
/* 10c) gin up a selector if /xxx/yyy/ or /xxx/yy
we may loop here several times, but eventually
the auto_names or noextype list will be exhausted */
if auto_name_type=2 then do /* xx/yy/ */
SEL=SELAUTONAME
parse var auto_name auto_name1 auto_name
sel=try_auto_name(sel,auto_name1)
if auto_name='' then auto_name_type=0 /* no more to check */
end
if auto_name_type=1 then do /* /xxx/yyy */
SEL=SELAUTONAME
parse var noexttype noexttype1 noexttype /* pluck off first word */
sel=sref_fix_url_ext(sel,noexttype1,verbose)
if sel=-1 then do /* A REDIRECT */
suse=selautoname
if pos('~',seloriginal)>0 then suse=seloriginal
foo=isa_move('!MOVED '||suse'/',servername,serverport)
signal do_post_filter
end
if noextype='' then auto_name_type=0 /* no more to check */
end
/* jump here to avoid some GET/HEAD (non cgi, non xx?ZZ) specific stuff */
do_verb: nop
/* 11) first: do some advanced options (EXEC and mimetype and MAXUSER*/
if adv_opts<>' ' then do
tdir=get_value('TEMPFILE_DIR',0)
gotit=sref_adv_opts_exec(adv_opts,source,request0,seloriginal,privsetboth,verbose, ,
servername,host_nickname,ddir,home_dir,tdir)
if gotit<>0 then do
response_status=gotit
signal do_post_filter
end
if doingneg<>1 then advopt_mime=sref_adv_opts_mimetype(adv_opts)
/* check for maxuser option */
gotit=sref_adv_opts_maxuser(adv_opts,seloriginal,serverport,verbose,servdir)
select
when gotit=0 then do
'RESPONSE HTTP/1.1 503 Service Unavailable.'
'string Server is busy, please try again in a few minutes '
signal do_post_filter
end
when abbrev(gotit,'\SEM32\')=1 then do /* release maxuser_sem when done */
maxuser_sem=gotit
end
when gotit='' then do /* no maxuser option */
nop
end
otherwise do /* gotit is a failure file */
awebmaster=get_value('WEBMASTER')
response_status=sref_maxfail(servername,seloriginal,gotit,verbose,awebmaster,'Max. Users exceeded',servdir)
signal do_post_filter
end /* othwerwise */
end /* select */
end /* if */
/* ---------- Process the method (PUT, DELETE, GET,POST, or HEAD) ----------- */
do_verb2: /* jump here on "directory specific not_found_url" */
/* parse ?xx stuff out */
parse var sel action '?' awords
/* .... Now carry out supported verbs (GET POST HEAD PuT DELETE ), or SPECIAL control */
/* -- and check for cgi_bin calls -- and check for imagemap calls*/
/* 12a)server side imagemap call ? */
if awords<>' ' & never_imagemaps<>1 then do /*possible mapimage call */
RRES=SREF_ISMAP_IMAGE(,AWORDS,ACTION,NCSA_ISMAP,CERN_ISMAP, ,
servername, serverport,tempfile,Ddir,max_pointdist,verbose)
IF ABBREV(RRES,'*!*')=1 THEN DO /* FIRST STEP, DO VIRTUAL FILE HERE */
mapfile=do_virtual_file(Ddir,SUBSTR(RRES,4),0,1,'!HTML')
MAX_POINTDIST=get_VALUE('MAX_POINTDIST')
RRES=SREF_ISMAP_IMAGE(MAPFILE,AWORDS,ACTION,NCSA_ISMAP,CERN_ISMAP, ,
servername, serverport,tempfile,Ddir,max_pointdist,verbose)
END
IF RRES<>"" THEN DO
PARSE VAR RRES RESPONSE_STATUS ',' POST_FILTER_MESSAGE
signal do_post_filter
END
END
/* 12b -- is it cgi ? */
cgi_bin_dir=STRIP(get_value('CGI_BIN_DIR',0))
ORIG_CBD=cgi_bin_dir
tsel=strip(upper(sel))
foobao=pos('CGI-BIN/',tsel)
if (foobao>0) & (cgi_bin_dir<>0) & (verb="GET" | verb="POST") then do
parse var tsel a1 "?" . /* double check */
if pos('CGI-BIN/',a1)>0 then do
call process_cgi /* process as cgi */
if result<0 then signal do_verb2 /* jump to selnotfound */
signal do_post_filter
end
end
/* 12c) special requests */
if left(sel,1)='!' then do
call do_a_special
signal do_post_filter
end
/* Process the VERB
Currently supported verbs:
HEAD: If auto_header, will also parse html file for header instructions
GET: Several variants: file transfer, file with ssi, ssp
POST: ssp
PUT: write a file (given permission exists)
DELETE: delete a file (given permission exists)
TRACE and OPTIONS
In all cases, the url is mapped to a particular file using the
virtual directory feature (or the data directory if no virtual
directory matches the requested url).
********************/
select
/* 13) Head Requests --- NO LONGER SUPPORTED SEPERATELY -- TREAT AS A GET, AND
LET GOSERVE SUPPRESS ENTITY BODY
when verb='HEAD' then do
call process_head
if result=1 then signal goautoname
end
****************** */
/* 14) GET requests (or a "selector not found" response */
when verb="GET" | verb="HEAD" | selnotfound<>"" then do
/* There are 4 classes of GET requests supported:
1) Simple file name eg; /ZIPFIP/ZIPFIP.HTM:
file is retrived, with possible ssi's
2) File name with OPTIONS, eg; /OVERVIEW.HTM?From+ZIPFIP+main+page
File is retrieved, with possible ssi's (some of which may use these OPTIONS
3) Form name with parameters, eg; /CALC/DOCALC?12-34%2B51
sref_getpost is called with appropriate argumen
4) SPECIAL: if selnotfound<>'', then we are here
because a special "not found url" has been invoked -- due to
the original selector failing to yield an existing file (or addon).
Note: ISINDEX type searchable-index requests are identical in
appearance to case 2. To avoid this problem, use the alias_file
mechanism (described above) to convert to a class 3
( "form name" SEL) that requests DOSEARCH
*/
parse var sel action '?' awords
action=TRANSLATE(strip(action))
/* 14a) Type of GET */
if pos('?',sel)=0 then do /* no argument list, must be case 1 */
jcase=1
end
else do /*arguments, class 2,3, or 4 */
attype=strip(mediatype(action))
if abbrev(upper(attype),'TEXT')=1 & pos('.CMD',upper(action))=0 then
jcase=2 /* class 2: html with "OPTIONS" */
else
jcase=3
end /* dtermine jcase */
/* 14b) File transfer (perhaps html with ?options */
if jcase < 3 then do /* generic file, or html with options */
if selnotfound="" then do /* selnotfound="" means it's inactive */
file=do_virtual_file(ddir,action,1,1,'!HTML') /* get local or remote virtual file */
if verbose>3 then foo=pmprintf_sref(" SRE-http: using file= "file)
if abbrev(file,'!DIR?')=1 then do
wow=isa_move('!TEMP '||file,servername,serverport)
signal do_post_filter
end
end
else do
file=selnotfound /* use previously determined "selector not found" file */
end
used_file=file
/* 14c) check htaccess rights */
if do_htaccess=1 & file<>0 & selnotfound="" then do
quick_run=0
tmp1=sref_htaccess(seloriginal,file_nocheck,htaccess_file,who,clientname0, ,
whoport,port,ddir,SERVERNAME,TEMPFILE,0)
if tmp1=-1 then do
response_status='401 - '
signal do_post_filter
end
parse var tmp1 qca ',' file0 ',' nopostf
file0=strip(file0) ;qca=strip(qca)
if file0<>0 & auto_name_type=2 & first_ht_auto=1 then auto_name=file0
first_ht_auto=0
if qca=0 then is_public=0 /* htaccess rights were needed, so no caching */
if strip(nopostf)=1 then no_postfilter=1
end /* do_htaccess if */
/* 14d) No match. Try again? */
if file=0 then DO /* no such file/dir */
if auto_name_type<>0 then signal goautoname /* try another defaults */
if selnotfound="" then do /* not found already tried? */
selnotfound=sref_not_found_local(seloriginal,not_found_url, ,
ddir,enmadd,transaction,home_dir,host_nickname)
end
else do
selnotfound=0 /* =0 means "don't try selnotfound again */
end
if selnotfound<>0 then do /* try using the "not found URL" selector */
sel=not_found_Url
if awords<>'' then sel=sel'?'awords
verb='GET'
signal do_verb2
end /* else, no selnotfound to use */
response_status= not_found_response(seloriginal,' <tt>'seloriginal'</tt> could not be found ',not_found_url)
selrec=' '
signal do_post_filter
end /* file=0 if */
/* 14e) File exists! determine mime type */
atype=mediatype(file)
/* 14f) Non html file (possibly byte range), or html (with possible ssis */
if atype<>'text/html' then
call process_non_html
else
call process_html
signal do_post_filter
end /* jcase < 3 */
/* 14g) jcase=3, an sre addon */
/* first, is ssp not allowed ? */
if no_processing=1 then do
response_status=sref_response('unauth',' Server side processing privileges not granted for: '||action,servername)
signal do_post_filter
end
/* 14H) ssp is allowed ...*/
usedfile=' '
addon_dir=get_value('ADDON_DIR')
if quick_run=1 then do /* expedited execution */
head_to_get=value('SREF_HEAD_TO_GET',,'os2environment')
rr=sref_quick_run(verb,ddir,tempfile,action,awords, ,
uri,who,servdir,workdir,privsetboth ,,
transaction,enmadd,verbose,servername,host_nickname,home_dir,head_to_get)
if rr=0 then quick_run=0
end
if quick_run=0 then do /* not a "quick run (or quick run failed */
averb='GET'
head_to_get=value('SREF_HEAD_TO_GET',,'os2environment')
if averb='HEAD' and head_to_get=1 then averb='GET'
if moreinfo<>'' & no_postfilter=1 then /* might be needed */
foo=sref_value('NO_POSTFILTER',1,'REQ',reqnum,,enmadd)
if dodebug=1 then
say '!DEB:MA2 '||left(transaction,5)' 'left(time('l'),11)' pre getpost'
if vlv>0 then do
oo=sref_value('_VLV',vlv,'REQ')
varylist=varylist||'0d0a'x||'Tcn: choice'
oo=sref_value('_VARYLIST',varylist,'REQ')
oo=sref_value('_ALTERNATES',alternates,'REQ')
oo=sref_value('_CONTENTLOC',contentloc,'REQ')
end
tdir=get_value('TEMPFILE_DIR',0)
got1=sref_getpost(tempfile,ACTION' , 'seloriginal,awords,averb' 'is_encrypt' 'RANGE_STUFF,uri,,
who,servdir,addon_dir,ddir','tdir, ,
privsetboth,enmadd,transaction' 'reqnum,verbose,serverport,home_dir, ,
servername,host_nickname,do_htaccess,htaccess_file,mysem||' 'myqueue)
end
pod1=word(got1,1)
/* 14I) addon not found? */
if pod1="!NOTFOUND" then do
if selnotfound="" then /* avoid inifinite lloooop */
selnotfound=sref_not_found_local(seloriginal,not_found_url, ,
addon_dir,enmadd,transaction,home_dir,host_nickname)
else
selnotfound=0
if selnotfound<>0 then do
verb="GET"
sel=not_found_url
signal do_verb2
end
else do /* no notfound document, use default */
parse var seloriginal goog '?' .
response_status= not_found_response(seloriginal,' addon not found: 'goog,' ')
selrec=' '
signal do_post_filter
end
end
/*14J) addon was found */
if datatype(pod1)="NUM" then do /* it's the response status */
response_status=subword(got1,1,2)
got1=subword(got1,3)
end
POD=LASTPOS(',',GOT1)
IF POD>0 THEN DO
USED_FILE=SUBSTR(GOT1,POD+1)
used_file=strip(used_file)
GOT1=DELSTR(GOT1,POD)
END
used_file=strip(used_file)
fpp=stream(tempfile,'c','close')
signal do_post_filter
end /* verb= get */
/* 15) POST */
when verb="POST" Then do
if no_processing=1 then do
response_status=sref_response('unauth',' Server side processing privileges not granted for: '||action,servername)
signal do_post_filter
end
drop awords
foo0=sref_GET_BODY(servername)
parse var foo0 foo ',' awords
ijump=1
SELECT
WHEN foo=3 | foo<0 then nop /* some kind of error */
WHEN FOO=1 THEN DO
response_status=sref_response(' 501 Unimplemented','501 unimplemented',servername,1)
END
WHEN FOO=2 THEN DO
response_status=sref_response('415 Unsupported Media Type','415 unsupported media type',servername,1)
END
OTHERWISE ijump=0
end
if ijump=1 then do
clientname0=who
signal do_post_filter
end
/* if here, got entity body */
action=TRANSLATE(strip(sel)) /* CAP AND Rid spaces */
addon_dir=get_value('ADDON_DIR')
if moreinfo<>'' & no_postfilter=1 then /* might be needed */
foo=sref_value('NO_POSTFILTER',1,'REQ',reqnum,,enmadd)
tdir=get_value('TEMPFILE_DIR',0)
got1=sref_getpost(tempfile,ACTION' , 'seloriginal,awords,verb' 'is_encrypt' 'RANGE_STUFF,,
uri,who,servdir,addon_dir,ddir','tdir, ,
privsetboth,enmadd,transaction' 'reqnum,verbose,serverport,home_dir, ,
servername,host_nickname,do_htaccess,htaccess_file,mysem||' 'myqueue)
pod1=word(got1,1)
if pod1="!NOTFOUND" then do
if selnotfound="" then /* avoid inifinite lloooop */
selnotfound=sref_not_found_local(seloriginal,not_found_url, ,
addon_dir,enmadd,transaction,home_dir,host_nickname)
else
selnotfound=0
if selnotfound<>0 then do
verb="GET"
sel=not_found_url
signal do_verb2
end
else do /* no notfound document, use default */
parse var seloriginal goog '?' .
response_status= not_found_response(seloriginal,' addon not found: 'goog,' ')
selrec=' '
signal do_post_filter
end
end
if datatype(pod1)="NUM" then do /* it's the response status */
response_status=subword(got1,1,2)
got1=subword(got1,3)
end
else do
arf=extract('bytessent')-base_sent
response_status='201 'arf
end
POD=LASTPOS(',',GOT1)
IF POD>0 THEN DO
USED_FILE=SUBSTR(GOT1,POD+1)
used_file=strip(used_file)
GOT1=DELSTR(GOT1,POD)
ss=dosdir(used_file,'s')
if ss<>' ' then RESPONSE_STATUS='200 '||DOSDIR(USED_FILE,'S')
END
used_file=strip(used_file)
signal do_post_filter
end
when verb="PUT" then do
put_No_overwrite=value('SREF_PUT_NO_OVERWRITE',,'os2environment')
parse var sel action '?' .
accept_range=get_value('ACCEPT_RANGE')
aa=sref_do_put('PUT',ddir,sel,enmadd,transaction,accopts, ,
tempfile,home_dir,servername,host_nickname,accept_range, ,
do_htaccess,htaccess_file,verbose,put_no_overwrite,protocol)
parse var aa aa ',' used_file; aa=strip(aa); used_file=strip(used_file)
signal do_post_filter
end
when verb="DELETE" then do
put_No_overwrite=value('SREF_PUT_NO_OVERWRITE',,'os2environment')
parse var sel action '?' .
accept_range=get_value('ACCEPT_RANGE')
aa=sref_do_put('DELETE',ddir,sel,enmadd,transaction,accopts, ,
tempfile,home_dir,servername,host_nickname,accept_range, ,
do_htaccess,htaccess_file,verbose,put_no_overwrite,protocol)
parse var aa aa ',' used_file; aa=strip(aa); used_file=strip(used_file)
signal do_post_filter
end
when verb='TRACE' then do
parse var request . amess .
foo=sref_gos('VAR type message/http NOCACHE ',amess)
end
when verb='OPTIONS' then do
parse var request . amess .
amess=strip(amess,,'/')
if amess='*' then do
adv_opts=adv_opts||crlf||'HEADER ADD Allow: HEAD GET POST PUT DELETE TRACE '
amess='Supported options on this server are: HEAD GET POST PUT DELETE TRACE '
foo=sref_gos('VAR type text/plain 'docache ' NAME ', ,
amess,,adv_opts,enmadd,protocol,,,,host_nickname,no_postfilter)
end
else do
foo=sref_response('notimpl','Options not implemented for this resource ',servername)
end
end
/* http extensions not currently supported -- perhaps later */
when abbrev(verb,'M-')=1 then do /* an extension */
'Response HTTP/1.1 510 Not Extended'
'HEADER ADD Expires: 'att
'String Server does not support extended http method: 'verb
end
otherwise DO
if VERBOSE>0 then ss= sref_error(" no such verb " verb,1)
RESPONSE_STATUS='501 0'
foo=sref_response('notimpl','method not implemented',servername)
signal do_post_filter
END
end /* select verb */
/* =========
jump here after completion code -- logging and other post-filter stuff done here.
==========
*/
do_post_filter:
/* signal to shutdown after completion of this request ? */
doshut=value('SRE_SHUTDOWN',,'os2environment')
if doshut=10 then do /* close down */
'close'
end
if dodebug=1 then do
say "!DEB:MA3 "||left(transaction,5)' 'left(time('l'),11)' postfilter'
end
if maxuser_sem<>'' then do /* release a maxuser semaphore */
foo=mutexsem_release(maxuser_sem)
if foo<>0 then do
if verbose>1 then
foo2=pmprintf_sref('SRE-http warning: mutexsem_release = 'foo ' ('maxuser_sem)
foo=mutexsem_close(maxuser_sem)
if foo<>0 then do
if verbose>1 then
foo2=pmprintf_sref('SRE-http warning: mutexsem_close (3) = 'foo ' ('maxuser_sem)
end
end
end
if no_postfilter=1 then exit ' ' /* no post filtering? then exit! */
post_filter=strip(get_value('POST_FILTER'))
postfilter_name=get_value('POSTFILTER_NAME')
/* save some extra stuff to the request specific variables (if a post_filter might
use it */
post_filter=1
if post_filter=1 then do
if pos(',',seloriginal||request)=0 then do
foo=sref_value('SOURCE SEL REQUEST IS_ENCRYPT',source','seloriginal','request','is_encrypt,'REQ',reqnum,,enmadd)
end
else do
foo=sref_value('SOURCE',source,'REQ',reqnum,,enmadd)
foo=sref_value('SEL',seloriginal,'REQ',reqnum,,enmadd)
foo=sref_value('REQUEST',request,'REQ',reqnum,,enmadd)
end
end
/* determin the response status */
IF RESPONSE_STATUS=' ' THEN do /* guess at response status */
arf=extract('bytessent')-base_sent
response_status='200 'arf
end
if rc=-7 then response_status=word(response_status,1) /* premature break -- use bytessent */
if words(response_status)<2 then do
ofo=extract('bytessent')-base_sent
response_status=word(response_status,1)||' '||ofo
end
if datatype(strip(word(response_status,2)))<>"NUM" then do
ofo=extract('bytessent')-base_sent
response_status=word(response_status,1)||' '||ofo
end
/*check for 400 status */
are1=strip(word(response_status,1))
if are1>399 then
record_option='NO'
else
record_option=strip(get_value('RECORD_OPTION'))
/* check for owner suppression */
call check_owner_suppress
if is_owner_suppress=1 then do
record_option='NO'
if verbose>2 then foo=pmprintf_sref(" Not recording OWNER or SUPERUSER request ",,port)
end
write_logs=strip(get_value('WRITE_LOGS'))
if (record_option="NO" & post_filter=0 & write_logs=0) | no_postfilter=1 then do /* nothing to do in post filter */
return ' '
end
meterdo=0
if pos('METER',translate(adv_opts))>0 then do
meterdo=reqfield('Meter')
if meterdo='' then do
meterdo='0/0'
end
else do
parse upper var meterdo . 'COUNT=' meterdo ',' .
if meterdo='' then meterdo='0/0'
end
end
if host_nickname<>'' then
record_all_file=get_value('RECORD_ALL_FILE')
else
record_all_file=get_value('RECORD_ALL_FILE',0)
post_filter=get_value('POST_FILTER')
selrec=sref_replacestrg(selrec,',','%2c','ALL')
request0=sref_replacestrg(request0,',','%2c','ALL')
browser=' ';authuser=' '
thereferer=reqfield('referer')
if write_logs=1 then do
if clientname0=0 then do
clientname0=sref_clientname(who,mysem,myqueue,basesem,enmadd,transaction)
end
browser=reqfield('user-agent')
authuser='-'
dec=sref_extract_upwd()
if dec<>'' then parse upper var dec authuser ':' . /* split to userid, if basic */
end
post_filter_message=response_status
a=rxqueue('s',enmadd||'POSTF')
queue record_option ',' record_all_file ',' post_filter ',' postfilter_name ',' serverport ',' ,
post_filter_message ',' source ',' request0 ',' got_def' 'selrec ',' ,
tempfile2 ',' servername ',' host_nickname ',' used_file ',' who ',' ,
enmadd ',' thereferer ',' reqnum ',' RESPONSE_STATUS ',' write_logs ',' ,
clientname0 ',' authuser ',' browser ',' verbose','privset','privset_secret', 'meterdo
aa=eventsem_post(basesem||'POSTF')
return ' ' /* note that postfilter and recorder don't need to tell the filter anything*/
/******************* END OF MAIN **************************/
/***********/
/* check on owner suppression */
check_owner_suppress:
chkowner=get_value('HIT_OWNER_SUPPRESS')
is_owner_suppress=0
if chkowner=1 then do
if owners=' ' then owners=get_value('Owners')
chkowner2=0
hit_superuser_suppress=value('SREF_HIT_SUPERUSER_SUPPRESS',,'os2environment')
if hit_superuser_suppress=1 then chkowner2=wordpos('SUPERUSER',privset)
if wordpos(who,owners)>0 | chkowner2>0 then do
is_owner_suppress=1
end
end
return is_owner_suppress
/* ------------------------------------- */
/* subroutine to strip & set !directives. Sets several globals;
so call as routine, not procedure */
modify_seloriginal:
force_auth=0
force_norecord=0
specific_mime=0
del_send=0
quick_run=0
is_encrypt=0
range_stuff=''
no_no_record=value('SREF_NO_NO_RECORD',,'os2environment')
empty_path_ok=value('SREF_EMPTY_PATH_OK',,'os2environment')
cgi_bin_pieces=value('SREF_CGI_BIN_PIECES',,'os2environment')
do forever
t1=seloriginal
if left(seloriginal,1)<>'!' then return 1
foo=sref_modify_seloriginal( ,
SELORIGINAL,DEFAULT_ENCRYPTIOn,IS_ENCRYPT,SELREC,FORCE_AUTH,NO_NO_RECORD,,
FORCE_NORECORD,SPECIFIC_MIME,DEL_SEND,RANGE_STUFF,QUICK_RUN,,
EMPTY_PATH_OK,CGI_BIN_PIECES,uri)
parse var foo SELORIGINAL '0d0a'x IS_ENCRYPT '0d0a'x SELREC '0d0a'x ,
FORCE_AUTH '0d0a'x ,
FORCE_NORECORD '0d0a'x SPECIFIC_MIME '0d0a'x DEL_SEND '0d0a'x ,
RANGE_STUFF '0d0a'x QUICK_RUN '0d0ax' ,
EMPTY_PATH_OK '0d0a'x CGI_BIN_PIECES
if t1=seloriginal then return 1 /* not modified, so done */
end
/* ------------------------------------------------ */
/* routine to get privileges (sets privset global). DOES not get public_privs*/
get_user_privs:
parse arg noadd,noinh
privset=privset||' '||check_user_info(who,1,noadd) /* auth, and possibly add-user, privs */
if noinh<>1 then do
call goodips(who) /* is this an inhouse connect - get some privs! */
isin=result
if isin<>0 then privset=PRIVSET||' '||inhouse_privs||' '||privset1
end
RETURN
/* ----------------------------------------------------------------------- */
/* Already completed (cache or prefilter. Record it and exit */
/* ----------------------------------------------------------------------- */
done_it: /* need globals, so call as routine */
parse arg status , amessage
issent=0
if datatype(status)<>'NUM' then status=0
if status=0 then issent=completed()
if (issent+status)=0 then return 0 /* otherwise exit */
if VERBOSE>1 then foo=pmprintf_sref(" Completed or redirected request: " amessage,,port)
parse var sel action '?' awords
return 1
/****************************/
/* remove repeats, extract secret privileges.
This will modify privest, and create privset_secret and privset2 */
fix_privset:
p1=''
secp1=''
privset=translate(translate(privset,' ',','||'0d0a0900'x))
do mm=1 to words(privset)
aw1=strip(word(privset,mm))
if abbrev(aw1,'?')=1 then do
aw1=substr(aw1,2)
if wordpos(aw1,secp1)=0 then secp1=secp1||aw1||' '
end
else do
if wordpos(aw1,p1)=0 then p1=p1||aw1||' '
end
end
privset=p1
privset_secret=secp1
privsetboth=privset' , 'privset_secret
return 1
/******************************************************************************/
/*-- DO_prefiltr: Call User Written pre-filter(s) --**/
/******************************************************************************/
do_prefiltr: procedure expose source request0 seloriginal prefilter_name verbose ,
transaction servername host_nickname reqnum REALM.
parse arg amessage
signal off syntax ; signal off error
signal on syntax name bad2a
signal on error name bad2a
foo3=' '
/* note that results from earilier pre-filters are sent do later ones */
do mm=1 to words(prefilter_name)
aname=word(prefilter_name,mm)
yow='foo3='||aname||'(source,request0,seloriginal,amessage,servername,foo3)'
interpret yow
if completed() then leave /* leave if pre-filter handled the request */
parse var foo3 status ',' prefilter_result
status=strip(status)
if status=1 then leave
end
signal off syntax
signal off error
signal on syntax name goterr
signal on error name goterr
return foo3
bad2a: /* jump here on syntax error */
signal off syntax
signal off error
cdrr=directory()
ss= sref_error(" Error in pre-filter routine "sigl' ' aname'(dir='cdrr,1)
signal on syntax name goterr
signal on error name goterr
return amessage
/* ----------------------------------------------------------------------- */
/* NOT_FOUND_RESPONSE: Return "not found" response, use macrospace routine */
/* ----------------------------------------------------------------------- */
not_found_response: procedure expose tempfile verbose transaction servername host_nickname seloriginal
parse arg request, message , message2 , reqnum REALM.
a=sref_not_found_response(request, message , message2,servername,seloriginal)
return a
/* ------------------------------------------------------ */
/* query and wait on helper threads */
/* ------------------------------------------------------*/
wait_queue: procedure expose os2e mysem myqueue enmadd basesem ,
mytid verbose transaction no_virtual servername host_nickname reqnum REALM.
parse arg athread,args,extra1,skipcheck
athread=strip(athread) ; args=strip(args)
/* check to see if no need to call queue */
if skipcheck<>1 then do
a1=check_queue_do(athread,enmadd,args,extra1)
parse var a1 istat','ires
if istat=1 then do
ires=strip(ires)
return ires
end
end
again1t:
goober=enmadd||athread
dothread=basesem||athread
a=rxqueue('s',goober)
woof=eventsem_query(dothread)
isboo=value('SREF_'athread'_BAD',,'os2environment')
if woof<0 | isboo=1 then do /* problem with this thread */
'RESPONSE HTTP/1.1 503 Server Unavailable' /*http/1.1 is now the default response */
string 'Server requires maintenance -- please retry in a few minutes '
foo=value('SREF_REDO',1,'os2environment')
foo=sref_error('Daemon not available: 'dothread,1)
exit
end
queue transaction ' ' host_nickname ',' myqueue ',' mysem ',' ARGS
a=eventsem_reset(mysem)
a=eventsem_post(dothread)
again2t:
a=eventsem_wait(mysem,90000) /* max wait of 90 seconds */
if a<>0 then do
ss=sref_error(mytid','athread' A Fatal Semaphore failure: 'a,1)
'response HTTP/1.1 503 Service Unavailable'
String 'Web server is temporarily busy '
exit ' '
end
a=rxqueue('s',myqueue)
parse pull aline
PARSE VAR ALINE idnum ',' aline
idnum=strip(translate(idnum,' ','000d0a'x));TRANSACTION=STRIP(TRANSACTION)
if idnum<>transaction then do /*wierd error: got someone else's message! */
say ' Read odd id from queue 'athread ':' transaction ',' idnum
if eventsem_query(mysem)=1 then aa=eventsem_reset(mysem)
signal again2t
end
aline=strip(aline)
return aline
/*-------------------------------------------------*/
/* - Check auto_name list (ONLY called if xxx/yyy/ type of url) ? */
/* ---------------------------------*/
try_auto_name: procedure expose verbose doing_autodir port REALM.
PARSE ARG SEL1,TRYME
FOO=SREF_TRY_AUTO_NAME(SEL1,TRYME,DOING_AUTODIR)
PARSE VAR FOO DOING_AUTODIR','SEL1
if VERBOSE>1 then foo=pmprintf_sref("Trying auto-named sel = " sel1,,port)
RETURN SEL1
/***************************************************************************/
/* ---------- ----------------------- ----------*/
/* LOGON checking. If no user match, requery client*/
/* -----------------------------------------------------------------------*/
do_logon: procedure expose inhouseips. enmadd os2e the_realm clientname0 isstale REALM.,
mysem myqueue basesem mytid verbose transaction no_virtual reqnum ,
servername host_nickname logon_limit logon_fail_file user_privs ,
seloriginal force_auth gotauser tempfile who user_logon_proc protocol
parse arg anip , inhouse_privs
gotauser=1 /* assume success */
/* see if an inhouseips. */
call goodips(anip)
if result=1 then do
if clientname0=0 then do
myname=sref_clientname(who,mysem,myqueue,basesem,enmadd,transaction)
end
else do
myname=clientname0
end
parse var myname myname1
ptmp=inhouse_privs||' '||privset1
stuff=check_user_info(who)
parse var stuff lstat .
if strip(lstat)>=1 then do
parse var stuff uu privset2
ptmp=ptmp||' '||privset2
end
return 1 myname1 ptmp
end
/* not inhouse, check if user info available. */
stuff=check_user_info(anip)
parse var stuff lstat . ; lstat=strip(lstat)
/* valid username? return stuff */
if lstat >=1 then return stuff
/* bad authorizaton type */
if lstat=0.2 then do
response_status=sref_response('notimplemented','Unknown authorization type',servername)
return 0
end
/* time out */
if lstat=0.3 then do
response_status=sref_response('503 Service Unavailable','Try again, server was busy.',servername,1)
return 0
end
/* bad nonce */
if lstat=0.4 then do
response_status=sref_response('400 Bad Request','The nonce is invalid.',servername,1)
return 0
end
/* no such user: either ask again, or send a "failure" response file */
gotauser=0
if logon_fail_file=0 then do /* ask again (possibly refresh a stale nonce */
return sref_ask_auth(the_realm,,servername,isstale) /* ask again */
end
/* if here, respond with generic "logon fail file". Note use of amess to
differentiate username failure from logon-limit exceeding */
awebmaster=get_value('WEBMASTER')
if logon_limit >= -lstat | logon_limit=0 then
amess="Incorrect username or password "
else
amess="Too many logon attempts per minute "
/* LOGON failure */
return sref_fail(servername,seloriginal,logon_fail_file,verbose,the_realm,'logon failure', ,
awebmaster,amess,,force_auth, the_realm, urlrealm ,myqueue,tempfile)
/* ------------------------------------------- */
/* check request header for auth, return user info if found and valid user
if privsonly=1, just return privileges (user specific, and possibly "own name"*/
/* ------------------------------------------- */
check_user_info: procedure expose mysem myqueue basesem enmadd os2e isstale port reqnum REALM.,
mytid verbose transaction no_virtual servername host_nickname user_logon_proc user_privs
parse arg anip,PRIVSONLY,noadd
FO=0 ; IF PRIVSONLY=1 THEN FO=""
if user_logon_proc<>' ' then do
uenable=strip(translate(get_value('USER_LOGON_ENABLE'))) /* possibly host specific suppression ? */
if wordpos(uenable,'NO N 0')=0 then do
foo=sref_extract_upwd()
if wordpos(uenable,'1 YES Y')=0 & uenable<>'' then do
user_logon_proc=uenable
end
parse var foo a1 ':' a2 ; username=strip(a1)
anarg=a1' 'a2' 'anip
if user_logon_proc='SREF_USER_LOGON' then do
stuff=sref_user_logon(anarg,servername,host_nickname)
end
else do
yike='stuff='||user_logon_proc||'("'||anarg||'",servername,host_nickname)'
interpret yike
end
parse upper var stuff astat .
if astat='X' then user_logon_proc=''
end
else do
user_logon_proc=''
end
end
if user_logon_proc='' then do /* perhaps userLogonProc doesn't handle this*/
aad=host_nickname; if aad='' then aad=0
stuff=sref_dologon(anip,mysem,myqueue,enmadd,transaction,aad)
parse var stuff stuff ',' username ; username=strip(username)
end
parse var stuff astatus privset1 ; astatus=strip(astatus)
if datatype(astatus)<>'NUM' & user_logon_proc<>' ' then do
ss=sref_error(" Problem with user logon proc "||user_logon_proc || '('stuff,1)
astatus=0
end
IF verbose>2 THEN foo=pmprintf_sref( " User logon info: "astatus,,port)
if astatus=0.1 then isstale=1
if astatus<1 then return astatus
if noadd<>1 then do
addname=get_value('add_user_name')
if user<>'*' then do
if addname=1 then privset1=privset1||' '||username
end
end
privset1=privset1||' '||get_value(user_Privs) /* add "user_privs" default "registered user" privileges */
IF PRIVSONLY=1 THEN RETURN PRIVSET1
return 1 username privset1
/* -----------------------------------------------------------------------*/
/* see if ip address matches one of a set of good ips (1 if yes)*/
/* check for numeric or names ,and check for wildcards */
/* if non-default host, ONLY get "Host specific" inhouseips */
/* -----------------------------------------------------------------------*/
goodips: procedure expose inhouseips. privset1 enmadd os2e verbose transaction servername host_nickname ,
clientname0 mysem myqueue basesem who reqnum REALM.
parse arg anips
anips=strip(anips) ;hostn=strip(host_nickname)
if symbol(inhouseips.0)<>"VAR" then do /* not been read yet */
aa='inhouseips.' ;addit=''
if hostN<>"" then addit='.'||hostn
nin=0
do mm=1 to 10000
useme=enmadd||aa||mm||addit ; useme=strip(useme)
tt=strip(value(useme,,os2e))
if tt="" | tt=0 then leave
nin=nin+1 ; inhouseips.nin=upper(tt)
end
inhouseips.0=nin
end
/* check exact matches -- perhaps name matches */
mdo=inhouseips.0
do mm=1 to mdo
if inhouseips.mm=' ' then iterate
if verify(word(inhouseips.mm,1),'*1234567890.')=0 then do /*a numeric ip */
if strip(word(inhouseips.mm,1))=anips then do /*it's an exact match -- extract privset */
parse var inhouseips.mm ff privset1
return 1
end
end
else do /* a name ip */
if clientname0=0 then
clientname0=sref_clientname(who,mysem,myqueue,basesem,enmadd,transaction)
if strip(word(inhouseips.mm,1))=clientname0 then do /*it's an exact match -- extract privset */
parse var inhouseips.mm ff privset1
return 1
end
end /* name or number inhouseip */
end
/* if here, try wild card matches */
do m2=1 to mdo /* wild card matches */
imm=sref_wild_Match(anips,inhouseips.m2)
if imm=0 & clientname0<>0 then
imm=sref_wild(clientname0,inhouseips.m2)
if imm=0 then iterate
parse var inhouseips.m2 . privset1
return 1
end
return 0 /* no match */
/*--------------------------------------------------*/
/* check user privileges (privset) against a url specific privilege list (aprivs)
if one of them matches, return >0 value
if no match, return 0 */
/* ----------------------------------------------- */
check_privs: procedure expose verbose transaction servername host_nickname ,
who enmadd servdir reqnum REALM.
parse upper arg privset , aprivs
/* check MUST_HAVE privilegs */
if pos('&',aprivs)>0 then do
musthaves=""
oneofs=""
do jj=1 to words(aprivs) /* extrace MUST_HAVE privs */
ajj=strip(word(aprivs,jj))
if abbrev(ajj,'&')=1 then
musthaves=musthaves||' '||ajj
else
oneofs=oneofs||' '||ajj
end
do jj=1 to words(musthaves)
avi=strip(word(musthaves,jj))
ajj=strip(avi,'l','&')
if wordpos(ajj,privset)=0 then do /* must have ALL must_have privs */
return 0
end
end
aprivs=oneofs
end
/* check ONE_OF privileges */
select
when wordpos('SUPERUSER',privset)>0 then
return 1
when wordpos('NO',aprivs)>0 then do
return 0
end
when aprivs="" | wordpos('*',aprivs)>0 | wordpos('YES',aprivs)>0 then do
return 1
end
otherwise do
do mm=1 to words(aprivs)
if wordpos(word(aprivs,mm),privset)>0 then do
return mm
end
end
end /* otherwise */
end /* select */
return 0
/* ----------------------------------------------- */
/* find virtual file name, or perform a remote lookup possibly
returns
file name if local file found (possibly starting with !REMOTE)
0 if no success in finding local or remote file (
remoteok=1 : allow looking up http:// file (and temporary save to temporary file)
if not_f=1, does the "doc not found" to goserve (if 0, does not respond to client)
nocheck=1 -- suppress the nochcek (1= do NOT check for the file's existence) */
/* ----------------------------------------------- */
do_virtual_file:procedure expose os2e mysem myqueue enmadd basesem servername serverport tempfile wild_sels_ok realm. ,
mytid verbose transaction no_virtual host_nickname file_nocheck verbose advopt_mime is_remote reqnum del_send
parse arg ddir,sel,remoteok,docheck,limtype
crlf='0d0a'x /* constants */
parse var sel action '?' .
if realm.!rule<>'' | del_send=1 then do
if realm.!virtual<>0 & del_send=0 then do
tt0=strip(translate(action,'\','/'),'l','\')
parse var realm.!virtual prefx adir
prefx=strip(translate(prefx,'\','/'),'l','\')
tt0a=substr(tt0,length(prefx)+1)
ip1=pos('\',tt0a); ip2=pos('*',adir)
if ip1=0 | ip2>0 then do /* no subdirs, or sub dir okay */
adir=strip(adir,'t','*')
file=adir||tt0a
end
else do /* is a subdir, and no */
file=0 /* so not a match */
end
end
else do /* no virt, use ddir (or !delsend) */
tt0=strip(translate(action,'\','/'),'l','\')
file=strip(translate(ddir,'\','/'),'t','\')||'\'||tt0
end
end
else do
file=wait_queue('VIRTUAL',action||' '||ddir||','||limtype)
end
if file="" | file=0 then return 0
if abbrev(upper(file),'HTTP:')=1 then do /* a remote url */
if remoteok<>1 then return 0 /* do not allow remote "virtual directory*/
tdir=get_value('TEMPDATA_DIR',0)
goo=sref_http_virtual(file,verbose,serverport,tdir)
parse var goo tmpf advopt_mime
is_remote=1
return tmpf
end
if pos('*',action)>0 then do /* request is for a wildcard? */
kk=sref_check_wild(file,action,wild_sels_ok,sel,verbose)
parse var kk i1','file
if i1=2 then return 0
if i1=1 then return file
end
file_Nocheck=file /* used by htaccess routines */
if docheck=1 then do /* check for file existence */
rf=stream(file,'c','query exists')
if rf="" then return 0
end
return file
/* --------------------------------------------------- */
/* take care of server side includes
. If none (or no_include=yes, or is not shtml?), then return 0 -- which means
. "go ahead and return the default document, and maybe cache it? "
*/
/* --------------------------------------------------- */
do_includes:procedure expose tempfile yes_ssi no_include os2e enmadd key_preface quick_interp_code quick_replace quick_interp not_ssi,
cgi_bin_dir seloriginal privset servdir verbose transaction ddir ,
home_dir servername host_nickname home_name no_processing myqueue adv_opts is_public is_encrypt cache_yes,
ssi_extensions who no_interpret_code force_norecord mysem basesem force_auth is_owner_suppress port reqnum REALM.
parse arg tfile,sel0,awords,is_remote,range_stuff
not_ssi=1
if yes_ssi<>1 then do /* yes_ssi permission overrules everything */
if no_include=1 then return 0 /* don't bother, just return original file */
ssi_shtml_only=get_value('SSI_SHTML_ONLY')
/* if shtml mode, check if its an .sht[ml] file */
if ssi_shtml_only=1 then do
FOO1=LASTPOS('.',sel0)
if foo1=0 then return 0 /* no extension! */
anext=upper(delstr(sel0,1,foo1))
ssi_extensions=value('SREF_SSI_EXTENSIONS',,'os2environment')
if wordpos(anext,upper(ssi_extensions))=0 then return 0
end
end
/* else, yes_ssi permssion (so do ssi) */
foo=stream(tfile,'c','query exists')
if foo=0 | foo="" then do /*problem opening ! */
if VERBOSE>0 then ss=sref_error(" Warning: Could not open file for SSIs : " tfile,verbose-1)
return 0 /* just send back file as is */
end
not_ssi=0
/* sref_do_includes */
tmp1=get_value('SSI_CACHE_ON')
ssic=0
if tmp1=0 then ssic=1
if force_auth=1 then ssic=1
DIRLIST=SERVDIR||' '||CGI_BIN_DIR||' '||DDIR||' '||HOME_DIR
gll=key_preface||' , '||quick_interp||' , '||quick_interp_code||' , '||quick_replace
/*no22=0; if range_stuff<>'' then no22=1*/
no22=0
gotit=sref_do_ssi(tfile,is_remote,sel0,awords,seloriginal,privset,enmadd, ,
DIRLIST,verbose,transaction,tempfile,gll, ,
port' 'servername||' '||host_nickname,home_name, ,
no_processing||' '||no_interpret_code||' '||force_norecord||' '||is_owner_suppress||' '||no22,,
myqueue' 'mysem' 'basesem,who,ssic,adv_opts)
return gotit
/**********************************************/
/* check to see if we need NOT call one of the helper threads */
/**********************************************/
check_queue_do:procedure expose no_virtual servername host_nickname myqueue reqnum
parse arg athread,enmadd,args,allow1
os2e='os2environment'
select
when athread="ALIAS" then do
aaa=get_value('SUPPRESS_ALIAS',0)
if aaa=1 then do
return ' 1 , 0 '|| args
end
end
when athread="PUBURL" then do
aaa=get_value('NEVER_PUBLICURLS',0)
bbb=get_value('PUBURL_FILE',0)
if aaa=1 | bbb='' then do
return ' 1 , 0 '
end
aaa=get_value('SREF_NUM_PURLS',,'os2environment')
if aaa=0 then return ' 1 , 0 '
end
when athread="USER" then do
if get_value('SUPPRESS_USER',0)=1 then do
yo=get_value('CHECKLOG')
if yo="NO" then
return ' 1 , 1 '
else
return ' 1, 0 '
end
end
when athread="ACCESS" then do
if get_value('SUPPRESS_ACCESS',0)=1 then do
return ' 1 , 0 '
end
if allow1="YES_NOCHECK" then do
return ' 1 , 0 '
end
end
when athread="VIRTUAL" then do
if no_virtual=0 then no_virtual=get_value('SUPPRESS_VIRTUAL',0)
if no_virtual=1 then do /* quick default, if no virtual */
parse var args action ddir','limtype
t1=strip(strip(translate(ddir,'\','/')),,'\')||'\'
action=translate(action,'\','/')
action=strip(action,'l','\')
tryfile=t1||action
return '1 ,'||tryfile
end
end
otherwise DO
return' 0 , 0 '
END
end
RETURN ' 0 ,0'
/* ------------------*/
/* see if this parameter applies to this host */
/* ------------------*/
check_host: procedure
parse upper arg thehost,thearg
f1=strip(word(thearg,1))
if right(f1,2)<>'//' then return thearg /* non host specific */
t1=left(f1,length(f1)-2)
if thehost=t1 then return strip(delword(thearg,1,1)) /* strip host and return */
return ' ' /* 0 signifies don't use */
/* ----------- */
/* get environment value, possibly host specific
hname=0 -- do not look under hostname
hname=1 -- do not look under default
*/
/* ------------ */
get_value: procedure expose enmadd host_nickname reqnum REALM.
parse upper arg vname,hname0
if hname0=0 then
hname=' '
else
hname=strip(host_nickname)
vname=strip(vname) ;
if hname<>' ' then do
booger=strip(enmadd||vname||'.'||hname)
aval=value(booger,,'os2environment')
if aval<>' ' | hname0=1 Then
return aval
end
aval=value(enmadd||vname,,'os2environment')
return aval
/* --------------------------------- */
/* detect a "moved" url (from an alias) -- calls macrospace routine */
isa_move:procedure expose tempfile verbose servername seloriginal myqueue reqnum REALM.
parse arg sel,servername ,serverport
sel=strip(sel)
tsel=upper(translate(sel,'/','\')) ;a1=left(tsel,1)
if a1='!' | a1='H' then do
wow=sref_isa_move(tsel,sel,servername,serverport,tempfile,verbose,seloriginal)
return wow
end
return 0
/* Determine MIME type. Check the most common ones here,
and if no match, call the more elaboate routine (in macrospace).
This more elaborate one also will examine mediatyp.rxx
If check_type, then use the SREF_CHECK_TYPE procedure if no
explicit type is available (if an
application/octet-stream by sref_mediatype
Also, use !SENDAS mime type, or advanced options file mime type, if
specified
*/
mediatype:procedure expose specific_mime advopt_mime myqueue reqnum host_nickname
sm2=specific_mime
/* if sm2<>0, then use it! */
if sm2<>0 then do
if abbrev(upper(sm2),'CHECK_')=0 then do
aa=translate(sm2,' ','_')
m1=strip(word(aa,1)); m2=strip(word(aa,2))
foof=m1||'/'||m2
return foof
end
end
if advopt_mime<>0 then return advopt_mime
/* if here, not a mime_subtype */
parse arg aval
/* is it sm2 = check_text? */
if upper(sm2)='CHECK_TEXT' then do
aa=sref_check_type(aval,0)
if aa<>0 then return aa
sm2=0 /* don't look again */
end
/* no check_text, so use file extension */
ext=translate(substr(aval, lastpos('.',aval)+1))
if wordpos(ext,'HTM HTML SHTML SHTM HTML-INCLUDE ')>0 then
return ' text/html'
if ext='GIF' then return 'image/gif'
bowow=sref_mediatype(aval,host_nickname) /* not a common default */
if upper(bowow)<>'APPLICATION/OCTET-STREAM' then return bowow
if upper(sm2)='CHECK_TYPE' then /* check type? */
return sref_check_type(aval,bowow)
return bowow /*not check_type */
/******/
/* syntax error */
goterr:
IF RC=-7 THEN EXIT ' ' /* if just a closed connection ,then don't worry */
LL=SIGL
glue='SRE-http error at line 'll '(rc= 'rc
if rxfuncquery('PMPRINTF')=1 then do
say glue
end
else do
if macroquery('sref_error')=' ' then
say glue
else
ss=sref_error(glue,1)
end
IF COMPLETED()=0 THEN
'var type text/plain name glue'
exit ' '
/******/
/* failure error */
goterr2:
IF RC=-7 | rc=-6 THEN return ' ' /* if just a closed connection ,then don't worry */
if rc=-1 | rc=-2 then do
'response HTTP/1.1 503 Service Unavailable'
'STRING Server is busy: try again in a minute ' /* timed out */
return ' '
end
if rc=-3 | rc=-4 then return 'String Server failure: too many bytes uploaded '
foo=sref_error(' SRE-http failure ('rc') at line 'sigl,1)
if completed()=0 then 'audit SRE-http failure ('rc') at line '||sigl
string ' Sorry, server failure ('RC') occured at line '||sigl
exit ' '
/***************************************************************/
sref_do_ping:procedure expose gospid transaction
parse upper arg asel
parse var asel '?' opts
amess=0
select
when opts='' then return 0
when opts='CLIENTS' then amess=extract('clients')
when opts='PING' then amess='Ping '||gospid
when opts='RESPONSETIME' then amess=extract('responsetime')
otherwise return 0
end
'HEADER NOAUTO '
'RESPONSE HTTP/1.1 200 'amess
'STRING !PING on 'transaction
exit ' '
/********************************/
/* check on advanced options */
get_adv_opts:
varg=''
if adv_opts<>" " then do
wd=get_value('workdata_dir')
foo=strip(wd,'t','\')||'\'||strip(adv_opts)
adv_opts_file=stream(foo,'c','query exists')
if adv_opts_file="" then do
adss= sref_error("Warning: missing advanced options file: " foo " ("seloriginal,1)
end
else do
ll=stream(adv_opts_file,'c','query size')
varg=charin(adv_opts_file,1,ll)
end
end
if adv_opts_2<>'' then do
do forever
if adv_opts_2='' then leave
parse var adv_opts_2 aao '|#|' adv_opts_2
if varg='' then
varg=aao
else
varg=varg||'0d0a'x||strip(aao)
end
end
adv_opts=varg
return 1
/*************************************/
/* see if cgi-bin call (and cgi-bin emulation is on */
process_cgi:
cgipath=""
if no_processing=1 then do /* no processing allowed */
response_status=sref_response('unauth',' CGI-BIN processing privileges not granted for: '||sel,servername)
fpp=stream(tempfile,'c','close')
return 0
end
if foobao=1 then do /* see if alias match */
selt=translate(sel,' ','\/?')
aline=wait_queue('ALIAS',word(selt,2))
parse var aline gotit new_dir
if gotit<>0 & new_dir<> "" then do
cgi_bin_dir=strip(translate(new_dir,'\','/'),'t','\')
end
end
else do
cgipath=left(sel,foobao-1)
cgi_bin_dir=do_virtual_file(cgi_bin_dir,cgipath,0,0,'!CGI-BIN')
end
/* hack to allow use of root directory */
if right(cgi_bin_dir,1)=':' then
oof=cgi_bin_dir||'\'
else
oof=strip(cgi_bin_dir,'t','\')
/* get the cgi-bin relevant portion of the
original selector, or it's alias if necessary */
useme=uri
foobao=pos('CGI-BIN/',upper(uri))
if foobao=0 then do
useme=sel
foobao=pos('CGI-BIN/',tsel)
end
selcgi=substr(useme,foobao)
/* is there a chance this scriptname exists? */
parse var selcgi ascript '?' .
parse var ascript . '/' ascript '/' . /* the scriptname, with no path info */
oof2=strip(oof,'t','\')||'\'||ascript
if pos('.',oof2)=0 then oof2=oof2||'.*'
goo=dosdir(oof2)
if goo="" then do /* no match (even to wildcard) */
if selnotfound="" then /* avoid inifinite lloooop */
selnotfound=sref_not_found_local(seloriginal,not_found_url, ,
orig_cbd,enmadd,transaction,home_dir,host_nickname)
else
selnotfound=0
if selnotfound<>0 then do
verb="GET"
sel=not_found_url
return -1
end
else do /* no notfound document, use default */
if verb='POST' then do
foo=sref_get_body() /* clear input stream */
end
response_status= not_found_response(seloriginal,' CGI-BIN script not found ',' ')
selrec=' '
return 0
end
end
tempfile_dir=get_value('TEMPDATA_DIR',0)
cmdfile=dostempname(strip(tempfile_dir,'t','\')||'\f?'||space(right(transaction,verbose),0)||'.cmd')
filter_name=sref_version(port)
if clientname0=0 then
clientname0=sref_clientname(who,mysem,myqueue,basesem,enmadd,transaction)
if moreinfo<>'' & no_postfilter=1 then /* might be needed */
foo=sref_value('NO_POSTFILTER',1,'REQ',reqnum,,enmadd)
/*note: pipe mode "send as written" cgi is no longer supported */
select
when cgi_bin_pieces=2 | cgi_bin_pieces=1 then do /* send pieces as available */
fix_expire=get_value('FIX_EXPIRE')
foox=enmadd' 'transaction' 'home_dir' 'host_nickname','fix_expire' , 'myqueue', 'mysem
response_status=sref_docgi_pieces_2(cgi_bin_dir, selcgi, verb, clientname0, filter_name, serverport , ,
servername,protocol' http/1.1', ddir, who,tempfile,cmdfile,0,VERBOSE,foox,do_htaccess,htaccess_file,privset,empty_path_ok,servdir)
end
otherwise do
foox=enmadd' 'transaction' 'home_dir' 'host_nickname
response_status=sref_docgi(cgi_bin_dir, selcgi, verb, clientname0, filter_name, serverport , ,
servername,protocol' http/1.1', ddir, who,tempfile,cmdfile,0,VERBOSE,foox,do_htaccess, ,
htaccess_file,privset,empty_path_ok,servdir)
end
end /* is a cgi-bin call */
return 1
/** END END END **********************/
/********************** INITIALIZATION PROCEDURES ***********************/
/*********/
/* initialize SRE. */
init_sre:
/*--- Load REXX libraries ----- */
/* Load up advanced REXX functions */
foo=rxfuncquery('sysloadfuncs')
if foo=1 then do
call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
call SysLoadFuncs
end
foo=rxfuncquery('rexxlibregister')
if foo=1 then do
call rxfuncadd 'rexxlibregister','rexxlib', 'rexxlibregister'
call rexxlibregister
end
/* set some parameters */
enmadd="SREF_"||port||"_"
basesem='\SEM32\'||enmadd
os2e='os2environment'
gospid=dospid()
/* ---- Do we need to initialize SRE-http ? --- */
/* Note: we do not use transaction number, since transaction is NOT reset
when the filter is changed. Hence, the use of this rather convoluted scheme */
thesem=basesem
sem_status=eventsem_query(thesem)
if sem_status<0 then do
call pmprintf(' ****** SRE-http started at '||date('n')||' '||time('n'))
is_wait=0
oo=start_srefilter(thesem,moreargs,port,gospid,enmadd,sem_maxwait)
if oo=0 then EXIT ' '
end
/* temporary block on ? */
is_wait=value('SREF_WAIT_FLAG',,'os2environment')
if is_wait=-2 then do
'header add error: Error Starting SRE-http! Restart Goserve, and run PMPRINTF to view error messages'
GOO=VALUE('sref_WAIT_FLAG_ERROR',,'OS2ENVIRONMENT')
'STRING SRE-http Fatal Error: 'goo
'close'
exit ' '
end
if is_wait=1 then call start_srefilter(1)
SRE_SUSPEND=value('SRE_SUSPEND',,'os2environment')
if sre_suspend=10 then do /* refuse connections */
'RESPONSE HTTP/1.1 503 Service Unavailable.'
'header add X-status: currently refusing connections'
'string 'servername()' is not currently accepting connections.'||'0d0a'x||'Please try again in a few minutes '
exit
end
return 1
/*****************************/
/* start srefilter -- or wait for it to finish resetting */
start_srefilter:procedure expose is_wait key_preface reqnum verbose
if is_wait=1 then do
do while is_wait>0
call syssleep 1
is_wait1=value('SREF_WAIT_FLAG',,'os2environment')
if is_wait1<>'' then is_wait=is_wait1
end
return 1 /* done waiting, proceed... */
end
/* as of 1.3g, call an external proc */
parse arg thesem,moreargs,port,gospid,enmadd,sem_maxwait
jj=sreinit1.cmd(key_preface,reqnum,verbose,thesem,moreargs,port,gospid,enmadd,sem_maxwait)
return jj
/*********************/
/* get host,datadir, & servername for this requesete */
get_host_info:procedure expose host_nickname ddir servername uri seloriginal enmadd myaddr reqnum
parse arg protocol
stuff=sref_host_info(myaddr,enmadd,uri,protocol)
if strip(stuff)='BAD' then return -1 /* if http/1.1 client did not include at host: header */
if stuff<>0 then do
parse var stuff servername ',' host_nickname ',' ddir
host_nickname=strip(host_nickname); ddir=strip(ddir)
servername=strip(servername)
end
else do
ddir=datadir()
servername=servername()
host_nickname=' '
end
if abbrev(upper(uri),'HTTP://')>0 then do
parse var uri . '//' . '/' uri
if uri='' then uri='/'
parse var seloriginal . '//' . '/' seloriginal
end
return 1
/****************/
/* -----------------Tidy up some initialization parameters ------------ */
tidy_up:
no_retain=0
reqprivs=''
accprivs=''
isstale=0
maxuser_sem=''
privset=' '
owners=' '
vlv=0 /* varying list verifier */
is_public=1 /* by default, public cache okay */
cache_yes=0 /* do not assume a CACHE permissoin, or publicurl*/
if proxy_cache=0 then is_public=0 /* cache_yes can override proxy_cache */
if left(seloriginal,1)='!' then do
if abbrev(upper(seloriginal),'!SEND')<>1 then is_public=0 /* don't cache special requests */
end
is_alias=0
from_auth=0
tmp.0=0 /* for use by INTERPRET blocks */
crlf='0d0a'x /* might need this */
got_def=0
nopostf=' '
auto_name_type=0
FIRST_HT_AUTO=1
do_htaccess=0 /* 0=don't do, 1= do htaccess */
used_file=' ' /* the file this is the target of the request */
logon_fail_file=0
access_fail_file=0
response_status=' '
serverport=port
doingneg=0
is_remote=0
selnotfound="" /* used with directory specific not found url */
advopt_mime=0 /* used with "sel specific mime type */
doing_autodir=0
if key_preface="#" then key_preface=0 /* # not allowed as key_preface */
never_imagemaps=value('SREF_NEVER_IMAGEMAPS',,'os2environment')
if never_imagemaps<>1 then do
ncsa_ismap=value('SREF_NCSA_ISMAP',,'os2environment')
cern_ismap=value('SREF_CERN_ISMAP',,'os2environment')
end
isinhouse=0
clientname0=0
mytid=dostid()
mysem=thesem||"t"||mytid
myqueue="SREF_"||port||'_t'||mytid
servdir=value(enmadd||'SERVDIR',,os2e)
no_postfilter=0 ; no_virtual=0
/* if !DELSEND special directive, MUST be under tempfile_dir */
if del_send=1 then do
ddir=get_value('TEMPFILE_DIR',0)
if ddir='' then do /* error, make a note */
'RESPONSE HTTP/1.1 405 Method not allowed '
'STRING Error: Server does not support !DELSEND '
call pmprintf(' ERROR: TEMPFILE_DIR not set (!DELSEND ) ')
exit ' '
end
end
verbose=get_value('VERBOSE')
if verbose>3 then FOOO=pmprintf_sref(" Using data directory= " ddir' ' seloriginal,,PORT)
if VERBOSE>1 & host_nickname<>' ' then
FOO=pmprintf_sref(' Request to host: ' host_nicknAME,,PORT)
tempdata_dir=get_value(tempdata_dir)
tdir=strip(TEMPDATA_DIR,'t','\')||'\'
tempfile=tdir'$'mytid'.'port /* Used to create temp (response) file */
tempfile2=tdir'$'reqnum'.'port /* For use in postfilter */
if stream(tempfile,'c','query exists')<>' ' then do /* just in case of prior crash?*/
if verbose>2 then ss= sref_error(" Warning: old tempfile being removed: " tempfile,1)
foo=sysfiledelete(tempfile)
if foo<>0 then do
if verbose>2 then FOO=pmprintf_sref(' Could not delete old tempfile: 'tempfile',trying 'tempfile2,,PORT)
foo=sysfiledelete(tempfile2)
tempfile=tempfile2
end
end
check_alias=get_value('CHECK_ALIAS')
home_dir=get_value('HOME_DIR')
htaccess_file=get_value('HTACCESS_FILE')
do_htaccess=get_value('DO_HTACCESS')
default=get_value('DEFAULT')
no_include=get_value('NO_INCLUDE')
no_processing=get_value('NO_PROCESSING')
no_interpret_code=get_value('NO_INTERPRET_CODE')
auto_header=get_value('AUTO_HEADER')
home_name=get_value('HOME_NAME')
not_found_url=get_value('NOT_FOUND_URL')
not_found_url=sref_replacestrg(not_found_url,'HOME_NAME',home_name)
pre_filter=get_value('PRE_FILTER')
prefilter_name=get_value('PREFILTER_NAME')
auto_name=get_value('AUTO_NAME')
/* clear error-message variable */
errorvar='SRE_ERROR_'||gospid||'_'||mytid
/* make personallized queue and semaphore */
call make_semmi
base_sent=extract('bytessent')
aas='!ERROR= HOST_NICKNAME='host_nickname' SERVERNAME='servername' DATADIR='ddir' IS_ENCRYPT='is_encrypt
oo=sref_value('!INI',aas,'REQ',reqnum,,enmadd)
return 1
/***************/
/* create a personallized queue & semaphore */
make_semmi:
a=rxqueue('s',myqueue)
noq=1
signal off syntax ; signal off error
signal on syntax name badq ; signal on error name badq
queue 0
noq=0
badq:
signal off syntax ; signal off error
signal on syntax name goterr
signal on error name goterr
if noq=1 then do
IF VERBOSE>0 THEN say " creating myqueue " myqueue
foo=rxqueue('c',myqueue)
if upper(foo)<>upper(myqueue) then say ' wierd queue error ' foo myqueue
a=rxqueue('s',myqueue)
end
yyq=queued()
if yyq>100 then do
if verbose>1 then say " Killing residual queue " myqueue yyq
aa2=rxqueue('d',myqueue)
aa2=rxqueue('c',myqueue)
aa2=rxqueue('s',myqueue)
yyq=queued()
end
do mmy=1 to yyq
pull poo .
end
wow=eventsem_query(mysem)
if wow=-187 then do
a=eventsem_create(mysem)
if a=0 then do
nop
end
else do
call pmprintf(' Could not create semaphore: 'mysem' , error='a)
'response HTTP/1.1 503 Service Unavailable'
'STRING Server is Busy. Try again later.'
exit ' '
end
end
foo=eventsem_reset(MYSEM)
return 1
/**************************/
/* add priviliges (called if puburl found */
add_privs_pub:
if wordpos(who,owners)>0 then privset=privset||" SUPERUSER INHOUSE "||INHOUSE_PRIVS
check_add_privs=get_value('CHECK_ADD_PRIVS') /* LOOK FOR ADDITIONAL PRIVILEGES? */
if check_add_privs=1 then do
aprefix=strip(get_value('ADD_PRIVS_PREFIX'))
ap2=sref_get_add_privs(host_nickname,who,port,enmadd,tempdata_dir,verbose)
ap2=translate(ap2,' ','&') /* correct entry errors (& for RESOURCE privs only */
do iw=1 to words(ap2)
privset=privset||' '||aprefix||strip(word(ap2,iw))
end
end
CALL get_user_privs 0 /* get inhouse, authorization, and own-name privs */
if realm.!rule<>' ' then do /* use realm info */
aline='1 , '||realm.!access
end
else do
aline=wait_queue('ACCESS',seloriginal,allow_access)
end
parse var aline . ',' . ',' accopts ',' urlrealm ',' . ',' adv_opts ',' adv_opts_2
call get_adv_opts /* get advanced options */
if wordpos('NO_POSTFILTER',upper(accopts))>0 then no_postfilter=1
return 1
/*****************************************/
/* add privileges from various sources */
add_privs_2:
/* add public_privs to everyone */
public_privs=get_value('public_privs')
privset=privset||' '||public_privs
/* add "username " to privset (this step may be redundant, but... ? */
addname=get_value('add_user_name')
if addname=1 then do
if wordpos(upper(username),upper(privset))=0 then
privset=privset||' '||username
end
/* check for dynamic privileges ? */
check_add_privs=get_value('CHECK_ADD_PRIVS')
if check_add_privs=1 then do
aprefix=strip(get_value('ADD_PRIVS_PREFIX'))
ap2=sref_get_add_privs(host_nickname,who,port,enmadd,tempdata_dir,verbose)
do iw=1 to words(ap2)
privset=privset||' '||aprefix||strip(word(ap2,iw))
end
privset=translate(privset,' ','&') /* correct entry errors */
end
isinhouse=wordpos('INHOUSE',upper(privset)) /* flag for inhouse client */
if wordpos('SUPERUSER',upper(privset))>0 then do
no_processing=0 /* make sure superusrs are unimpeded */
no_interpret_code=0
end
return 1
/***********************/
/* lookup logon parameters */
get_log_params:
checklog=get_value('CHECKLOG');if checklog="YES" then checklog="ALWAYS"
inhouse_privs=get_value('INHOUSE_PRIVS')
the_realm=get_value('THE_REALM')
allow_access=get_value('ALLOW_ACCESS')
if checklog="INHOUSE" | checklog="ALWAYS" then
dologon=1
else
dologon=0
return 1
/*******************************************/
/* lookup various permissions */
lookup_permissions:
/* Now check for ssi and ssp privs */
aok=wordpos('NO_SSI',accopts)
if aok<>0 then
no_include=1
yes_ssi=0
yes_ssi=wordpos('YES_SSI',accopts)
if yes_ssi>0 then yes_ssi=1
aok=wordpos('NO_SSP',accopts)
if aok<>0 & wordpos('SUPERUSER',privset)=0 then
no_processing=1
aok=wordpos('NO_CODE',accopts)
if aok<>0 & wordpos('SUPERUSER',privset)=0 then
no_interpret_code=1
/* explicitly allow caching? */
aok=wordpos('CACHE',accopts)
if aok<>0 then do
is_public=1
cache_yes=2
end
aok=wordpos('CACHE*',accopts)
if aok<>0 then do
is_public=2 ; cache_yes=1
end
aok=wordpos('NOCACHE',accopts) /* nocache trumps cache */
if aok<>0 then do
is_public=0
end
IF IS_PUBLIC=0 THEN CACHE_YES=0
/* see if suppress alias and/or suppress of this url*/
if wordpos('NO_ALIAS',accopts)>0 then
check_alias=0
if wordpos('NO_POSTFILTER',accopts)>0 | force_norecord=1 then
no_postfilter=1
if wordpos('NO_VIRTUAL',accopts)>0 then
no_virtual=1
if wordpos('NO_HTACCESS',accopts)>0 then
do_htaccess=0
if wordpos('SUPERUSER',privset)>0 then
do_htaccess=0
if del_send=1 then do /* del_send has limited "mobility", regardless of cache privilege */
cache_yes=0; is_public=0 ; no_virtual=1 ; check_alias=0
end
return 1
/*****************************/
/* do a special request */
do_a_special:
usel=upper(sel)
if abbrev(usel,'!DIR')=1 then do
parse var sel action '?' stuff
dir_cache_size=value('SREF_DIR_CACHE_SIZE',,'os2environment')
dir_cache_duration=value('SREF_DIR_CACHE_DURATION',,'os2environment')
response_status=sref_dir(ddir,tempfile,action,stuff,tempdata_dir, ,
dir_cache_duration,dir_cache_size,enmadd, ,
transaction,verbose,servername,host_nickname,home_dir,privset,doing_autodir,seloriginal,protocol)
if response_status=-1 then do
response_status= not_found_response(seloriginal,' the <tt>' stuff' </tt>directory could not be found.',not_found_url)
end
return 1
end
if abbrev(usel,'!SSI')=1 then do
quick_interp=value("SREF_QUICK_INTERP",,'os2environment')
quick_interp_code=value('SREF_QUICK_INTERP_CODE',,'os2environment')
quick_replace=value('SREF_QUICK_REPLACE',,'os2environment')
parse var sel action '?' args ; args=strip(args)
if wordpos('SUPERUSER',upper(privset))+wordpos('CONTROL',upper(privset))=0 then do
response_status=sref_ask_auth(the_realm,,servername,isstale)
end
else do
DIRLIST=SERVDIR||' '||CGI_BIN_DIR||' '||DDIR||' '||HOME_DIR
call check_owner_suppress
foo=sref_do_ssi('*'||strip(args),0,0,0,seloriginal,privset,enmadd, ,
DIRLIST,verbose,transaction,tempfile, ,
key_preface||' , '||quick_interp||' , '||quick_interp_code||' , '||quick_replace,,
servername||' '||host_nickname,home_name, ,
no_processing||' '||no_interpret_code||' '||force_norecord||' '||is_owner_suppress||' 0 ', ,
myqueue' 'mysem' 'basesem,who)
end
return 1
end
if abbrev(usel,'!AUTH')=1 then do
response_status=sref_ask_auth('Force_authorization',,servername,isstale)
return 1
end
/* otherwise, one of the generic ones */
post_filter_message=sref_special_request(sel,privset,the_realm,os2e,enmadd,tempfile)
if post_filter_message=-1 then do /* !special requests require special privs */
response_status=sref_ask_auth(the_realm,,servername,isstale)
end
if abbrev(post_filter_message,'Unknown') then do
response_status=sref_response('badreq', 'asked for unknown Special control "'sel'"',servername)
end
return 1
/*********************************/
/* process a non-html file */
process_non_Html:
doerase=''
/* IF HERE, not a byte range request */
if del_send=1 then do /* a "delete after send" rquest */
response_status='200 '||dosdir(file,'s')
doerase='ERASE'
end
else do
response_status='200 '||dosdir(file,'s')
end
if file<>'' then fooo=stream(file,'c','close')
okpr=0
select
WHEN CACHE_YES=1 & IS_PUBLIC=2 THEN DOCACHE='CACHE* MAXAGE 1 '
WHEN CACHE_YES=2 & IS_PUBLIC=1 THEN DOCACHE='CACHE'
when proxy_cache=0 then docache='NOCACHE*'
when selnotfound<>'' then docache='NOCACHE* RESPONSE 404%20Not%20Found'
when is_public=0 then docache='NOCACHE'
when is_public=2 then docache='CACHE*'
otherwise docache=' '
end
if del_send<>1 then okpr=get_value('ACCEPT_RANGE')
if dodebug=1 then
say "!DEB:MA4 "||left(transaction,5)' 'left(time('l'),11)' pre srefgos(nonhtml)'
filex='"'||file||'"'
FOO=sref_gos('FILE 'doerase ' type ' atype ' 'docache' NAME" 'filex ' ENCRYPT 'is_encrypt' VLV 'vlv' !RANGE 'range_stuff,, ,
okpr,adv_opts, ,
enmadd,protocol,,
response_status,servername,,host_nickname,no_postfilter,,reqprivs)
foo=strip(foo)
select
when (word(foo,1)='200' | word(foo,1)='201') & datatype(word(foo,3))='NUM' then do
response_status=word(foo,1)' 'word(foo,3)
end
when word(foo,1)=206 | word(foo,1)=226 | word(foo,1)=227 then do
ofo=extract('bytessent')-base_sent
RESPONSE_STATUS=word(foo,1)||' '||ofo
end
when abbrev(foo,'2')=0 then do
ofo=extract('bytessent')-base_sent
response_status=word(foo,1)||' '||ofo
end
otherwise nop
end
return 1
/*********************************/
/* response_s */
/* process an html file */
process_html:
call check_owner_suppress
NOT_SSI=0
sxp=' '
quick_interp=value("SREF_QUICK_INTERP",,'os2environment')
quick_interp_code=value('SREF_QUICK_INTERP_CODE',,'os2environment')
quick_replace=value('SREF_QUICK_REPLACE',,'os2environment')
dofile1=do_includes(file,action,awords,is_remote,no_postfilter,range_stuff) /* process file for ssis */
dynfile=''
parse var dofile1 astat','cfile
if dodebug=1 then
say "!DEB:MA5 "||left(transaction,5)' 'left(time('l'),11)' pre do_includes'
parse var astat istat maxage dynfile /*maxage may be time (if non dynamic ssis')
or file name (semi-dynamicss
or nothing (if fully dynamic) */
sxp=' '
if maxage<>'' & datatype(maxage)='NUM' then sxp='MAXAGE 'maxage
aah=0
if auto_header='ALWAYS' then
aah=1
if auto_header='HEAD' & verb='HEAD' then
aah=2
okpr=0
if del_send<>1 then okpr=get_value('ACCEPT_RANGE')
i1=1
if maxage<>'' then i1=strip(maxage)
select
WHEN CACHE_YES=1 & IS_PUBLIC=2 THEN DOCACHE='CACHE* MAXAGE 1 '
WHEN CACHE_YES=2 & IS_PUBLIC=1 THEN DOCACHE='CACHE'
when proxy_cache=0 then docache='NOCACHE*'
when selnotfound<>'' then docache='NOCACHE* RESPONSE 404%20Not%20Found'
when is_public=0 then docache='NOCACHE'
when is_public=2 then docache='CACHE*'
otherwise docache=' '
end
doerase=' '
if del_send=1 then doerase='ERASE'
/* ISTAT=0: "no ssis, or not allowed to do ssis" */
if trunc(istat)=0 then do
doerase=''
if del_send=1 then do
response_status='200 '||dosdir(file,'s')
end
else do
response_status='200 '||dosdir(file,'s')
end
if selnotfound<>'' then do
response_status='404 '||dosdir(file,'s')
end
filex='"'||file||'"'
foo=sref_gos('FILE 'doerase ' 'sxp' type text/html 'docache ' NAME" 'filex' ENCRYPT 'is_encrypt' VLV 'vlv' !RANGE 'range_stuff,, ,
okpr,adv_opts, ,
enmadd,protocol,,
response_status,servername,aah,host_nickname,no_postfilter,,reqprivs,,verbose)
select
when (word(foo,1)=200 | word(foo,1)=201) & datatype(word(foo,3))='NUM' then do
response_status=word(foo,1)' 'word(foo,3)
end
when word(foo,1)=206 then do
ofo=extract('bytessent')-base_sent
RESPONSE_STATUS='206 '||EXTRACT('BYTESSENT')
end
when abbrev(foo,'2')=0 then do
ofo=extract('bytessent')-base_sent
response_status=word(foo,1)||' '||ofo
end
otherwise nop
end
if selnotfound<>'' then do
response_status='404 '||ofo
end
IF NOT_SSI=1 & VERBOSE>3 THEN call pmprintf( " HTML file was NOT checked for SSI's: "action)
end /* istat=0 == no ssis in file */
/* ISTAT=-1 : Problem (often a broken connection */
if istat=-1 then do
return 1
end
/* ISTAT=-2: return a cached-as-is (static ssis) file */
if istat=-2 then do
foo=sref_gos('FILE type text/html 'sxp ' 'docache ' NAME 'cfile' ENCRYPT 'is_encrypt' VLV 'vlv' !RANGE 'RANGE_STUFF,,,
okpr,adv_opts, ,
enmadd,protocol, ,
response_status,servername,aah,host_nickname,no_postfilter,,reqprivs,file,verbose)
response_status='200 '||dosdir(cfile,'S')
if (word(foo,1)=200 | word(foo,1)=201) & datatype(word(foo,3))='NUM' then do
response_status=word(foo,1)' 'word(foo,3)
end
if word(foo,1)=206 then do
ofo=extract('bytessent')-base_sent
RESPONSE_STATUS='206 '||ofo
end
if abbrev(foo,'2')=0 then do
ofo=extract('bytessent')-base_sent
response_status=word(foo,1)||' '||ofo
end
end
/* istat=-3: redirected or otherwise resolved */
if istat=-3 then do
ofo=extract('bytessent')-base_sent
response_status='200 '||ofo
end
/* ISTAT>0 == use VAR to return dynamic ssi containing document (or first
static cache document. Note that these might be
"semi dynamic" ssis (that can be handled by sreproxy,)
a condition noted by dynfile <>'' */
if istat>=1 then do
if selnotfound='' & is_public=1 then do /* set max-age for dynamic ssis? */
if maxage<>'' then
aa=maxage*86400
else
aa=strip(value('SREF_DYNSSI_MAXAGE',,'os2environment'))
if datatype(aa)='NUM' then
aa=' MAXAGE 'aa's '
else
aa=''
docache='CACHE_S 'aa /* special case of ssi-cache of dynamic ssi */
end
foo=sref_gos('VAR type text/html 'sxp ' 'docache ' name ' file ' ENCRYPT 'IS_ENCRYPT' VLV 'vlv' !RANGE ' RANGE_STUFF, ,
cfile,0,adv_opts,enmadd,protocol,,
response_status,servername,aah,host_nickname,no_postfilter,dynfile,reqprivs,file,verbose)
if selnotfound='' then do
response_status='200 '||istat
end
if (word(foo,1)=200 | word(foo,1)=201) & datatype(word(foo,3))='NUM' then do
response_status=word(foo,1)' 'word(foo,3)
end
IF SELNOTFOUND<>'' THEN do
response_status='404 '||dosdir(file,'s')
end
ofo=extract('bytessent')-base_sent
if word(foo,1)=206 then RESPONSE_STATUS='206 '||ofo
if abbrev(foo,'2')=0 then response_status=word(foo,1)||' '||ofo
end
/* cleanup and return */
if del_Send=1 then do
arf=sysfiledelete(file)
end
return 1
/* Look in advanced options file for a SET ENCRYPT entry */
sref_adv_opts_encrypt:procedure
parse upper arg is_encrypt,adv_opts,default_encryption
crlf='0d0a'x
do forever
if adv_opts='' then leave
parse var adv_opts aline (crlf) adv_opts
aline=strip(space(aline))
if abbrev(aline,'SET ENCRYPT')=0 then iterate
is_encrypt=strip(word(aline,3))
if is_encrypt='' then is_encrypt=default_encryption
end
return is_encrypt
/**********************************************************/
/* to be moved to macrospace */
/*****************************/
/**********************************************************/
/*****************************/