home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / srev13g.zip / srefiltr.80 < prev    next >
Text File  |  1999-06-27  |  97KB  |  2,847 lines

  1. /* Sre-http main program, ver 1.3g
  2.   Copyright for the world, 1997,1998,1999. Daniel Hellerstein.
  3.   Liability,etc. strictly denied (see the READ.ME file);
  4.   but feel free to use and modify this freeware code as you see fit
  5.   (no compensation required, but attribution is deemed proper and fitting).
  6.  
  7.   See SREINIT0.CMD for some startup parameters */
  8.  
  9.  
  10. /* ---------Get stuff sent from GOSERVE program -----------------*/
  11.  
  12. parse arg source, request , seloriginal,MOREINFO
  13. 'RESPONSE HTTP/1.1 200 Ok.'           /*http/1.1 is now the default response */
  14.  
  15.  
  16. /*** UNcomment this for debugging purposes 
  17. 'read header var foob '
  18. say " SOURCE: " source
  19. say " request: " request
  20. say foob
  21. *******/
  22.  
  23. enctypes='SRE_A SRE_B SRE_BF SRE_BFC'  /* currently supported encryption types */
  24.  
  25. /* set to 1 to enable some debug-tracing  -- set to 0 to disable */
  26. dodebug=0
  27. aa=value("SREF_DEBUG",dodebug,'os2environment')
  28.  
  29. /*set exception handler */
  30. signal on syntax name goterr;signal on error name goterr
  31. signal on halt name goterr;call on failure name goterr2
  32.  
  33. request0=request ; selrec=seloriginal
  34. parse var source myaddr port transaction who whoport . /* Often useful */
  35. parse var request verb uri protocol .        /* split up the request line */
  36. reqnum=extract('request')
  37.  
  38. crlf='0d0a'x                      
  39.  
  40. if dodebug=1 then do
  41.   aa=''
  42.   if moreinfo='' then aa=left(seloriginal,25)
  43.   say "!DEB:MA1 "||left(transaction'-'reqnum,10)' 'left(time('l'),11)' 'aa
  44. end
  45.  
  46. verb=translate(verb)
  47. uri=strip(uri)
  48.  
  49. /* initialize? */
  50. call init_sre
  51.  
  52. key_preface=value("SREF_KEY_PREFACE",,'os2environment')
  53. never_publicurls=value("SREF_NEVER_PUBLICURLS",,'os2environment')
  54. proxy_cache=value('SREF_PROXY_CACHE',,'os2environment')
  55. parse var proxy_cache proxy_cache '_' .
  56. proxy_cache=strip(proxy_cache)
  57.  
  58. user_logon_Proc=value('SREF_USER_LOGON_PROC',,'os2environment')
  59. wild_sels_ok=value('SREF_WILD_SELS_OK',,'os2environment')
  60. enable_encryption=value("SREF_ENABLE_ENCRYPTION",,'OS2ENVIRONMENT')
  61. default_encryption=value("SREF_DEFAULT_ENCRYPTION",,'OS2ENVIRONMENT')
  62.  
  63. /* Check for basic grooviness */
  64. if left(protocol,4)\='HTTP' & protocol\='' then do
  65.           response_status=sref_response('badreq', 'specified a protocol that was not HTTP',servername)
  66.           clientname0=who
  67.           signal do_post_filter
  68. end
  69. if request=" " then return 'NODATA NoWait NoResponse'     /* netscape sometimes does this */
  70. if abbrev(upper(request),'GETIP')=1 then return 'NoDATA NoWait'
  71.  
  72. /* special head request -- used by monitoring/rebalancing addons */
  73. main_server=value('SREF_MAIN_SERVER',,'os2environment')
  74. if main_server='' then main_server=myaddr
  75. if transaction>1 then do
  76.   if upper(verb)='HEAD' & who=main_server & abbrev(upper(seloriginal),'!PING')=1 then do
  77.      aa=sref_do_ping(seloriginal)  /* might exit */
  78.   end
  79. end
  80.  
  81. /* Get host, datadir, and servername info */
  82. amess=''
  83. if moreinfo<>'' then do
  84.    parse var moreinfo servername','host_nickname',' ddir .
  85.    if abbrev(upper(uri),'HTTP://')>0 then do
  86.           parse var uri . '//' . '/' uri
  87.           if uri='' then uri='/'
  88.           parse var seloriginal . '//'  . '/' seloriginal
  89.    end        
  90. end
  91. else do
  92.    amess=get_host_info(protocol)
  93. end
  94. servername=strip(servername); host_nickname=strip(host_nickname);ddir=strip(ddir)
  95.  
  96. if amess=-1 then do
  97.      foo=sref_response('400 Bad Request','HOST not provided by http/1.1 client',myaddr)
  98.      response_status=sref_response('badreq', 'http 1.1 client did not include host information',servername)
  99.      clientname0=who
  100.      signal do_post_filter
  101. end
  102.  
  103. /* check if load balancing needed */
  104. backupserverlist=value('sref_backupserverlist',,'os2environment')
  105. loadthreshold=value('sref_loadthreshold',,'os2environment')
  106. if abbrev(upper(seloriginal),'!NOBALANCE')<>1 & abbrev(upper(seloriginal),'!FORCE')<>1  ,
  107.           &  loadthreshold>0 then do
  108.  verbose=get_value('VERBOSE',0)
  109.  servdir=value(enmadd||'SERVDIR',,os2e)
  110.  foo=sref_backupserver(backupserverlist,loadthreshold,host_nickname,seloriginal,servdir,verbose)
  111.  if foo<>"" then do
  112.      response_status='302 0'
  113.      clientname0=who
  114.      signal do_post_filter
  115.  end
  116. end                     /* load balancing not allowed */
  117.  
  118. /* Take care of special ! directives, and set several parameters, such as:
  119.     force_auth force_norecord specific_mime del_send quick_run */
  120. call  modify_seloriginal 
  121. if enable_encryption=0 then is_encrypt=0  
  122.  
  123. range_at_end=value('SREF_RANGE_AT_END',,'os2environment')
  124. if range_stuff='' & range_at_end=1 then do       /* check for ;range ? */
  125.    iss=pos(';',seloriginal)  /* check for ;range info in selector? */
  126.    if iss>0 & pos('?',seloriginal)=0 then do  /* if ssp, don't do it */
  127.      range_stuff=substr(seloriginal,iss+1)
  128.      seloriginal=left(seloriginal,iss-1)  ; selrec=seloriginal
  129.    end
  130. end
  131.  
  132. call tidy_up            /* set a few more parameters */
  133.  
  134. IF RANGE_STUFF<>'' & VERBOSE>3 THEN 
  135.      foo=pmprintf_sref('RANGE info= 'range_stuff,,port)
  136.  
  137. /*  -- now process the request  */
  138.  
  139. /* 1) call a pre-filter (it might EXIT back to GoServe)
  140.      The pre-filter should check for completion!
  141.     Note that pre-filter is ALWAYS called, even if cached transfer occurred
  142.    (assuming that you've set goserve's "call filter anyways" parameter */
  143.  
  144. if pre_filter="FIRST"  then do
  145.     prefilter_result=do_prefiltr(' ')
  146.     parse var prefilter_result status ',' prefilter_result
  147.     a=done_it(status,"Pre-filter processed: "||prefilter_result)
  148.     if a=1 then do
  149.           signal do_post_filter
  150.     end
  151. end
  152.  
  153. /* 2) MAKE SURE THE REQUEST IS STILL ACTIVE!!
  154.      (IF CACHING OCCURED, IT MIGHT NOT BE !! */
  155. aa=done_it(0,'From cache: '||seloriginal)
  156.  
  157. /* already been completed (possibly from prefilter) -- look for "no record" flags */
  158. /* Note: if already completed, then don't worry about sreproxy caching */
  159. if aa=1 then DO
  160.  
  161.    if force_norecord=1 then return ' ' /* a !norecord request */
  162.  
  163. /* is it a public url with NORECORD option */
  164.    aline=wait_queue('PUBURL',seloriginal)
  165.    parse var aline . aline .
  166.    if pos('NORECORD',aline)>0 then return ' '
  167.  
  168. /* check access file for nopostfilter */
  169.   aline=wait_queue('ACCESS',seloriginal,allow_access)
  170.   parse var aline istat ',' accprivs ',' accopts ',' .
  171.   accprivs=space(strip(upper(translate(accprivs,' ','09'x))),1)
  172.   accopts=space(strip(upper(translate(accopts,' ','09'x))),1)
  173.   if wordpos('NO_POSTFILTER',accopts)>0  then return ' '
  174.  
  175. /* postfilter not suppressed ... do it */
  176.     response_status='200 '||extract('bytessent')
  177.     signal do_post_filter
  178. END
  179.  
  180. /* 2b) check for Expect: 100-Continue */
  181. if protocol<>'HTTP/1.0' then do  /* not needed for http/1.0 clients */
  182.   oo=upper(reqfield('Expect'))
  183.   if strip(oo)='100-CONTINUE' then do
  184.      a1='100-continue not supported'
  185.      foo=sref_gos('VAR type text/html NOCACHE RESPONSE 417%20Expectation%20Failed NAME A1 ',a1)
  186.      signal do_post_filter
  187.   end
  188. end
  189.  
  190.  
  191. /* 2c) get superceding realm info? */
  192.  
  193. realm.=''
  194. no_srealm=value('SREF_NO_SUPERCEDING_REALM',,'os2environment')
  195. if no_srealm<>1 then do
  196.     parse var no_srealm is1 is2
  197.     if is2<>0 then do
  198.        srealm=wait_queue('SREALM',seloriginal,,1)
  199.     end
  200.     if srealm<>'' then
  201.       parse var srealm realm.!realm (crlf) realm.!rule (Crlf) realm.!access (CRLF) ,
  202.                        realm.!alias (crlf) realm.!puburls (crlf) realm.!virtual
  203. /*
  204. say host_nickname " SREALM: " realm.!realm
  205. say  "  -- rul "realm.!rule
  206. say  "  -- ac "realm.!access
  207. say  "  -- al "realm.!alias
  208. say  "  -- pub "realm.!puburls
  209. say  "  -- vir "realm.!virtual
  210. */
  211.  
  212. end
  213.  
  214. /* 3) Is it one of the public_urlS ??. IF so, skip logons,
  215.      etc (but do aliases and ssi's). */
  216.  
  217. sel=seloriginal 
  218.  
  219. if never_publicurls<>1 then do
  220.   foo=get_value('PUBURL_FILE')
  221.   if foo='' then do
  222.      aline=0                   /* no file, hence no publicurls */
  223.   end
  224.   else do
  225.      if realm.!rule<>'' then do         /* use realm match */
  226.        if realm.!puburls<>0 then        /* is a pub url */
  227.            aline=realm.!rule' 'realm.!puburls
  228.        else
  229.            aline=0
  230.      end
  231.      else do
  232.          aline=wait_queue('PUBURL',seloriginal) 
  233.      end
  234.   end
  235.   if aline<>0 then do             /* matched a public url! */
  236.      do_htaccess=0 ; is_encrypt=0 ; is_public=1; CACHE_YES=2  /* proxy cache must revalidate */
  237.  
  238.      privset=get_value('public_privs')||' PUBLIC_URL '
  239.  
  240.      stuff=sref_public_urls(sel,aline,ddir,home_dir,verbose,specific_mime)
  241.  
  242.      parse var stuff  litmatch norecmatch amessage
  243.      litmatch=strip(litmatch) 
  244.      if strip(norecmatch)=1 then no_postfilter=1
  245.      if litmatch=1 then do  /* sref_public_urls responded to literal puburls */
  246.         pr=get_value('ACCEPT_RANGE')
  247.         foo=sref_gos(amessage ' MAXAGE 1 !RANGE 'range_stuff,,pr,,enmadd, ,
  248.                    protocol,,,,host_nickname,no_postfilter)
  249.         signal do_post_filter
  250.      end
  251.      if  value('SREF_ALWAYS_CHECK_PRIVS',,'os2environment')=1 then call add_privs_pub       /*  get privs? */
  252.      call fix_privset           /* remove repeats, find secret privs */
  253.      signal  do_alias      /*  do the verb (skip logons, access check, etc */
  254.   end
  255. end             /* neverpublicurl */
  256.  
  257.  
  258. /* 4) Not a public_url; Do we check for logon rights, etc. */
  259.  
  260. /* 4a) check for unallowed ip */
  261. username=' '            
  262. owners=get_value('OWNERS')
  263. badips=get_Value('UNALLOWEDIPS')
  264. mdo=0
  265. if badips=1 then do
  266.    mdo=sref_badips(who,enmadd,host_nickname)
  267.    is_public=0
  268. end
  269. if mdo=1 then do  /* he is a bad ips, but we let owner and inhouse override it */
  270.   IS_PUBLIC=0            /* CAN'T BE CACHED BY PROXY ! */
  271.   if wordpos(who,owners)=0 then do    /* not an owner */
  272.     call goodips(who)
  273.     if result=0 then do  /* not an inhouseips */
  274.           response_status=sref_response('unauth', 'You are not permitted access to this web server ',servername)
  275.           signal do_post_filter
  276.     end
  277.     else do
  278.         if verbose>0 then foo=pmprintf_sref(' Note: 'who' is a badips and inhouseips -- ignoring badips! ',,port)
  279.         username=who
  280.     end
  281.   end
  282.   else do
  283.      if verbose>0 then  foo=pmprintf_sref(' Note: 'who' is  badips and an owner -- ignoring badips! ',,port)
  284.      username='OWNER'
  285.   end
  286. end
  287.  
  288.  
  289.  
  290. /* 4b) Do a DNS check ? */
  291. dns_check=get_value('dns_check')
  292. if dns_check="YES" then do
  293.    IS_PUBLIC=0
  294.    if clientname0=0 then
  295.        clientname0=sref_clientname(who,mysem,myqueue,basesem,enmadd,transaction)
  296.    if clientname0=who then do
  297.         audit ' Denied access to ' who
  298.         response_status=sref_response('unauth', 'No client name found, access to this web server is denied. ',servername)
  299.         signal do_post_filter
  300.     end
  301. end
  302.  
  303. /* 4c) Check user/pwd/privilege list  */
  304. call get_log_params
  305.  
  306. IF CHECKLOG<>'NO' THEN IS_PUBLIC=0 /* IF LOGON REQUIRED, then no public cache */
  307.  
  308. /* do logons, etc ... */
  309.  
  310.  if  wordpos(who,owners)>0 then do   /* owners are treated with kid gloves */
  311.          privset="SUPERUSER INHOUSE "||inhouse_privs   /* also give inhouse privs  */
  312.          CALL get_user_privs 1,1  /* get user privs */
  313.          username="OWNER"
  314.  end
  315.  else do                       /* non owners get the third degree? */
  316.      if  dologon=1 then do       /* yup, book 'em */
  317.          logon_fail_file=get_value('LOGON_FAIL_FILE')
  318.          logon_limit=value('SREF_LOGON_LIMIT',,'os2environment')
  319.          userinfo=do_logon(who,inhouse_privs)    /* if no match, exits (for new pwd or say sorry)  */
  320.          if gotauser=0 then do
  321.                 response_status=userinfo
  322.                 signal do_post_filter
  323.          end
  324.          parse var Userinfo lstat username privset
  325.          username=strip(username)
  326.  
  327.         /*very tough--only inhouse allowed (explicit or as a privilege)?*/
  328.         if checklog="INHOUSE" & wordpos('INHOUSE',privset)=0 & wordpos('SUPERUSER',privset)=0 then  do
  329.            response_status=sref_response('unauth', 'Sorry, access currently limited to in-house users ',servername)
  330.            signal do_post_filter
  331.         end     /* not inhouse */
  332.  
  333. /* If here, username/password found welcome ! */
  334.         if verbose>1 then foo=pmprintf_sref(host_nickname '// 'seloriginal' :request from: ' username '(privs: ' privset,,port)
  335.  
  336.      end                /* dologon =1 */
  337.  
  338. /* If here, then no logons required (dologon=0 */
  339.      else do
  340.         CALL get_user_privs 1    /* go get inhouse, user; but NOT ownname privileges */
  341.      end                 /* check if logon rwquired */
  342.  
  343.  end                    /* not superuser */
  344.  
  345. /* 5) Logon permitted. Add more privileges? */
  346. call add_privs_2                /* add privileges to non puburls */
  347.  
  348.  
  349. /* 5a) extract secret privileges, and remove redundant privileges  */
  350. call fix_privset
  351.  
  352.    
  353. /*  6) now check ACCESS file */
  354.  
  355.   if realm.!rule<>' 'then do            /* use realm info */
  356.       aline='1 , '||realm.!access
  357.   end
  358.   else do
  359.      aline=wait_queue('ACCESS',seloriginal,allow_access)
  360.   end
  361.  
  362.   parse var aline istat ',' accprivs ',' accopts ',' urlrealm ',' afail_file ',' adv_opts ',' adv_opts_2
  363.   accopts=space(strip(upper(translate(accopts,' ','09'x))),1)
  364.   accprivs=space(strip(upper(translate(accprivs,' ','09'x))),1)
  365.  
  366. /* privileges required (non *, and allow_access disabled */
  367.   IF ACCPRIVS<>' ' & POS('*',ACCPRIVS)=0 & abbrev('YES',allow_access)=0 THEN do
  368.      IS_PUBLIC=0
  369.   end
  370.  
  371.   afail_file=strip(afail_file)
  372.   if urlrealm="" then do
  373.      if value('SREF_REALM_1ST_PRIV',,'os2environment')=1 then   urlrealm=word(accprivs,1)
  374.   end
  375.  
  376. /* Note: access is checked for all request (checked above for public_Urls)
  377.    istat=0 for all non-matched urls */
  378.  
  379. /* should we disallow */
  380.   ok1=0
  381.   if wordpos('SUPERUSER',privset)>0 then ok1=1
  382.   if ok1=0 then do
  383.     select
  384.       when allow_access="YES" | allow_access="YES_NOCHECK"  then
  385.         ok1=1
  386.       when allow_access="INHOUSE" & isinhouse=1 then
  387.         ok1=1
  388.       otherwise
  389.         if istat<>0 then DO      /* if istat=0, then sref_ask_auth below */
  390. /* add own-resource privilege? */
  391.            addreso=get_value('ADD_RESOURCE_NAME')
  392.            if addreso=1 theN DO
  393.              PARSE UPPER VAR SELORIGINAL ACTION '?' .
  394.              accprivs=accprivs||' '||action
  395.            end
  396.            ok1=check_privs(privset,accprivs)
  397.          end
  398.     end
  399.   end
  400.  
  401.   reqprivs=accprivs             /* used by sreproxy, via srefgos */
  402.   if reqprivs='' then reqprivs='*'
  403.  
  404. /* if ACCESS to this url not permitted, let client try "another" user name,
  405.   OR send a response file */
  406.  
  407.  if ok1=0 then do               /* not okay -- ask authorization? */
  408.  
  409.      access_fail_file=get_value('ACCESS_FAIL_FILE')
  410.      if access_fail_file=0 | access_fail_file=-1 | access_fail_file=' ' then do
  411.            afail_file=access_Fail_file  /* -1 and 0 suppress access fail file */
  412.      end
  413.      else do
  414.         if access_fail_file<>1 then
  415.             if afail_file=' ' | afail_file=0 then afail_file=access_fail_file
  416.      end
  417.      if afail_File=1 | afail_file=' ' then afail_file=0   /* 1 in access_fail_file -- if no specific fail file, use auth */
  418.      select 
  419.        when afail_file=0 then  do  /*       just ask authoriaztion */ 
  420.           response_status=sref_ask_auth(the_realm,urlrealm,servername,isstale)  
  421.        end
  422.        when afail_file=-1 then do           /* terse denial */
  423.              response_status=sref_response('unauth','Access denied',servername)  /* flat out denial */
  424.        end
  425.        otherwise do                     /* access fail file */
  426.          brealm=the_realm                                    
  427.          if urlrealm<>' ' & urlrealm<>0 then brealm=urlrealm 
  428.          awebmaster=get_value('WEBMASTER')
  429.          response_status=sref_fail(servername,seloriginal,afail_file,verbose,brealm,'access failure',awebmaster, ,
  430.            'No access privileges to this resource',1,  force_auth,the_realm,urlrealm,myqueue,tempfile)
  431.       end
  432.      end
  433.      signal do_post_filter
  434.   end
  435.  
  436. /* if here, access  privileges were satisfied */
  437.  
  438. /* 6a) lookup/set permissions for this url */
  439. call lookup_permissions
  440.  
  441. /* 6b) get advanced options */
  442. call get_adv_opts   /* get advanced options */
  443.  
  444. /* check for encryption advanced option */
  445. if enable_encryption<>0 then do
  446.    is_encrypt=sref_adv_opts_encrypt(is_encrypt,adv_opts,default_encryption)
  447. end
  448.  
  449. /* 6c - if encryption required, check for appropriate privileges */
  450. /* if is_encrypt on of the encrypts, then a 
  451.    ?ENCRYPT "secret permission" MUST be available for this user */
  452. epwd=''
  453.  
  454. if wordpos(is_encrypt,enctypes)>0 then do
  455.   do mm=1 to words(privset_secret)
  456.      fwrd=translate(strip(word(privset_secret,mm)))
  457.      if abbrev(fwrd,'ENCRYPT:')=0 then iterate
  458.      parse var fwrd . ':' epwd ; epwd=strip(epwd)
  459.      is_encrypt=is_encrypt':'epwd
  460.      if enable_encryption>1 then
  461.            foo=sref_value('ENCRYPT',is_encrypt,'REQ',reqnum,,enmadd)
  462.      leave
  463.   end
  464.   if epwd='' then do /* no permission, ask for username */
  465.      response_status=sref_ask_auth(the_realm,urlrealm,servername)  
  466.      SIGNAL DO_POST_FILTER
  467.   end
  468. end
  469.  
  470. /* 7) call prefilter */
  471. /* call a pre-filter (it might EXIT back to GoServe) */
  472. if pre_filter="YES" then do             /* if FIRST, then prefilter was called BEFORE logon */
  473.     prefilter_result=do_prefiltr(privsetboth)
  474.     parse var prefilter_result status ',' prefilter_result
  475.     a=done_it(status,"Pre-filter processed: "||prefilter_result)
  476.     if a=1 then do
  477.           signal do_post_filter
  478.     end
  479. end
  480.  
  481. /* 8) do aliases */
  482.  
  483. /*  8a) is it for the  DEFAULT "home page" 
  484.         (relative to datadir, No virtual directory  lookups! */
  485.  
  486.  if sel=' '  then do
  487.       sel=sref_get_default(default,ddir,verbose,myqueue) /* always relative to datadir */
  488.       selrec='DEFAULT='||sel
  489.       got_def=1
  490.  end
  491.  else do
  492.    if substr(sel,1,1)='?' then do   /* simple, or with options */
  493.        sel=sref_get_default(default,ddir,verbose,myqueue)||sel   /* default MUST be an HTML document  */
  494.        selrec='DEFAULT='||sel
  495.        got_def=1
  496.    end
  497.  end
  498.  
  499. /* check for redirection DEFAULT  */
  500. if got_def=1 & abbrev(upper(sel),'HTTP://')=1 then do
  501.     dog=isa_move(sel,servername,serverport)
  502.     if dog<>0 then do
  503.        signal do_post_filter
  504.     end
  505. end
  506.  
  507. /* 8b) Now see if the ACTION is really an alias for some other action */
  508.  
  509.  
  510. do_alias: nop                           /* jump here if public_url */
  511.  
  512. if check_alias<>0 then do      /*see if 'action' is an alias for something else*/
  513.   if realm.!rule<>' 'then do            /* use realm info */
  514.       if realm.!alias=0 then
  515.          aline=0
  516.       else
  517.          aline='1 'realm.!alias
  518.   end
  519.   else do
  520.      aline=wait_queue('ALIAS',seloriginal)
  521.   end
  522.  
  523.   parse var aline istat newsel
  524.   if istat>0 then do
  525.      sel=strip(newsel)
  526.      if verbose>1 then foo=pmprintf_sref(" Alias #  resolves to: " sel,,port)
  527.      is_alias=1
  528.   end
  529.  
  530. /* 8c) redirection? or absolute file */
  531.   if is_alias=1 then do
  532.     dog=isa_move(sel,servername,serverport)
  533.     if dog<>0 then do
  534.        signal do_post_filter
  535.     end
  536.  
  537. /* 8d) is this a "send non-data directory file" action (OBSOLETE, use of virtual directories recommended)*/
  538.     if abbrev(upper(sel),"!TRANSFER=")=1 then do
  539.       parse var sel action '?' awords
  540.       response_status=SREF_send_non_datadir(upper(action),,
  541.                              tempfile,verbose,transaction,servername,host_nickname,,
  542.                              specific_mime,advopt_mime)
  543.       signal do_post_filter
  544.    end
  545.  
  546. /* 8e) TCN? */
  547.     if abbrev(upper(sel),"!NEG")=1 then do
  548.  
  549.         negstuff=sref_do_negotiate(seloriginal,verbose,enmadd,home_dir,servername, ,
  550.                             host_nickname,ddir,home_dir,transaction,,
  551.                             tempfile,sel,is_public,protocol,semqueue)
  552.         if negstuff=0 then do     
  553.            response_status= not_found_response(seloriginal,' Variant list not found ',' ')
  554.            selrec=' '
  555.            signal do_post_filter
  556.         end
  557.         if negstuff=-1 then do  /* could not resolve; response handled in sref_negotiate */
  558.            signal do_post_filter
  559.         end
  560.  
  561. /* otherwise, first line is the negotiated "sel", then mimetype,
  562.   remaining lines are new headers */
  563.         parse var negstuff sel '0d0a'x advopt_mime '0d0a'x vlv '0d0a'x ,
  564.                            varylist '0d0a'x alternates '0d0a'x reqheads
  565.         contentloc=sel
  566.         doingneg=1
  567.         adv_opts=adv_opts||'0d0a'x||strip(reqheads)
  568.  
  569. /* but-- check to see if this is a negotiable resource */
  570.         foo=wait_queue('ALIAS',sel)
  571.         parse upper var foo .  aa .
  572.         if strip(aa)='!NEGOTIATE' then do       /* 506 error */
  573.             response_status=sref_response('alsonegotiates', 'The selected variant of a negotiable resource is another negotiable resource',servername)
  574.             signal do_post_filter
  575.         end        
  576.      end                /* !negotiate */
  577.    end          /* isalias=1 */
  578. end             /* checkalias */
  579.  
  580. /* 9) See if a "home_dir" flag (a ~) is present.  If so, replace it */
  581. parse var sel action '?' awords
  582.  
  583.  
  584. foo1=pos('~',action)
  585. if foo1>0 then do            /* do ~ for home_dir replacement, with $ option */
  586.   action=sref_home_dir(action,home_dir)
  587.   action=strip(action,'l','/')
  588. end
  589. if pos('?',sel)>0 then
  590.     sel=action||'?'||awords
  591.  else
  592.      sel=action
  593.  
  594. /*  The next stuff is for GET & HEAD requests (non cgi, non addon) only, so skip otherwise */
  595. if (verb<>"GET" & verb<>'HEAD') | left(sel,1)="!" then signal do_verb
  596. if pos("CGI-BIN/",upper(sel))>0  | pos('?',sel)>0 then signal do_verb
  597.  
  598. /* 10) Check sel to see if it's a /xx/yyy/ or /xx/yyy selector. */
  599. /*     (only valid for get/head, non-cgi requests */
  600.  
  601.  
  602.  
  603. sel=strip(sel)
  604. selautoname=sel   /* may need to reset sel (see GET & HEAD verb processing below) */
  605.  
  606. /* 10a: /xxx/yyy */
  607. noexttype=upper(get_value('NOEXT_TYPE'))
  608. if noexttype<>"NONE" & right(sel,1)<>'/' then  do         /* it doesn't end with a / */
  609.    if lastpos('.',sel) <= lastpos('/',sel) then  auto_name_type=1  /* and has no extension */
  610. end
  611.  
  612. /* 10b) /XXX/yyy/ */
  613. if right(sel,1)='/' then  auto_name_type=2
  614.  
  615. if auto_name_type>0 & pos('*',sel)>0 & wild_sels_okay>0 then auto_name_type=0
  616.  
  617. goautoname:             /* hop here if no match, sel ends with / or noextension */
  618.  
  619. /* 10c) gin up a selector if /xxx/yyy/ or /xxx/yy 
  620.        we may loop here several times, but eventually
  621.        the auto_names or noextype list will be exhausted */
  622.  
  623. if auto_name_type=2 then do           /* xx/yy/ */
  624.    SEL=SELAUTONAME
  625.    parse var auto_name auto_name1 auto_name
  626.    sel=try_auto_name(sel,auto_name1)
  627.    if auto_name='' then auto_name_type=0        /* no more to check */
  628. end
  629.  
  630. if auto_name_type=1 then do        /* /xxx/yyy */
  631.   SEL=SELAUTONAME
  632.   parse var noexttype noexttype1 noexttype   /* pluck off first word */
  633.   sel=sref_fix_url_ext(sel,noexttype1,verbose)
  634.   if sel=-1 then do           /* A REDIRECT */
  635.        suse=selautoname
  636.        if pos('~',seloriginal)>0 then suse=seloriginal
  637.        foo=isa_move('!MOVED '||suse'/',servername,serverport)
  638.        signal do_post_filter
  639.    end
  640.    if noextype='' then auto_name_type=0        /* no more to check */
  641. end
  642.  
  643. /* jump here to avoid some GET/HEAD (non cgi, non xx?ZZ) specific stuff */
  644. do_verb:   nop   
  645.  
  646. /* 11) first: do some advanced options (EXEC and mimetype */
  647.  
  648. if adv_opts<>' ' then do
  649.    tdir=get_value('TEMPFILE_DIR',0)
  650.    gotit=sref_adv_opts_exec(adv_opts,source,request0,seloriginal,privsetboth,verbose, ,
  651.                             servername,host_nickname,ddir,home_dir,tdir)
  652.    if gotit<>0 then do
  653.         response_status=gotit
  654.         signal do_post_filter
  655.    end
  656.    if doingneg<>1 then advopt_mime=sref_adv_opts_mimetype(adv_opts)
  657. end
  658.  
  659. /* ---------- Process the method (PUT, DELETE, GET,POST, or HEAD) ----------- */
  660.  
  661. do_verb2:    /* jump here on "directory specific not_found_url" */
  662.  
  663. /* parse ?xx stuff out */
  664. parse var sel action '?' awords
  665.  
  666. /* .... Now carry out supported verbs (GET POST HEAD PuT DELETE ), or SPECIAL control */
  667. /*   -- and check for cgi_bin calls  -- and check for imagemap calls*/
  668.  
  669.  
  670. /* 12a)server side imagemap call ? */
  671. if awords<>' ' & never_imagemaps<>1 then do               /*possible mapimage call */
  672.   RRES=SREF_ISMAP_IMAGE(,AWORDS,ACTION,NCSA_ISMAP,CERN_ISMAP,  ,
  673.                         servername, serverport,tempfile,Ddir,max_pointdist,verbose)
  674.   IF ABBREV(RRES,'*!*')=1 THEN DO               /* FIRST STEP, DO VIRTUAL FILE HERE */
  675.       mapfile=do_virtual_file(Ddir,SUBSTR(RRES,4),0,1,'!HTML')
  676.       MAX_POINTDIST=get_VALUE('MAX_POINTDIST')
  677.       RRES=SREF_ISMAP_IMAGE(MAPFILE,AWORDS,ACTION,NCSA_ISMAP,CERN_ISMAP,  ,
  678.                         servername, serverport,tempfile,Ddir,max_pointdist,verbose)
  679.   END
  680.   IF RRES<>"" THEN DO
  681.       PARSE VAR RRES RESPONSE_STATUS ',' POST_FILTER_MESSSAGE
  682.       signal do_post_filter
  683.   END
  684. END
  685.  
  686. /* 12b -- is it cgi ? */
  687. cgi_bin_dir=STRIP(get_value('CGI_BIN_DIR',0))
  688. ORIG_CBD=cgi_bin_dir
  689. tsel=strip(upper(sel))
  690. foobao=pos('CGI-BIN/',tsel)
  691. if  (foobao>0) & (cgi_bin_dir<>0)   & (verb="GET" | verb="POST") then do
  692.   parse var tsel a1 "?" .               /* double check */
  693.   if pos('CGI-BIN/',a1)>0 then do
  694.     call process_cgi                    /* process as  cgi */
  695.     if result<0 then signal do_verb2   /*  jump to selnotfound */
  696.     signal  do_post_filter
  697.   end
  698. end
  699.  
  700. /* 12c) special requests */
  701. if left(sel,1)='!' then do
  702.   call do_a_special 
  703.   signal do_post_filter
  704. end
  705.  
  706.  
  707. /*  Process the VERB
  708.   Currently supported verbs:
  709.      HEAD: If auto_header, will also parse html file for header instructions
  710.      GET: Several variants: file transfer, file with ssi, ssp
  711.      POST: ssp
  712.      PUT: write a file (given permission exists)
  713.      DELETE: delete a file (given permission exists)
  714.      TRACE and OPTIONS
  715. In all cases, the url is mapped to a particular file using the
  716. virtual directory feature (or the data directory if no virtual
  717. directory matches the requested url).
  718.  
  719.  
  720.    ********************/
  721.  
  722. select
  723.  
  724. /* 13) Head Requests --- NO LONGER SUPPORTED SEPERATELY -- TREAT AS A GET, AND
  725.        LET GOSERVE SUPPRESS ENTITY BODY 
  726.  when verb='HEAD' then do
  727.     call process_head 
  728.     if result=1 then signal goautoname
  729.  end
  730. ****************** */
  731.  
  732.  
  733. /* 14) GET requests (or a "selector not found" response */
  734.  when verb="GET" | verb="HEAD" | selnotfound<>"" then do
  735.  
  736. /* There are 4 classes of GET requests supported:
  737.    1) Simple file name  eg;  /ZIPFIP/ZIPFIP.HTM:
  738.        file is retrived, with possible ssi's
  739.     2) File name with OPTIONS, eg; /OVERVIEW.HTM?From+ZIPFIP+main+page
  740.         File is retrieved, with possible ssi's (some of which may use these OPTIONS
  741.     3) Form name with parameters, eg; /CALC/DOCALC?12-34%2B51
  742.          sref_getpost is called with appropriate argumen
  743.     4) SPECIAL: if selnotfound<>'', then we are here
  744.        because a special "not found url" has been invoked -- due to
  745.        the original selector failing to yield an existing file (or addon).
  746.  
  747.     Note: ISINDEX type searchable-index requests are identical in
  748.            appearance to case 2.  To avoid this problem, use the alias_file
  749.            mechanism (described above) to convert to a class 3
  750.            ( "form name" SEL) that requests DOSEARCH
  751.  
  752. */
  753.     parse var sel action '?' awords
  754.     action=TRANSLATE(strip(action))   
  755.  
  756. /* 14a) Type of GET */
  757.     if  pos('?',sel)=0 then do          /* no argument list, must be case 1 */
  758.           jcase=1
  759.     end
  760.     else do                   /*arguments, class 2,3, or 4 */
  761.          attype=strip(mediatype(action))
  762.          if abbrev(upper(attype),'TEXT')=1  & pos('.CMD',upper(action))=0 then
  763.              jcase=2            /* class 2: html with "OPTIONS" */
  764.          else 
  765.              jcase=3              
  766.     end      /* dtermine jcase */
  767.  
  768.  
  769. /* 14b) File transfer (perhaps html with ?options */ 
  770.     if jcase < 3 then  do            /* generic file,  or html with options */
  771.  
  772.        if selnotfound="" then  do    /* selnotfound="" means it's inactive */
  773.            file=do_virtual_file(ddir,action,1,1,'!HTML')  /* get local or remote virtual file */
  774.            if verbose>3 then foo=pmprintf_sref("SRE-http: using file= "file)
  775.            if abbrev(file,'!DIR?')=1 then do
  776.               wow=isa_move('!TEMP '||file,servername,serverport)
  777.               signal do_post_filter
  778.            end
  779.        end
  780.        else  do           
  781.            file=selnotfound     /* use previously determined "selector not found"  file */
  782.        end
  783.        used_file=file
  784.  
  785.  
  786. /* 14c) check htaccess rights */     
  787.        if do_htaccess=1   & file<>0 & selnotfound="" then do
  788.             quick_run=0
  789.             tmp1=sref_htaccess(seloriginal,file_nocheck,htaccess_file,who,clientname0, ,
  790.                                whoport,port,ddir,SERVERNAME,TEMPFILE,0)
  791.             if tmp1=-1 then do
  792.                  response_status='401 - '
  793.                  signal do_post_filter
  794.              end
  795.              parse var tmp1  qca ',' file0  ',' nopostf
  796.              file0=strip(file0) ;qca=strip(qca)
  797.              if file0<>0 & auto_name_type=2 & first_ht_auto=1 then  auto_name=file0
  798.              first_ht_auto=0
  799.              if qca=0 then is_public=0   /* htaccess rights were needed, so no caching */
  800.              if strip(nopostf)=1 then no_postfilter=1
  801.         end             /* do_htaccess if */
  802.  
  803. /*  14d) No match. Try again? */
  804.  
  805.        if file=0  then DO  /* no such file/dir */
  806.  
  807.          if auto_name_type<>0  then  signal goautoname /* try another  defaults */
  808.          if selnotfound="" then do      /* not found already tried? */
  809.              selnotfound=sref_not_found_local(seloriginal,not_found_url, ,
  810.                             ddir,enmadd,transaction,home_dir,host_nickname)
  811.          end
  812.          else do
  813.              selnotfound=0      /* =0 means "don't try selnotfound again */
  814.          end
  815.          if selnotfound<>0 then do   /* try using the "not found URL" selector */
  816.              sel=not_found_Url
  817.              if awords<>'' then sel=sel'?'awords
  818.              verb='GET'
  819.              signal do_verb2
  820.          end                /* else, no selnotfound to use */
  821.          response_status=  not_found_response(seloriginal,' <tt>'seloriginal'</tt> could not be found ',not_found_url)
  822.          selrec=' '
  823.          signal do_post_filter
  824.        end              /* file=0 if */
  825.  
  826. /* 14e) File exists! determine mime type  */
  827.        atype=mediatype(file)
  828.  
  829. /* 14f) Non html file (possibly byte range), or html (with possible ssis */
  830.  
  831.       if atype<>'text/html' then 
  832.           call process_non_html
  833.        else 
  834.           call process_html      
  835.  
  836.        signal do_post_filter
  837.  
  838.     end                 /* jcase < 3 */
  839.  
  840. /* 14g) jcase=3, an sre addon */
  841.  
  842. /* first, is ssp not allowed ? */
  843.     if no_processing=1 then do
  844.           response_status=sref_response('unauth',' Server side processing privileges not granted for: '||action,servername)
  845.           signal do_post_filter
  846.     end
  847.  
  848. /* 14H) ssp is allowed ...*/
  849.     usedfile=' '
  850.     addon_dir=get_value('ADDON_DIR',0)
  851.    if quick_run=1  then do  /* expedited execution */
  852.           head_to_get=value('SREF_HEAD_TO_GET',,'os2environment')
  853.           rr=sref_quick_run(verb,ddir,tempfile,action,awords, ,
  854.           uri,who,servdir,workdir,privsetboth ,,
  855.           transaction,enmadd,verbose,servername,host_nickname,home_dir,head_to_get)
  856.           if rr=0 then quick_run=0
  857.    end
  858.    if quick_run=0  then do      /* not a "quick run (or quick run failed */
  859.        averb='GET'
  860.        head_to_get=value('SREF_HEAD_TO_GET',,'os2environment')
  861.        if averb='HEAD' and head_to_get=1 then averb='GET'
  862.        if moreinfo<>'' & no_postfilter=1 then           /* might be needed */
  863.            foo=sref_value('NO_POSTFILTER',1,'REQ',reqnum,,enmadd)
  864.  
  865.     if dodebug=1 then 
  866.         say '!DEB:MA2 '||left(transaction,5)' 'left(time('l'),11)' pre getpost'
  867.        if vlv>0 then do
  868.           oo=sref_value('_VLV',vlv,'REQ')
  869.           varylist=varylist||'0d0a'x||'Tcn: choice'
  870.           oo=sref_value('_VARYLIST',varylist,'REQ')
  871.           oo=sref_value('_ALTERNATES',alternates,'REQ')
  872.           oo=sref_value('_CONTENTLOC',contentloc,'REQ') 
  873.        end
  874.        got1=sref_getpost(tempfile,ACTION' , 'seloriginal,awords,averb' 'is_encrypt' 'RANGE_STUFF,uri,,
  875.                         who,servdir,addon_dir,ddir, ,
  876.                         privsetboth,enmadd,transaction' 'reqnum,verbose,serverport,home_dir, ,
  877.                         servername,host_nickname,do_htaccess,htaccess_file,mysem||' 'myqueue)
  878.    end
  879.    pod1=word(got1,1)
  880.  
  881. /* 14I) addon not found? */
  882.    if pod1="!NOTFOUND" then do
  883.           if selnotfound="" then        /* avoid inifinite lloooop */
  884.              selnotfound=sref_not_found_local(seloriginal,not_found_url, ,
  885.                       addon_dir,enmadd,transaction,home_dir,host_nickname)
  886.           else
  887.              selnotfound=0
  888.  
  889.           if selnotfound<>0 then do
  890.               verb="GET"
  891.               sel=not_found_url
  892.               signal do_verb2
  893.           end
  894.           else do          /* no notfound document, use default */
  895.             response_status= not_found_response(seloriginal,' addon  not found ',' ')
  896.             selrec=' '
  897.             signal do_post_filter
  898.           end
  899.    end
  900.  
  901. /*14J) addon was found */
  902.    if datatype(pod1)="NUM" then do      /* it's the response status */
  903.        response_status=subword(got1,1,2)
  904.        got1=subword(got1,3)
  905.    end
  906.    POD=LASTPOS(',',GOT1)
  907.    IF POD>0 THEN DO
  908.               USED_FILE=SUBSTR(GOT1,POD+1)
  909.               used_file=strip(used_file)
  910.              GOT1=DELSTR(GOT1,POD)
  911.    END
  912.    used_file=strip(used_file)
  913.    fpp=stream(tempfile,'c','close')
  914.    signal do_post_filter
  915.  
  916.  end                   /* verb= get */
  917.  
  918. /* 15) POST */
  919.  when verb="POST" Then do
  920.     if no_processing=1 then do
  921.          response_status=sref_response('unauth',' Server side processing privileges not granted for: '||action,servername)
  922.          signal do_post_filter
  923.      end
  924.  
  925.     drop awords
  926.  
  927.     foo0=sref_GET_BODY(servername)              
  928.     parse var foo0 foo ',' awords
  929.  
  930.     ijump=1
  931.     SELECT 
  932.       WHEN foo=3 | foo<0 then nop  /* some kind of error */
  933.       WHEN FOO=1 THEN DO
  934.          response_status=sref_response(' 501 Unimplemented','501 unimplemented',servername,1)
  935.       END
  936.       WHEN FOO=2 THEN DO
  937.          response_status=sref_response('415 Unsupported Media Type','415 unsupported media type',servername,1)
  938.       END
  939.       OTHERWISE ijump=0
  940.     end
  941.     if ijump=1 then do
  942.        clientname0=who
  943.        signal do_post_filter
  944.     end
  945.  
  946. /* if here, got entity body */
  947.     action=TRANSLATE(strip(sel))   /* CAP AND Rid  spaces */
  948.  
  949.     addon_dir=get_value('ADDON_DIR',0)
  950.     if moreinfo<>'' & no_postfilter=1 then           /* might be needed */
  951.            foo=sref_value('NO_POSTFILTER',1,'REQ',reqnum,,enmadd)
  952.  
  953.     got1=sref_getpost(tempfile,ACTION' , 'seloriginal,awords,verb' 'is_encrypt' 'RANGE_STUFF,,
  954.                          uri,who,servdir,addon_dir,ddir, ,
  955.                       privsetboth,enmadd,transaction' 'reqnum,verbose,serverport,home_dir, ,
  956.                      servername,host_nickname,do_htaccess,htaccess_file,mysem||' 'myqueue)
  957.     pod1=word(got1,1)
  958.     if pod1="!NOTFOUND" then do
  959.               if selnotfound="" then        /* avoid inifinite lloooop */
  960.                  selnotfound=sref_not_found_local(seloriginal,not_found_url, ,
  961.                       addon_dir,enmadd,transaction,home_dir,host_nickname)
  962.               else
  963.                  selnotfound=0
  964.               if selnotfound<>0 then do
  965.                 verb="GET"
  966.                 sel=not_found_url
  967.                 signal do_verb2
  968.               end
  969.               else do          /* no notfound document, use default */
  970.                  response_status= not_found_response(seloriginal,' addon  not found ',' ')
  971.                  selrec=' '
  972.                  signal do_post_filter
  973.              end
  974.     end
  975.  
  976.     if datatype(pod1)="NUM" then do      /* it's the response status */
  977.          response_status=subword(got1,1,2)
  978.          got1=subword(got1,3)
  979.     end
  980.     else do
  981.         arf=extract('bytessent')-base_sent
  982.         response_status='201 'arf
  983.     end
  984.     POD=LASTPOS(',',GOT1)
  985.     IF POD>0 THEN DO
  986.          USED_FILE=SUBSTR(GOT1,POD+1)
  987.          used_file=strip(used_file)
  988.          GOT1=DELSTR(GOT1,POD)
  989.          ss=dosdir(used_file,'s')
  990.          if ss<>' ' then  RESPONSE_STATUS='200 '||DOSDIR(USED_FILE,'S')
  991.     END
  992.  
  993.     used_file=strip(used_file)
  994.     signal do_post_filter
  995.  end
  996.  
  997.  when verb="PUT" then do
  998.    put_No_overwrite=value('SREF_PUT_NO_OVERWRITE',,'os2environment')
  999.    parse var sel action '?' .
  1000.    accept_range=get_value('ACCEPT_RANGE')
  1001.    aa=sref_do_put('PUT',ddir,sel,enmadd,transaction,accopts, ,
  1002.        tempfile,home_dir,servername,host_nickname,accept_range, ,
  1003.        do_htaccess,htaccess_file,verbose,put_no_overwrite,protocol)
  1004.    parse var aa aa ',' used_file; aa=strip(aa); used_file=strip(used_file)
  1005.    signal do_post_filter
  1006.  end
  1007.  
  1008.  when verb="DELETE" then do
  1009.     put_No_overwrite=value('SREF_PUT_NO_OVERWRITE',,'os2environment')
  1010.     parse var sel action '?' .
  1011.     accept_range=get_value('ACCEPT_RANGE')
  1012.      aa=sref_do_put('DELETE',ddir,sel,enmadd,transaction,accopts, ,
  1013.             tempfile,home_dir,servername,host_nickname,accept_range, ,
  1014.             do_htaccess,htaccess_file,verbose,put_no_overwrite,protocol)
  1015.     parse var aa aa ',' used_file; aa=strip(aa); used_file=strip(used_file)
  1016.     signal do_post_filter
  1017.  end
  1018.  
  1019.  when verb='TRACE' then do
  1020.     parse var request .  amess .
  1021.     foo=sref_gos('VAR type message/http NOCACHE ',amess)
  1022.  end
  1023.  
  1024.  when verb='OPTIONS' then do
  1025.     parse var request .  amess .
  1026.     amess=strip(amess,,'/')
  1027.     if amess='*' then do
  1028.         adv_opts=adv_opts||crlf||'HEADER ADD Allow: HEAD GET POST PUT DELETE TRACE '
  1029.         amess='Supported options on this server are:  HEAD GET POST PUT DELETE TRACE '
  1030.         foo=sref_gos('VAR type text/plain  'docache ' NAME ', ,
  1031.                      amess,,adv_opts,enmadd,protocol,,,,host_nickname,no_postfilter)
  1032.     end
  1033.     else do
  1034.         foo=sref_response('notimpl','Options not implemented for this resource ',servername)
  1035.     end    
  1036.  end
  1037.  
  1038.  
  1039. /* http extensions not currently supported -- perhaps later */
  1040.  when abbrev(verb,'M-')=1 then do /* an extension */
  1041.        'Response HTTP/1.1 510 Not Extended'
  1042.        'HEADER ADD Expires: 'att
  1043.        'String Server does not support extended http method: 'verb
  1044.    end
  1045.    
  1046.  otherwise DO
  1047.       if VERBOSE>0 then ss= sref_error(" no such verb " verb,1)
  1048.       RESPONSE_STATUS='501 0'
  1049.       foo=sref_response('notimpl','method not implemented',servername)
  1050.       signal do_post_filter
  1051.  END
  1052.  
  1053. end             /* select verb */
  1054.  
  1055. /* =========
  1056.     jump here after completion code -- logging and other post-filter stuff done here.
  1057.   ==========
  1058. */
  1059.  
  1060. do_post_filter:
  1061.  
  1062. if dodebug=1 then do
  1063.   say "!DEB:MA3 "||left(transaction,5)' 'left(time('l'),11)' postfilter'
  1064. end
  1065.  
  1066.  
  1067. if no_postfilter=1 then  exit ' '   /* no post filtering? then exit! */
  1068. post_filter=strip(get_value('POST_FILTER'))
  1069. postfilter_name=get_value('POSTFILTER_NAME')
  1070.  
  1071. /* save some extra stuff to the request specific variables (if a post_filter might
  1072.    use it */
  1073. post_filter=1
  1074. if post_filter=1 then do
  1075.   if pos(',',seloriginal||request)=0 then do
  1076.      foo=sref_value('SOURCE  SEL REQUEST IS_ENCRYPT',source','seloriginal','request','is_encrypt,'REQ',reqnum,,enmadd)
  1077.   end
  1078.   else do
  1079.     foo=sref_value('SOURCE',source,'REQ',reqnum,,enmadd)
  1080.     foo=sref_value('SEL',seloriginal,'REQ',reqnum,,enmadd)
  1081.     foo=sref_value('REQUEST',request,'REQ',reqnum,,enmadd)
  1082.   end
  1083. end
  1084.  
  1085. /* determin the response status */
  1086. IF RESPONSE_STATUS=' '  THEN  do  /* guess at response status */
  1087.     arf=extract('bytessent')-base_sent
  1088.     response_status='200 'arf
  1089. end
  1090.  
  1091. if rc=-7 then response_status=word(response_status,1)  /* premature break -- use bytessent */
  1092. if words(response_status)<2 then do
  1093.   ofo=extract('bytessent')-base_sent
  1094.   response_status=word(response_status,1)||' '||ofo
  1095. end
  1096. if datatype(strip(word(response_status,2)))<>"NUM" then do
  1097.   ofo=extract('bytessent')-base_sent
  1098.   response_status=word(response_status,1)||' '||ofo
  1099. end
  1100.  
  1101.  
  1102. /*check for 400 status */
  1103. are1=strip(word(response_status,1))
  1104. if are1>399 then
  1105.    record_option='NO'
  1106. else
  1107.    record_option=strip(get_value('RECORD_OPTION'))
  1108.  
  1109. /* check for owner suppression */
  1110.  
  1111. call check_owner_suppress
  1112. if is_owner_suppress=1 then do
  1113.        record_option='NO'
  1114.        if verbose>2 then foo=pmprintf_sref(" Not recording OWNER or SUPERUSER request ",,port)
  1115. end
  1116.  
  1117. write_logs=strip(get_value('WRITE_LOGS'))
  1118.  
  1119. if (record_option="NO" & post_filter=0  & write_logs=0) | no_postfilter=1 then do /* nothing to do in post filter */
  1120.     return ' '
  1121. end
  1122.  
  1123. meterdo=0
  1124. if pos('METER',translate(adv_opts))>0 then do  
  1125.   meterdo=reqfield('Meter')
  1126.   if meterdo='' then do
  1127.       meterdo='0/0'
  1128.   end
  1129.   else do
  1130.      parse upper var meterdo . 'COUNT=' meterdo ',' .
  1131.      if meterdo='' then meterdo='0/0'
  1132.   end
  1133. end
  1134.  
  1135. if host_nickname<>''  then 
  1136.    record_all_file=get_value('RECORD_ALL_FILE')
  1137. else
  1138.    record_all_file=get_value('RECORD_ALL_FILE',0)
  1139.  
  1140. post_filter=get_value('POST_FILTER')
  1141.  
  1142. selrec=sref_replacestrg(selrec,',','%2c','ALL')
  1143. request0=sref_replacestrg(request0,',','%2c','ALL')
  1144.  
  1145. browser=' ';authuser=' '
  1146. thereferer=reqfield('referer')
  1147. if write_logs=1 then do
  1148.  
  1149.   if  clientname0=0 then do
  1150.      clientname0=sref_clientname(who,mysem,myqueue,basesem,enmadd,transaction)
  1151.   end
  1152.  
  1153.   browser=reqfield('user-agent')
  1154.   authuser='-'
  1155.   dec=sref_extract_upwd()
  1156.   if dec<>'' then parse upper var dec authuser ':' .      /* split to userid, if basic */
  1157.   
  1158. end
  1159.  
  1160. post_filter_message=response_status
  1161. a=rxqueue('s',enmadd||'POSTF')
  1162. queue  record_option ',' record_all_file ',' post_filter ',' postfilter_name ',' serverport ',' ,
  1163.                  post_filter_message ',' source ',' request0 ',' got_def' 'selrec ',' ,
  1164.                 tempfile2 ','  servername ',' host_nickname ',' used_file ',' who ',' ,
  1165.                 enmadd ',' thereferer ',' reqnum ',' RESPONSE_STATUS ',' write_logs ',' ,
  1166.                 clientname0 ',' authuser ',' browser ',' verbose','privset','privset_secret', 'meterdo
  1167.  
  1168. aa=eventsem_post(basesem||'POSTF')
  1169.  
  1170. return ' '  /* note that postfilter and recorder don't need to tell the filter anything*/
  1171.  
  1172. /******************* END OF MAIN  **************************/
  1173.  
  1174. /***********/
  1175. /* check on owner suppression */
  1176. check_owner_suppress:
  1177. chkowner=get_value('HIT_OWNER_SUPPRESS')
  1178.  
  1179. is_owner_suppress=0
  1180. if chkowner=1 then do
  1181.   if owners=' ' then owners=get_value('Owners')
  1182.   chkowner2=0
  1183.   hit_superuser_suppress=value('SREF_HIT_SUPERUSER_SUPPRESS',,'os2environment')
  1184.   if hit_superuser_suppress=1 then chkowner2=wordpos('SUPERUSER',privset)
  1185.   if wordpos(who,owners)>0 | chkowner2>0 then do
  1186.        is_owner_suppress=1
  1187.   end
  1188. end
  1189. return is_owner_suppress
  1190.  
  1191. /* ------------------------------------- */
  1192. /* subroutine to strip & set !directives. Sets several globals;
  1193.  so call as routine, not procedure  */
  1194.  
  1195. modify_seloriginal:
  1196. force_auth=0
  1197. force_norecord=0
  1198. specific_mime=0
  1199. del_send=0
  1200. quick_run=0
  1201. is_encrypt=0
  1202. range_stuff=''
  1203. no_no_record=value('SREF_NO_NO_RECORD',,'os2environment')
  1204. empty_path_ok=value('SREF_EMPTY_PATH_OK',,'os2environment')
  1205. cgi_bin_pieces=value('SREF_CGI_BIN_PIECES',,'os2environment')
  1206.  
  1207. do forever
  1208.    t1=seloriginal
  1209.    if left(seloriginal,1)<>'!' then return 1
  1210.    foo=sref_modify_seloriginal( ,
  1211.         SELORIGINAL,DEFAULT_ENCRYPTIOn,IS_ENCRYPT,SELREC,FORCE_AUTH,NO_NO_RECORD,,
  1212.        FORCE_NORECORD,SPECIFIC_MIME,DEL_SEND,RANGE_STUFF,QUICK_RUN,,
  1213.        EMPTY_PATH_OK,CGI_BIN_PIECES,uri)
  1214.    parse var foo SELORIGINAL '0d0a'x IS_ENCRYPT '0d0a'x SELREC '0d0a'x ,
  1215.       FORCE_AUTH '0d0a'x ,
  1216.       FORCE_NORECORD '0d0a'x SPECIFIC_MIME '0d0a'x DEL_SEND '0d0a'x ,
  1217.       RANGE_STUFF '0d0a'x QUICK_RUN '0d0ax' ,
  1218.       EMPTY_PATH_OK '0d0a'x CGI_BIN_PIECES
  1219.    if t1=seloriginal then return 1        /* not modified, so done */
  1220. end
  1221.  
  1222.  
  1223. /* ------------------------------------------------ */
  1224. /* routine to get privileges (sets privset global). DOES not get public_privs*/
  1225. get_user_privs:
  1226.   parse arg noadd,noinh
  1227.   privset=privset||' '||check_user_info(who,1,noadd)  /* auth, and possibly add-user, privs */
  1228.  
  1229.  if noinh<>1 then do
  1230.      call goodips(who)  /* is this an inhouse connect - get some privs! */
  1231.      isin=result
  1232.      if isin<>0 then   privset=PRIVSET||' '||inhouse_privs||' '||privset1
  1233.   end
  1234.  
  1235.   RETURN
  1236.  
  1237.  
  1238. /* ----------------------------------------------------------------------- */
  1239. /* Already completed (cache or prefilter. Record it and exit            */
  1240. /* ----------------------------------------------------------------------- */
  1241. done_it:                        /* need globals, so call as routine */
  1242.  parse arg status , amessage
  1243.     issent=0
  1244.     if datatype(status)<>'NUM' then status=0
  1245.     if status=0 then issent=completed()
  1246.     if (issent+status)=0 then return 0   /* otherwise exit */
  1247.  
  1248.     if VERBOSE>1 then foo=pmprintf_sref(" Completed or redirected request: " amessage,,port)
  1249.     parse var sel action '?' awords
  1250.      return 1
  1251.  
  1252.  
  1253. /****************************/
  1254. /* remove repeats, extract secret privileges.
  1255.   This will modify privest, and create privset_secret and privset2 */
  1256. fix_privset:
  1257. p1=''
  1258. secp1=''
  1259. privset=translate(translate(privset,' ',','||'0d0a0900'x))
  1260. do mm=1 to words(privset)
  1261.    aw1=strip(word(privset,mm))
  1262.    if abbrev(aw1,'?')=1 then do
  1263.      aw1=substr(aw1,2)
  1264.      if wordpos(aw1,secp1)=0 then secp1=secp1||aw1||' '
  1265.    end
  1266.    else do
  1267.       if wordpos(aw1,p1)=0 then p1=p1||aw1||' '
  1268.    end
  1269. end
  1270. privset=p1
  1271. privset_secret=secp1
  1272. privsetboth=privset' , 'privset_secret
  1273. return 1
  1274.  
  1275.  
  1276. /******************************************************************************/
  1277. /*-- DO_prefiltr: Call User Written pre-filter(s)                  --**/
  1278. /******************************************************************************/
  1279.  
  1280. do_prefiltr: procedure expose source request0 seloriginal prefilter_name verbose ,
  1281.               transaction servername host_nickname reqnum REALM.
  1282.   parse arg amessage
  1283.   signal off syntax ; signal off error
  1284.   signal on syntax name bad2a
  1285.   signal on error name bad2a
  1286.   foo3=' '
  1287.  
  1288. /* note that results from earilier pre-filters are sent do later ones */
  1289.   do mm=1 to words(prefilter_name)
  1290.       aname=word(prefilter_name,mm)
  1291.       yow='foo3='||aname||'(source,request0,seloriginal,amessage,servername,foo3)'
  1292.       interpret yow
  1293.  
  1294.       if completed() then leave  /* leave if pre-filter handled the request */
  1295.          parse var foo3 status ',' prefilter_result
  1296.          status=strip(status)
  1297.         if status=1 then leave
  1298.   end
  1299.  
  1300. signal off syntax
  1301. signal off error 
  1302. signal on syntax name goterr
  1303. signal on error name goterr
  1304.  
  1305. return foo3
  1306.  
  1307.  
  1308. bad2a:          /* jump here on syntax error */
  1309.  
  1310.   signal off syntax
  1311.   signal off error 
  1312.   cdrr=directory()
  1313.   ss= sref_error(" Error in pre-filter routine "sigl' ' aname'(dir='cdrr,1)
  1314.   signal on syntax name goterr
  1315.   signal on error name goterr
  1316.  
  1317.   return amessage
  1318.  
  1319.  
  1320.  
  1321.  
  1322.  
  1323.  
  1324. /* ----------------------------------------------------------------------- */
  1325. /* NOT_FOUND_RESPONSE: Return "not found" response, use macrospace routine */
  1326. /* ----------------------------------------------------------------------- */
  1327. not_found_response: procedure expose tempfile  verbose  transaction servername host_nickname seloriginal 
  1328.   parse arg request, message , message2 , reqnum   REALM.
  1329. a=sref_not_found_response(request, message , message2,servername,seloriginal)
  1330. return a
  1331.  
  1332.  
  1333. /* ------------------------------------------------------ */
  1334. /* query and wait on helper threads */
  1335. /* ------------------------------------------------------*/
  1336. wait_queue: procedure expose os2e mysem myqueue enmadd basesem  ,
  1337.           mytid verbose  transaction no_virtual servername host_nickname   reqnum  REALM.
  1338. parse arg athread,args,extra1,skipcheck
  1339. athread=strip(athread) ; args=strip(args)
  1340. /* check to see if no need to call queue */
  1341.  
  1342. if skipcheck<>1 then do
  1343.   a1=check_queue_do(athread,enmadd,args,extra1)
  1344.   if istat=1 then do
  1345.      ires=strip(ires)
  1346.      return ires
  1347.   end
  1348. end
  1349.  
  1350. again1t:
  1351.  
  1352. goober=enmadd||athread
  1353.   a=rxqueue('s',goober)
  1354.   queue  transaction ' ' host_nickname ',' myqueue ',' mysem ','  ARGS
  1355.  
  1356.   a=eventsem_reset(mysem)
  1357.   dothread=basesem||athread
  1358.  
  1359.   a=eventsem_post(dothread)
  1360. again2t:
  1361.   a=eventsem_wait(mysem,90000)  /* max wait of 90 seconds */
  1362.  
  1363.   if a<>0 then do
  1364.         ss=sref_error(mytid','athread' A Fatal Semaphore failure: 'a,1)
  1365.         'response HTTP/1.1 503 Service Unavailable'
  1366.         String 'Web server is temporarily busy '
  1367.         exit ' '
  1368.   end
  1369.   a=rxqueue('s',myqueue)
  1370.  
  1371.   parse pull aline
  1372.  
  1373.   PARSE VAR ALINE idnum ',' aline
  1374.   idnum=strip(translate(idnum,' ','000d0a'x));TRANSACTION=STRIP(TRANSACTION)
  1375.   if idnum<>transaction then  do /*wierd error: got someone else's message! */
  1376.       say ' Read odd id from queue 'athread ':' transaction ',' idnum
  1377.       if eventsem_query(mysem)=1 then aa=eventsem_reset(mysem)
  1378.      signal again2t
  1379.   end
  1380.  
  1381.   aline=strip(aline)
  1382.   return aline
  1383.  
  1384.  
  1385. /*-------------------------------------------------*/
  1386. /* - Check auto_name list (ONLY called if xxx/yyy/ type of url) ? */
  1387. /* ---------------------------------*/
  1388. try_auto_name: procedure expose verbose  doing_autodir port   REALM.
  1389. PARSE ARG SEL1,TRYME
  1390. FOO=SREF_TRY_AUTO_NAME(SEL1,TRYME,DOING_AUTODIR)
  1391. PARSE VAR FOO DOING_AUTODIR','SEL1
  1392. if VERBOSE>1 then foo=pmprintf_sref("Trying auto-named sel = " sel1,,port)
  1393. RETURN SEL1
  1394.  
  1395.  
  1396.  
  1397. /***************************************************************************/
  1398. /* ---------- ----------------------- ----------*/
  1399. /* LOGON checking. If no user match, requery client*/
  1400. /* -----------------------------------------------------------------------*/
  1401.  
  1402. do_logon: procedure expose inhouseips. enmadd os2e the_realm clientname0 isstale  REALM.,
  1403.                    mysem myqueue basesem mytid verbose  transaction no_virtual  reqnum ,
  1404.                    servername host_nickname logon_limit logon_fail_file  user_privs ,
  1405.                    seloriginal force_auth gotauser tempfile who user_logon_proc protocol
  1406.  
  1407.   parse arg anip , inhouse_privs
  1408.  
  1409.   gotauser=1             /* assume success */
  1410. /* see if an inhouseips. */
  1411.   call goodips(anip)
  1412.   if result=1 then do
  1413.      if clientname0=0 then do
  1414.         myname=sref_clientname(who,mysem,myqueue,basesem,enmadd,transaction)
  1415.       end
  1416.       else do
  1417.          myname=clientname0
  1418.       end
  1419.       parse var myname myname1
  1420.       ptmp=inhouse_privs||' '||privset1
  1421.  
  1422.       stuff=check_user_info(who)
  1423.       parse var stuff lstat .
  1424.       if strip(lstat)>=1 then do
  1425.          parse var stuff uu privset2
  1426.          ptmp=ptmp||' '||privset2
  1427.       end
  1428.       return  1 myname1 ptmp
  1429.   end
  1430.  
  1431. /* not inhouse, check if user info available.  */
  1432.   stuff=check_user_info(anip)
  1433.  
  1434.   parse var stuff lstat . ; lstat=strip(lstat)
  1435.  
  1436. /* valid username? return stuff */
  1437.  
  1438.   if lstat >=1 then return   stuff
  1439.  
  1440. /* bad authorizaton type */
  1441.   if lstat=0.2 then do
  1442.      response_status=sref_response('notimplemented','Unknown authorization type',servername)
  1443.      return 0
  1444.   end
  1445.  
  1446. /* time out */
  1447.   if lstat=0.3 then do
  1448.      response_status=sref_response('503 Service Unavailable','Try again, server was busy.',servername,1)
  1449.      return 0
  1450.   end
  1451.  
  1452. /* bad nonce */
  1453.   if lstat=0.4 then do
  1454.      response_status=sref_response('400 Bad Request','The nonce is invalid.',servername,1)
  1455.      return 0
  1456.   end
  1457.  
  1458. /* no such user: either ask again, or send a "failure" response file */
  1459.    gotauser=0
  1460.  
  1461.    if logon_fail_file=0  then do   /* ask again (possibly refresh a stale nonce */
  1462.         return sref_ask_auth(the_realm,,servername,isstale)   /* ask again */
  1463.    end
  1464.  
  1465. /* if here, respond with generic "logon fail file". Note use of amess to
  1466.    differentiate username failure from logon-limit exceeding */
  1467.    awebmaster=get_value('WEBMASTER')
  1468.    if logon_limit >= -lstat | logon_limit=0 then
  1469.         amess="Incorrect username or password "
  1470.    else
  1471.         amess="Too many logon attempts per minute "
  1472.  
  1473. /* LOGON failure */
  1474.    return sref_fail(servername,seloriginal,logon_fail_file,verbose,the_realm,'logon failure', ,
  1475.                    awebmaster,amess,,force_auth, the_realm, urlrealm ,myqueue,tempfile)
  1476.  
  1477.  
  1478. /* ------------------------------------------- */
  1479. /* check request header for auth, return user info if found and valid user
  1480. if privsonly=1, just return privileges (user specific, and possibly "own name"*/
  1481. /* ------------------------------------------- */
  1482.  
  1483. check_user_info: procedure expose mysem myqueue basesem enmadd os2e isstale port  reqnum  REALM.,
  1484.              mytid verbose  transaction no_virtual servername host_nickname user_logon_proc user_privs
  1485. parse arg anip,PRIVSONLY,noadd
  1486. FO=0 ; IF PRIVSONLY=1 THEN FO=""
  1487.  
  1488.   if user_logon_proc<>' ' then do
  1489.      foo=sref_extract_upwd()
  1490.      parse var foo a1 ':' a2 ; username=strip(a1)
  1491.      anarg=a1' 'a2' 'anip
  1492.      yike='stuff='||user_logon_proc||'("'||anarg||'")'
  1493.      interpret yike
  1494.      parse upper var stuff  astat .
  1495.      if astat='X' then user_logon_proc=''
  1496.   end
  1497.  
  1498.   if user_logon_proc='' then do             /* perhaps userLogonProc doesn't handle this*/
  1499.      aad=host_nickname; if aad='' then aad=0
  1500.      stuff=sref_dologon(anip,mysem,myqueue,enmadd,transaction,aad)
  1501.      parse var stuff stuff ','  username ; username=strip(username)
  1502.   end
  1503.  
  1504.   parse var stuff astatus privset1 ; astatus=strip(astatus)
  1505.   if datatype(astatus)<>'NUM' & user_logon_proc<>' ' then do
  1506.        ss=sref_error(" Problem with user logon proc "||user_logon_proc || '('stuff,1)
  1507.        astatus=0
  1508.   end
  1509.  
  1510.   IF verbose>2 THEN foo=pmprintf_sref( " User logon info: "astatus,,port)
  1511.  
  1512.   if astatus=0.1 then isstale=1
  1513.   if astatus<1 then return astatus
  1514.  
  1515.    if noadd<>1 then do
  1516.      addname=get_value('add_user_name')
  1517.      if user<>'*' then do
  1518.        if addname=1 then privset1=privset1||' '||username
  1519.      end
  1520.   end
  1521.  
  1522.   privset1=privset1||' '||get_value(user_Privs)   /* add "user_privs" default "registered user" privileges */
  1523.  
  1524.   IF PRIVSONLY=1 THEN RETURN PRIVSET1
  1525.  
  1526.   return 1 username privset1
  1527.  
  1528.  
  1529.  
  1530.  
  1531. /* -----------------------------------------------------------------------*/
  1532. /* see if ip address matches one of a set of good ips (1 if yes)*/
  1533. /* check for numeric or names ,and check for wildcards */
  1534. /* if non-default host, ONLY get "Host specific" inhouseips */
  1535. /* -----------------------------------------------------------------------*/
  1536. goodips: procedure expose inhouseips. privset1 enmadd os2e verbose  transaction servername host_nickname ,
  1537.                    clientname0 mysem myqueue basesem who  reqnum  REALM.
  1538.  
  1539.  
  1540. parse arg anips
  1541.  
  1542. anips=strip(anips) ;hostn=strip(host_nickname)
  1543.  
  1544. if symbol(inhouseips.0)<>"VAR" then do  /* not been read yet */
  1545.    aa='inhouseips.' ;addit=''
  1546.    if hostN<>"" then addit='.'||hostn
  1547.    nin=0
  1548.    do mm=1 to 10000
  1549.       useme=enmadd||aa||mm||addit ; useme=strip(useme)
  1550.       tt=strip(value(useme,,os2e))
  1551.       if tt="" | tt=0 then leave
  1552.       nin=nin+1 ; inhouseips.nin=upper(tt)
  1553.    end
  1554.    inhouseips.0=nin
  1555. end
  1556.  
  1557. /* check exact matches -- perhaps name matches */
  1558. mdo=inhouseips.0
  1559. do mm=1 to mdo
  1560.   if inhouseips.mm=' '  then iterate
  1561.   if verify(word(inhouseips.mm,1),'*1234567890.')=0 then do  /*a numeric ip */
  1562.      if strip(word(inhouseips.mm,1))=anips then do        /*it's an exact match -- extract privset */
  1563.         parse var inhouseips.mm ff  privset1
  1564.         return 1
  1565.     end
  1566.   end
  1567.   else do                      /* a name ip */
  1568.       if clientname0=0 then 
  1569.             clientname0=sref_clientname(who,mysem,myqueue,basesem,enmadd,transaction)
  1570.       if strip(word(inhouseips.mm,1))=clientname0 then do        /*it's an exact match -- extract privset */
  1571.          parse var inhouseips.mm ff  privset1
  1572.          return 1
  1573.       end
  1574.   end           /* name or number inhouseip */
  1575. end
  1576.  
  1577. /* if here, try wild card matches */
  1578. do m2=1 to mdo           /* wild card matches */
  1579.     imm=sref_wild_Match(anips,inhouseips.m2)
  1580.     if imm=0 & clientname0<>0 then 
  1581.         imm=sref_wild(clientname0,inhouseips.m2)
  1582.     if imm=0 then iterate
  1583.     parse var inhouseips.m2 . privset1
  1584.     return 1
  1585. end
  1586. return 0                /* no match */
  1587.  
  1588.  
  1589. /*--------------------------------------------------*/
  1590. /* check user privileges (privset) against a url specific privilege list (aprivs)
  1591. if one of them matches, return >0 value
  1592. if no match, return 0 */
  1593. /* ----------------------------------------------- */
  1594.  
  1595. check_privs: procedure  expose verbose  transaction servername host_nickname ,
  1596.             who enmadd servdir  reqnum  REALM.
  1597. parse upper arg privset , aprivs
  1598.  
  1599. /* check MUST_HAVE privilegs */
  1600.  
  1601. if pos('&',aprivs)>0 then do
  1602.    musthaves=""
  1603.    oneofs=""
  1604.    do jj=1 to words(aprivs)             /* extrace MUST_HAVE privs */
  1605.         ajj=strip(word(aprivs,jj))
  1606.         if abbrev(ajj,'&')=1 then
  1607.                 musthaves=musthaves||' '||ajj
  1608.         else
  1609.                 oneofs=oneofs||' '||ajj
  1610.    end
  1611.    do jj=1 to words(musthaves)
  1612.         avi=strip(word(musthaves,jj))
  1613.         ajj=strip(avi,'l','&')
  1614.         if wordpos(ajj,privset)=0 then do       /* must have ALL must_have privs */
  1615.             return 0
  1616.         end
  1617.    end
  1618.    aprivs=oneofs
  1619. end
  1620.  
  1621.  
  1622. /* check ONE_OF privileges */
  1623. select
  1624.     when wordpos('SUPERUSER',privset)>0 then
  1625.         return 1
  1626.     when wordpos('NO',aprivs)>0 then do
  1627.         return 0
  1628.     end
  1629.     when aprivs="" | wordpos('*',aprivs)>0 | wordpos('YES',aprivs)>0 then do
  1630.         return 1
  1631.     end
  1632.     otherwise do
  1633.        do mm=1 to words(aprivs)
  1634.           if wordpos(word(aprivs,mm),privset)>0 then do
  1635.                return mm
  1636.           end
  1637.        end
  1638.     end         /* otherwise */
  1639.  end    /* select */
  1640.  
  1641.  return 0
  1642.  
  1643.  
  1644.  
  1645. /* ----------------------------------------------- */
  1646. /* find virtual file name, or perform a remote lookup possibly
  1647. returns
  1648.   file name if local file found (possibly starting with !REMOTE)
  1649.   0 if no success in finding local or remote file (
  1650.  
  1651.   remoteok=1 : allow looking up http:// file (and temporary save to temporary file)
  1652.   if not_f=1, does the "doc not found" to goserve (if 0, does not respond to client)
  1653.   nocheck=1 -- suppress the nochcek (1= do NOT check for the file's existence) */
  1654.  
  1655. /* ----------------------------------------------- */
  1656. do_virtual_file:procedure expose os2e mysem myqueue enmadd basesem  servername serverport tempfile wild_sels_ok realm. ,
  1657.               mytid verbose  transaction no_virtual  host_nickname file_nocheck verbose advopt_mime is_remote  reqnum del_send
  1658.  
  1659. parse arg ddir,sel,remoteok,docheck,limtype
  1660.  
  1661.   crlf='0d0a'x                        /* constants */
  1662.   parse var sel action '?' .
  1663.   if realm.!rule<>'' | del_send=1 then do
  1664.     if realm.!virtual<>0 & del_send=0 then do
  1665.         tt0=strip(translate(action,'\','/'),'l','\')
  1666.         parse var realm.!virtual prefx adir
  1667.         tt0a=substr(tt0,length(prefx)+1)
  1668.         ip1=pos('\',tt0a); ip2=pos('*',adir)
  1669.         if ip1=0 | ip2>0 then do  /* no subdirs, or dir\* */
  1670.             adir=strip(adir,'t','*')
  1671.             file=adir||tt0a
  1672.         end
  1673.         else do     /* is a subdir, and no \* */
  1674.               file=0 /* so not a match */
  1675.         end
  1676.     end 
  1677.     else do            /* no virt, use ddir (or !delsend)  */
  1678.         tt0=strip(translate(action,'\','/'),'l','\')
  1679.         file=strip(translate(ddir,'\','/'),'t','\')||'\'||tt0
  1680.     end
  1681.    end
  1682.    else do
  1683.       file=wait_queue('VIRTUAL',action||' '||ddir||','||limtype)
  1684.    end
  1685.   if file="" | file=0 then return 0
  1686.   if abbrev(upper(file),'HTTP:')=1 then do  /* a remote url */
  1687.       if remoteok<>1 then return 0        /* do not allow remote "virtual directory*/
  1688.       tdir=get_value('TEMPDATA_DIR',0)
  1689.       goo=sref_http_virtual(file,verbose,serverport,tdir)
  1690.       parse var goo tmpf advopt_mime 
  1691.       is_remote=1
  1692.       return tmpf
  1693.     end
  1694.  
  1695.    if pos('*',action)>0 then do     /* request is for a wildcard? */
  1696.       kk=sref_check_wild(file,action,wild_sels_ok,sel,verbose)
  1697.       parse var kk i1','file
  1698.       if i1=2 then return 0
  1699.       if i1=1 then return file
  1700.    end
  1701.  
  1702.    file_Nocheck=file  /* used by htaccess routines */
  1703.    if docheck=1  then do  /* check for file existence */
  1704.         rf=stream(file,'c','query exists')
  1705.         if rf="" then return 0
  1706.    end
  1707.    return file
  1708.  
  1709.  
  1710. /* --------------------------------------------------- */
  1711. /* take care of server side includes
  1712. .  If none (or no_include=yes, or is not shtml?), then return 0 -- which means
  1713. .      "go ahead and return the default document, and maybe cache it? "
  1714. */
  1715. /* --------------------------------------------------- */
  1716.  
  1717. do_includes:procedure expose tempfile yes_ssi no_include os2e enmadd key_preface quick_interp_code quick_replace quick_interp not_ssi,
  1718.           cgi_bin_dir seloriginal privset servdir verbose  transaction ddir ,
  1719.           home_dir servername host_nickname home_name no_processing myqueue adv_opts is_public is_encrypt cache_yes,
  1720.           ssi_extensions who no_interpret_code force_norecord mysem basesem force_auth is_owner_suppress port  reqnum  REALM.
  1721.  
  1722.  parse  arg tfile,sel0,awords,is_remote,range_stuff
  1723.  
  1724.  not_ssi=1
  1725.  
  1726.  if yes_ssi<>1 then do  /* yes_ssi permission overrules everything */
  1727.  
  1728.     if no_include=1 then return 0  /* don't bother, just return original file */
  1729.  
  1730.      ssi_shtml_only=get_value('SSI_SHTML_ONLY')
  1731.  
  1732. /* if shtml mode, check if its an .sht[ml] file */
  1733.     if ssi_shtml_only=1 then do
  1734.        FOO1=LASTPOS('.',sel0)
  1735.        if foo1=0 then return 0                /* no extension! */
  1736.        anext=upper(delstr(sel0,1,foo1))
  1737.        ssi_extensions=value('SREF_SSI_EXTENSIONS',,'os2environment')
  1738.        if wordpos(anext,upper(ssi_extensions))=0 then return 0
  1739.     end
  1740.  end    
  1741. /* else, yes_ssi permssion (so do ssi) */
  1742.  
  1743.  
  1744.  foo=stream(tfile,'c','query exists')
  1745.  if foo=0 | foo="" then do              /*problem opening ! */
  1746.       if VERBOSE>0 then ss=sref_error(" Warning: Could not open file for SSIs : " tfile,verbose-1)
  1747.       return 0          /* just send back file as is */
  1748.  end
  1749.  
  1750.  not_ssi=0
  1751.  
  1752. /* sref_do_includes */
  1753.  
  1754.  tmp1=get_value('SSI_CACHE_ON')
  1755.  ssic=0
  1756.  if tmp1=0 then ssic=1
  1757.  if  force_auth=1 then  ssic=1
  1758.  DIRLIST=SERVDIR||' '||CGI_BIN_DIR||' '||DDIR||' '||HOME_DIR
  1759.  gll=key_preface||' , '||quick_interp||' , '||quick_interp_code||' , '||quick_replace
  1760.  
  1761. /*no22=0; if range_stuff<>'' then no22=1*/
  1762. no22=0
  1763.  
  1764.  gotit=sref_do_ssi(tfile,is_remote,sel0,awords,seloriginal,privset,enmadd, ,
  1765.               DIRLIST,verbose,transaction,tempfile,gll, ,
  1766.               port' 'servername||' '||host_nickname,home_name, ,
  1767.               no_processing||' '||no_interpret_code||' '||force_norecord||' '||is_owner_suppress||' '||no22,,
  1768.               myqueue' 'mysem' 'basesem,who,ssic,adv_opts)
  1769. /*say " pose dossi "*/
  1770.  
  1771. return gotit
  1772.  
  1773.  
  1774. /**********************************************/
  1775. /* check to see if we need NOT call one of the helper threads */
  1776. /**********************************************/
  1777. check_queue_do:procedure expose no_virtual servername host_nickname  myqueue   reqnum 
  1778. parse arg athread,enmadd,args,allow1
  1779. os2e='os2environment'
  1780.  
  1781. select
  1782.   when athread="ALIAS" then do
  1783.      aaa=get_value('SUPPRESS_ALIAS',0)
  1784.      if aaa=1 then do
  1785.            return ' 1  , 0 '|| args
  1786.       end
  1787.   end
  1788.  
  1789.   when athread="PUBURL" then do
  1790.      aaa=get_value('NEVER_PUBLICURLS',0)
  1791.      bbb=get_value('PUBURL_FILE',0)
  1792.      if aaa=1 | bbb='' then do
  1793.            return ' 1  , 0 '
  1794.       end
  1795.      aaa=get_value('SREF_NUM_PURLS',,'os2environment')
  1796.      if aaa=0 then  return ' 1  , 0 '
  1797.   end
  1798.  
  1799.  
  1800.   when athread="USER" then do
  1801.       if get_value('SUPPRESS_USER',0)=1 then do
  1802.           yo=get_value('CHECKLOG')
  1803.           if yo="NO" then
  1804.              return ' 1 , 1 '
  1805.           else
  1806.              return ' 1, 0 '
  1807.       end
  1808.   end
  1809.   when athread="ACCESS" then do
  1810.       if get_value('SUPPRESS_ACCESS',0)=1 then  do
  1811.            return ' 1 , 0 '
  1812.       end
  1813.       if allow1="YES_NOCHECK" then do
  1814.            return ' 1 , 0 '
  1815.       end
  1816.   end
  1817.   when athread="VIRTUAL" then do
  1818.      if no_virtual=0 then  no_virtual=get_value('SUPPRESS_VIRTUAL',0)
  1819.      if no_virtual=1 then do                    /* quick default, if no virtual */
  1820.         parse var args action ddir','limtype
  1821.         t1=strip(strip(translate(ddir,'\','/')),,'\')||'\'
  1822.         action=translate(action,'\','/')
  1823.         action=strip(action,'l','\')
  1824.         tryfile=t1||action
  1825.         return '1 ,'||tryfile
  1826.      end
  1827.   end
  1828.   otherwise DO
  1829.         return' 0 , 0 '
  1830.   END
  1831. end
  1832.  
  1833. RETURN ' 0 ,0'
  1834.  
  1835.  
  1836. /* ------------------*/
  1837. /* see if this parameter applies to this host */
  1838. /* ------------------*/
  1839. check_host: procedure
  1840. parse upper arg thehost,thearg
  1841. f1=strip(word(thearg,1))
  1842. if right(f1,2)<>'//' then return thearg       /* non host specific */
  1843. t1=left(f1,length(f1)-2)
  1844. if thehost=t1 then return strip(delword(thearg,1,1)) /* strip host and return */
  1845.  
  1846. return ' '               /* 0 signifies don't use */
  1847.  
  1848. /* ----------- */
  1849. /* get environment value, possibly host specific
  1850. hname=0 -- do not look under hostname
  1851. hname=1 -- do not look under default
  1852.  */
  1853. /* ------------ */
  1854. get_value: procedure expose enmadd host_nickname  reqnum   REALM.
  1855. parse upper arg vname,hname0
  1856. if hname0=0 then
  1857.         hname=' '
  1858. else
  1859.     hname=strip(host_nickname)
  1860.  
  1861. vname=strip(vname) ;
  1862. if hname<>' ' then do
  1863.    booger=strip(enmadd||vname||'.'||hname)
  1864.    aval=value(booger,,'os2environment')
  1865.    if aval<>' ' | hname0=1 Then
  1866.         return aval
  1867. end
  1868. aval=value(enmadd||vname,,'os2environment')
  1869. return aval
  1870.  
  1871.  
  1872.  
  1873. /* --------------------------------- */
  1874. /* detect a "moved" url (from an alias) -- calls macrospace routine */
  1875. isa_move:procedure expose tempfile verbose   servername  seloriginal myqueue  reqnum  REALM.
  1876. parse arg sel,servername ,serverport
  1877.  
  1878. sel=strip(sel)
  1879. tsel=upper(translate(sel,'/','\')) ;a1=left(tsel,1)
  1880. if a1='!' | a1='H' then do
  1881.    wow=sref_isa_move(tsel,sel,servername,serverport,tempfile,verbose,seloriginal)
  1882.    return wow
  1883. end
  1884. return 0
  1885.  
  1886.  
  1887. /*  Determine MIME type.  Check the most common ones here,
  1888. and if no match, call the more elaboate routine (in macrospace).
  1889. This more elaborate one also will examine mediatyp.rxx 
  1890. If check_type, then use the SREF_CHECK_TYPE procedure if no
  1891. explicit type is available (if an 
  1892. application/octet-stream by sref_mediatype
  1893. Also, use !SENDAS mime type, or advanced options file mime type, if 
  1894. specified
  1895. */
  1896.  
  1897. mediatype:procedure expose specific_mime advopt_mime myqueue  reqnum 
  1898. sm2=specific_mime
  1899.  
  1900. /* if sm2<>0, then use it! */
  1901.  if sm2<>0 then do
  1902.    if abbrev(upper(sm2),'CHECK_')=0 then do
  1903.      aa=translate(sm2,' ','_')
  1904.      m1=strip(word(aa,1)); m2=strip(word(aa,2))
  1905.      foof=m1||'/'||m2
  1906.      return foof
  1907.    end
  1908.  end
  1909.  
  1910. if advopt_mime<>0 then   return advopt_mime
  1911.  
  1912.  
  1913. /* if here, not a mime_subtype */
  1914.  
  1915.  parse arg aval
  1916. /* is it sm2 = check_text? */
  1917. if upper(sm2)='CHECK_TEXT' then do
  1918.    aa=sref_check_type(aval,0)
  1919.    if aa<>0 then return aa
  1920.    sm2=0                /* don't look again */
  1921. end
  1922.  
  1923. /* no check_text, so use file extension */
  1924.  
  1925.   ext=translate(substr(aval, lastpos('.',aval)+1))
  1926.   if wordpos(ext,'HTM HTML SHTML SHTM HTML-INCLUDE ')>0 then
  1927.         return ' text/html'
  1928.   if ext='GIF' then return 'image/gif'
  1929.  
  1930.   bowow=sref_mediatype(aval)  /* not a common default */
  1931.  
  1932.   if upper(bowow)<>'APPLICATION/OCTET-STREAM' then return bowow
  1933.  
  1934.   if upper(sm2)='CHECK_TYPE' then   /* check type? */
  1935.       return sref_check_type(aval,bowow)
  1936.   
  1937.   return bowow          /*not check_type */
  1938.  
  1939.  
  1940.  
  1941. /******/
  1942. /* syntax error */
  1943. goterr:
  1944. IF RC=-7 THEN EXIT ' '  /* if just  a closed connection ,then don't worry */
  1945. LL=SIGL
  1946. glue='SRE-http error at line 'll '(rc= 'rc
  1947.  
  1948. if rxfuncquery('PMPRINTF')=1 then do
  1949.     say glue
  1950. end
  1951. else do
  1952.   if macroquery('sref_error')=' ' then
  1953.     say glue
  1954.   else
  1955.     ss=sref_error(glue,1)
  1956. end
  1957. IF COMPLETED()=0 THEN
  1958.    'var type text/plain name glue'
  1959.  
  1960.  
  1961. exit  ' '
  1962.  
  1963.  
  1964. /******/
  1965. /* failure error */
  1966. goterr2:
  1967. IF RC=-7 | rc=-6 THEN return ' '  /* if just  a closed connection ,then don't worry */
  1968. if rc=-1 | rc=-2 then do
  1969.         'response HTTP/1.1 503 Service Unavailable'
  1970.         'STRING Server is busy: try again in a minute '  /* timed out */
  1971.         return ' '
  1972. end
  1973. if rc=-3 | rc=-4 then return 'String Server failure: too many bytes uploaded '
  1974.  
  1975. foo=sref_error(' SRE-http failure ('rc') at line 'sigl,1)
  1976. if completed()=0 then 'audit SRE-http failure ('rc') at line '||sigl
  1977. string ' Sorry, server failure ('RC') occured at line '||sigl
  1978. exit ' '
  1979.  
  1980.  
  1981.  
  1982. /***************************************************************/
  1983. sref_do_ping:procedure expose gospid transaction 
  1984. parse upper arg asel
  1985. parse var asel '?' opts
  1986. amess=0
  1987. select
  1988.  when opts='' then return  0
  1989.  when opts='CLIENTS' then amess=extract('clients')
  1990.  when opts='PING' then amess='Ping '||gospid
  1991.  when opts='RESPONSETIME' then amess=extract('responsetime')
  1992.  otherwise return 0
  1993. end
  1994. 'HEADER NOAUTO '
  1995. 'RESPONSE HTTP/1.1 200 'amess
  1996. 'STRING !PING on 'transaction
  1997. exit ' '
  1998.  
  1999. /********************************/
  2000. /* check on advanced options */
  2001. get_adv_opts:
  2002. varg=''
  2003. if adv_opts<>" " then do
  2004.       wd=get_value('workdata_dir')
  2005.       foo=strip(wd,'t','\')||'\'||strip(adv_opts)
  2006.       adv_opts_file=stream(foo,'c','query exists')
  2007.       if adv_opts_file="" then do
  2008.          adss= sref_error("Warning: missing advanced options file: " foo " ("seloriginal,1)
  2009.       end
  2010.       else do
  2011.          ll=stream(adv_opts_file,'c','query size')
  2012.          varg=charin(adv_opts_file,1,ll)
  2013.       end
  2014. end
  2015. if adv_opts_2<>'' then do
  2016.   do forever
  2017.     if adv_opts_2='' then leave
  2018.     parse var adv_opts_2 aao '|#|' adv_opts_2
  2019.     if varg='' then
  2020.          varg=aao
  2021.     else
  2022.         varg=varg||'0d0a'x||strip(aao)
  2023.   end
  2024. end
  2025. adv_opts=varg
  2026.  
  2027. return 1
  2028.  
  2029.  
  2030.  
  2031. /*************************************/
  2032. /* see if cgi-bin call (and cgi-bin emulation is on */
  2033. process_cgi:
  2034.  
  2035.   cgipath=""
  2036.  
  2037.   if no_processing=1 then do                /* no processing allowed */
  2038.           response_status=sref_response('unauth',' CGI-BIN processing privileges not granted for: '||sel,servername)
  2039.           fpp=stream(tempfile,'c','close')
  2040.           return 0
  2041.   end
  2042.  
  2043.   if foobao=1 then do                       /* see if alias match */
  2044.            selt=translate(sel,' ','\/?')
  2045.            aline=wait_queue('ALIAS',word(selt,2))
  2046.            parse var aline gotit new_dir
  2047.            if gotit<>0 & new_dir<> "" then do
  2048.                 cgi_bin_dir=strip(translate(new_dir,'\','/'),'t','\')
  2049.            end
  2050.    end
  2051.    else do
  2052.          cgipath=left(sel,foobao-1)
  2053.          cgi_bin_dir=do_virtual_file(cgi_bin_dir,cgipath,0,0,'!CGI-BIN')
  2054.    end
  2055.  
  2056. /* hack to allow use of root directory */
  2057.    if right(cgi_bin_dir,1)=':' then
  2058.         oof=cgi_bin_dir||'\'
  2059.    else
  2060.         oof=strip(cgi_bin_dir,'t','\')
  2061.  
  2062. /* get the cgi-bin relevant portion of the
  2063.    original selector, or it's alias if necessary */
  2064.  
  2065.    useme=uri
  2066.    foobao=pos('CGI-BIN/',upper(uri))        
  2067.    if foobao=0 then do                      
  2068.       useme=sel                             
  2069.       foobao=pos('CGI-BIN/',tsel)           
  2070.    end                                      
  2071.    selcgi=substr(useme,foobao)                 
  2072.  
  2073. /* is there a chance this scriptname exists? */
  2074.    parse var selcgi  ascript '?' .
  2075.    parse var ascript . '/' ascript '/' .  /* the scriptname, with no path info */
  2076.    oof2=strip(oof,'t','\')||'\'||ascript
  2077.    if pos('.',oof2)=0 then oof2=oof2||'.*'
  2078.    goo=dosdir(oof2)
  2079.   
  2080.    if goo="" then do             /* no match (even to wildcard) */
  2081.        if selnotfound="" then        /* avoid inifinite lloooop */
  2082.             selnotfound=sref_not_found_local(seloriginal,not_found_url, ,
  2083.                   orig_cbd,enmadd,transaction,home_dir,host_nickname)
  2084.        else
  2085.           selnotfound=0
  2086.  
  2087.        if selnotfound<>0 then do
  2088.          verb="GET"
  2089.          sel=not_found_url
  2090.          return -1
  2091.        end
  2092.        else do          /* no notfound document, use default */
  2093.          if verb='POST' then do
  2094.              foo=sref_get_body() /* clear input stream */
  2095.          end
  2096.  
  2097.          response_status= not_found_response(seloriginal,' CGI-BIN script not found ',' ')
  2098.          selrec=' '
  2099.          return 0
  2100.        end
  2101.    end
  2102.  
  2103.    tempfile_dir=get_value('TEMPDATA_DIR',0)
  2104.    cmdfile=dostempname(strip(tempfile_dir,'t','\')||'\f?'||space(right(transaction,6),0)||'.cmd')
  2105.    filter_name=sref_version(port)
  2106.  
  2107.    if clientname0=0 then 
  2108.       clientname0=sref_clientname(who,mysem,myqueue,basesem,enmadd,transaction)
  2109.  
  2110.     if moreinfo<>'' & no_postfilter=1 then           /* might be needed */
  2111.        foo=sref_value('NO_POSTFILTER',1,'REQ',reqnum,,enmadd)
  2112.  
  2113. /*note: pipe mode "send as written" cgi is no longer supported */
  2114.  
  2115.    select 
  2116.        when cgi_bin_pieces=2 | cgi_bin_pieces=1 then do  /*  send pieces as available */
  2117.          fix_expire=get_value('FIX_EXPIRE')
  2118.          foox=enmadd' 'transaction' 'home_dir' 'host_nickname','fix_expire' , 'myqueue', 'mysem
  2119.          response_status=sref_docgi_pieces_2(cgi_bin_dir, selcgi, verb, clientname0, filter_name, serverport , ,
  2120.              servername,protocol' http/1.1', ddir, who,tempfile,cmdfile,0,VERBOSE,foox,do_htaccess,htaccess_file,privset,empty_path_ok,servdir)
  2121.        end
  2122.        otherwise do
  2123.           foox=enmadd' 'transaction' 'home_dir' 'host_nickname
  2124.           response_status=sref_docgi(cgi_bin_dir, selcgi, verb, clientname0, filter_name, serverport , ,
  2125.              servername,protocol' http/1.1', ddir, who,tempfile,cmdfile,0,VERBOSE,foox,do_htaccess, ,
  2126.              htaccess_file,privset,empty_path_ok,servdir)
  2127.        end
  2128.  
  2129.  
  2130.  
  2131.   end             /* is a cgi-bin call */
  2132. return 1
  2133.  
  2134.  
  2135.  
  2136. /** END  END END **********************/
  2137.  
  2138.  
  2139. /********************** INITIALIZATION PROCEDURES  ***********************/
  2140.  
  2141. /*********/
  2142. /* initialize SRE. */
  2143. init_sre:
  2144.  
  2145. /*---   Load REXX libraries ----- */
  2146. /* Load up advanced REXX functions */
  2147. foo=rxfuncquery('sysloadfuncs')
  2148. if foo=1 then do
  2149.   call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  2150.   call SysLoadFuncs
  2151. end
  2152. foo=rxfuncquery('rexxlibregister')
  2153. if foo=1 then do
  2154.  call rxfuncadd 'rexxlibregister','rexxlib', 'rexxlibregister'
  2155.  call rexxlibregister
  2156. end
  2157.  
  2158.  
  2159. /* set some parameters */
  2160. enmadd="SREF_"||port||"_"
  2161. basesem='\SEM32\'||enmadd
  2162. os2e='os2environment'
  2163. gospid=dospid()
  2164.  
  2165. /* ---- Do we need to initialize SRE-http ?  --- */
  2166. /* Note: we do not use transaction number, since transaction is NOT reset
  2167.    when the filter is changed.  Hence, the use of this rather convoluted scheme */
  2168. thesem=basesem
  2169. sem_status=eventsem_query(thesem)
  2170. if sem_status<0 then do
  2171.   call pmprintf(' ****** SRE-http started at '||date('n')||' '||time('n'))
  2172.   is_wait=0
  2173.   oo=start_srefilter(thesem,moreargs,port,gospid,enmadd,sem_maxwait)
  2174.   if oo=0 then EXIT ' '
  2175. end
  2176.  
  2177. /* temporary block on ? */
  2178. is_wait=value('SREF_WAIT_FLAG',,'os2environment')
  2179. if is_wait=-2 then do
  2180.   'header add error: Error Starting SRE-http! Restart Goserve, and run PMPRINTF to view error messages'
  2181.   GOO=VALUE('sref_WAIT_FLAG_ERROR',,'OS2ENVIRONMENT')
  2182.  
  2183.   'STRING SRE-http Fatal Error: 'goo
  2184.   'close'
  2185.    exit ' '
  2186. end
  2187. if is_wait=1 then call start_srefilter(1)
  2188.  
  2189. return 1                
  2190.  
  2191.  
  2192.  
  2193. /*****************************/
  2194. /* start srefilter -- or wait for it to finish resetting */
  2195. start_srefilter:procedure expose is_wait key_preface  reqnum  verbose
  2196. if is_wait=1 then do
  2197.   do  while is_wait>0
  2198.      call syssleep 1
  2199.      is_wait1=value('SREF_WAIT_FLAG',,'os2environment')
  2200.      if is_wait1<>'' then is_wait=is_wait1
  2201.   end
  2202.   return 1  /* done waiting, proceed... */
  2203. end
  2204.  
  2205. /* as of 1.3g, call an external proc */
  2206. parse arg thesem,moreargs,port,gospid,enmadd,sem_maxwait      
  2207. jj=sreinit1.cmd(key_preface,reqnum,verbose,thesem,moreargs,port,gospid,enmadd,sem_maxwait)      
  2208. return jj
  2209.  
  2210.  
  2211. /*********************/
  2212. /* get host,datadir, & servername for this requesete */
  2213. get_host_info:procedure expose host_nickname ddir servername uri seloriginal enmadd myaddr  reqnum 
  2214. parse arg protocol
  2215.  
  2216. stuff=sref_host_info(myaddr,enmadd,uri,protocol)
  2217. if strip(stuff)='BAD' then return -1           /* if http/1.1 client did not include at host: header */
  2218.  
  2219. if stuff<>0 then do
  2220.       parse var stuff  servername ',' host_nickname  ',' ddir
  2221.       host_nickname=strip(host_nickname); ddir=strip(ddir)
  2222.       servername=strip(servername)
  2223. end
  2224. else do
  2225.     ddir=datadir()
  2226.     servername=servername()
  2227.     host_nickname=' '
  2228. end
  2229. if abbrev(upper(uri),'HTTP://')>0 then do
  2230.           parse var uri . '//' . '/' uri
  2231.           if uri='' then uri='/'
  2232.           parse var seloriginal . '//'  . '/' seloriginal
  2233. end        
  2234. return 1
  2235.  
  2236.  
  2237. /****************/
  2238. /*  -----------------Tidy up some initialization parameters ------------ */
  2239. tidy_up:
  2240.  
  2241. reqprivs=''
  2242. accprivs=''
  2243. isstale=0
  2244. privset=' '
  2245. owners=' '
  2246. vlv=0           /* varying list verifier */
  2247. is_public=1   /* by default, public cache okay */
  2248. cache_yes=0     /* do not assume a CACHE permissoin, or publicurl*/
  2249. if proxy_cache=0 then is_public=0  /* cache_yes can override proxy_cache */
  2250.  
  2251. if left(seloriginal,1)='!' then do
  2252.    if abbrev(upper(seloriginal),'!SEND')<>1 then is_public=0 /* don't cache special requests */
  2253. end
  2254.  
  2255. is_alias=0
  2256. from_auth=0
  2257. tmp.0=0                 /* for use by INTERPRET blocks */
  2258. crlf='0d0a'x            /* might need this */
  2259. got_def=0
  2260. nopostf=' '
  2261. auto_name_type=0 
  2262. FIRST_HT_AUTO=1
  2263. do_htaccess=0    /* 0=don't do, 1= do htaccess */
  2264. used_file=' '   /* the file this is the target of the request */
  2265. logon_fail_file=0
  2266. access_fail_file=0
  2267. response_status=' '
  2268. serverport=port
  2269. doingneg=0
  2270. is_remote=0
  2271. selnotfound=""          /* used with directory specific not found url */
  2272. advopt_mime=0       /* used with "sel specific mime type */
  2273. doing_autodir=0
  2274. if key_preface="#" then key_preface=0  /* # not allowed as key_preface */
  2275.  
  2276. never_imagemaps=value('SREF_NEVER_IMAGEMAPS',,'os2environment')
  2277. if never_imagemaps<>1 then do
  2278.   ncsa_ismap=value('SREF_NCSA_ISMAP',,'os2environment')
  2279.   cern_ismap=value('SREF_CERN_ISMAP',,'os2environment')
  2280. end
  2281.  
  2282. isinhouse=0
  2283. clientname0=0
  2284.  
  2285. mytid=dostid()
  2286.  
  2287. mysem=thesem||"t"||mytid
  2288. myqueue="SREF_"||port||'_t'||mytid
  2289. servdir=value(enmadd||'SERVDIR',,os2e)
  2290.  
  2291. no_postfilter=0 ; no_virtual=0
  2292.  
  2293. /* if !DELSEND special directive, MUST be under tempfile_dir */
  2294. if del_send=1 then do
  2295.    ddir=get_value('TEMPFILE_DIR',0)
  2296.    if ddir='' then do           /* error, make a note */
  2297.       'RESPONSE HTTP/1.1 405 Method not allowed '
  2298.       'STRING Error: Server does not support !DELSEND '
  2299.       call pmprintf(' ERROR: TEMPFILE_DIR not set (!DELSEND ) ')
  2300.       exit ' '
  2301.    end
  2302. end
  2303.  
  2304. verbose=get_value('VERBOSE')
  2305.  
  2306. if verbose>3 then FOOO=pmprintf_sref(" Using data directory= " ddir' ' seloriginal,,PORT)
  2307.  
  2308. if  VERBOSE>1 & host_nickname<>' ' then
  2309.    FOO=pmprintf_sref(' Request to host: ' host_nicknAME,,PORT)
  2310.  
  2311. tempdata_dir=get_value(tempdata_dir)
  2312.  
  2313. tdir=strip(TEMPDATA_DIR,'t','\')||'\'
  2314. tempfile=tdir'$'mytid'.'port                      /* Used to create temp (response) file */
  2315. tempfile2=tdir'$'reqnum'.'port                      /* For use in postfilter  */
  2316.  
  2317. if stream(tempfile,'c','query exists')<>' ' then  do /* just in case of prior crash?*/
  2318.    if verbose>2 then ss= sref_error(" Warning: old tempfile being removed: " tempfile,1)
  2319.    foo=sysfiledelete(tempfile)
  2320.    if foo<>0 then do
  2321.        if verbose>2 then FOO=pmprintf_sref(' Could not delete old tempfile: 'tempfile',trying 'tempfile2,,PORT)
  2322.       foo=sysfiledelete(tempfile2)
  2323.       tempfile=tempfile2
  2324.    end
  2325. end
  2326.  
  2327. check_alias=get_value('CHECK_ALIAS')
  2328. home_dir=get_value('HOME_DIR')
  2329. htaccess_file=get_value('HTACCESS_FILE')
  2330. do_htaccess=get_value('DO_HTACCESS')
  2331. default=get_value('DEFAULT')
  2332. no_include=get_value('NO_INCLUDE')
  2333. no_processing=get_value('NO_PROCESSING')
  2334. no_interpret_code=get_value('NO_INTERPRET_CODE')
  2335. auto_header=get_value('AUTO_HEADER')
  2336.  
  2337. home_name=get_value('HOME_NAME')
  2338. not_found_url=get_value('NOT_FOUND_URL')
  2339. not_found_url=sref_replacestrg(not_found_url,'HOME_NAME',home_name)
  2340.  
  2341. pre_filter=get_value('PRE_FILTER')
  2342. prefilter_name=get_value('PREFILTER_NAME')
  2343. auto_name=get_value('AUTO_NAME')
  2344.  
  2345. /* clear error-message variable */
  2346. errorvar='SRE_ERROR_'||gospid||'_'||mytid
  2347.  
  2348. /* make personallized queue and semaphore */
  2349. call make_semmi
  2350. base_sent=extract('bytessent')  
  2351.  
  2352. aas='!ERROR= HOST_NICKNAME='host_nickname' SERVERNAME='servername' DATADIR='ddir' IS_ENCRYPT='is_encrypt
  2353. oo=sref_value('!INI',aas,'REQ',reqnum,,enmadd)
  2354.  
  2355. return 1
  2356.  
  2357.  
  2358. /***************/
  2359. /* create a personallized queue & semaphore */
  2360. make_semmi:
  2361. a=rxqueue('s',myqueue)
  2362. noq=1
  2363. signal off syntax ; signal off error
  2364. signal on syntax name badq ; signal on error name badq
  2365. queue 0
  2366. noq=0
  2367. badq:
  2368. signal off syntax ; signal off error
  2369. signal on syntax name goterr
  2370. signal on error name goterr
  2371.  
  2372. if noq=1 then do
  2373.   IF VERBOSE>0 THEN say " creating myqueue " myqueue
  2374.   foo=rxqueue('c',myqueue)
  2375.   if upper(foo)<>upper(myqueue) then say ' wierd queue error ' foo myqueue
  2376.   a=rxqueue('s',myqueue)
  2377. end
  2378. yyq=queued()
  2379. if yyq>100 then do
  2380.   if verbose>1 then say " Killing residual queue " myqueue yyq
  2381.   aa2=rxqueue('d',myqueue)
  2382.   aa2=rxqueue('c',myqueue)
  2383.   aa2=rxqueue('s',myqueue)
  2384.   yyq=queued()
  2385. end
  2386. do mmy=1 to yyq
  2387.     pull poo .
  2388. end
  2389.  
  2390. wow=eventsem_query(mysem)
  2391. if wow=-187 then do
  2392.    a=eventsem_create(mysem)
  2393.    if a=0  then do
  2394.        nop
  2395.   end
  2396.   else do
  2397.      call pmprintf(' Could not create semaphore: 'mysem' , error='a)
  2398.      'response HTTP/1.1 503 Service Unavailable'
  2399.      'STRING Server is Busy. Try again later.'
  2400.      exit ' '
  2401.    end
  2402. end
  2403. foo=eventsem_reset(MYSEM)
  2404. return 1
  2405.  
  2406. /**************************/
  2407. /* add priviliges (called if puburl found */
  2408. add_privs_pub:
  2409.    if  wordpos(who,owners)>0 then  privset=privset||" SUPERUSER INHOUSE "||INHOUSE_PRIVS
  2410.  
  2411.    check_add_privs=get_value('CHECK_ADD_PRIVS')  /* LOOK FOR ADDITIONAL PRIVILEGES? */
  2412.    if check_add_privs=1 then do
  2413.          aprefix=strip(get_value('ADD_PRIVS_PREFIX'))
  2414.          ap2=sref_get_add_privs(host_nickname,who,port,enmadd,tempdata_dir,verbose)
  2415.          ap2=translate(ap2,' ','&')    /* correct entry errors (& for RESOURCE privs only  */
  2416.          do iw=1 to words(ap2)
  2417.             privset=privset||' '||aprefix||strip(word(ap2,iw))
  2418.          end
  2419.  
  2420.    end
  2421.  
  2422.    CALL get_user_privs 0    /* get inhouse, authorization, and own-name privs */
  2423.  
  2424.   if realm.!rule<>' 'then do            /* use realm info */
  2425.       aline='1 , '||realm.!access
  2426.   end
  2427.   else do
  2428.      aline=wait_queue('ACCESS',seloriginal,allow_access)
  2429.   end
  2430.   parse var aline .  ',' . ',' accopts ',' urlrealm ',' . ',' adv_opts ',' adv_opts_2
  2431.  
  2432.   call get_adv_opts   /* get advanced options */
  2433.  
  2434.  if wordpos('NO_POSTFILTER',upper(accopts))>0 then no_postfilter=1
  2435.  
  2436. return 1
  2437.  
  2438.  
  2439. /*****************************************/
  2440. /* add privileges from various sources */
  2441. add_privs_2:
  2442. /* add public_privs to everyone */
  2443.  public_privs=get_value('public_privs')
  2444.  privset=privset||' '||public_privs
  2445.  
  2446. /* add "username " to privset (this step may be redundant, but... ? */
  2447. addname=get_value('add_user_name')
  2448. if addname=1 then do
  2449.   if wordpos(upper(username),upper(privset))=0 then
  2450.        privset=privset||' '||username
  2451. end
  2452.  
  2453. /* check for dynamic privileges ? */
  2454. check_add_privs=get_value('CHECK_ADD_PRIVS')
  2455. if check_add_privs=1 then do
  2456.        aprefix=strip(get_value('ADD_PRIVS_PREFIX'))
  2457.        ap2=sref_get_add_privs(host_nickname,who,port,enmadd,tempdata_dir,verbose)
  2458.        do iw=1 to words(ap2)
  2459.           privset=privset||' '||aprefix||strip(word(ap2,iw))
  2460.        end
  2461.        privset=translate(privset,' ','&')  /* correct entry errors */
  2462. end
  2463.  
  2464. isinhouse=wordpos('INHOUSE',upper(privset))  /* flag for inhouse client */
  2465.  
  2466. if wordpos('SUPERUSER',upper(privset))>0 then do
  2467.    no_processing=0 /* make sure superusrs are unimpeded */
  2468.    no_interpret_code=0
  2469. end
  2470.  
  2471. return 1
  2472.  
  2473. /***********************/
  2474. /* lookup logon parameters */
  2475. get_log_params:
  2476.  
  2477. checklog=get_value('CHECKLOG');if checklog="YES" then checklog="ALWAYS"
  2478. inhouse_privs=get_value('INHOUSE_PRIVS')
  2479. the_realm=get_value('THE_REALM')
  2480. allow_access=get_value('ALLOW_ACCESS') 
  2481. if checklog="INHOUSE" | checklog="ALWAYS" then 
  2482.          dologon=1
  2483. else
  2484.          dologon=0
  2485. return 1
  2486.  
  2487.  
  2488. /*******************************************/
  2489. /* lookup various permissions */
  2490. lookup_permissions:
  2491.  
  2492. /* Now check for ssi and ssp privs */
  2493.  aok=wordpos('NO_SSI',accopts)
  2494.  if aok<>0 then
  2495.           no_include=1
  2496.  
  2497.  yes_ssi=0
  2498.  yes_ssi=wordpos('YES_SSI',accopts)
  2499.  if yes_ssi>0 then yes_ssi=1
  2500.  
  2501.  aok=wordpos('NO_SSP',accopts)
  2502.  if aok<>0  & wordpos('SUPERUSER',privset)=0 then
  2503.        no_processing=1
  2504.  
  2505.  aok=wordpos('NO_CODE',accopts)
  2506.  if aok<>0  & wordpos('SUPERUSER',privset)=0 then
  2507.        no_interpret_code=1
  2508.  
  2509.  
  2510. /* explicitly allow caching? */
  2511.  aok=wordpos('CACHE',accopts)
  2512.  if aok<>0 then  do
  2513.    is_public=1
  2514.    cache_yes=2
  2515.  end
  2516.  
  2517.  aok=wordpos('CACHE*',accopts)
  2518.  if aok<>0 then  do
  2519.      is_public=2 ; cache_yes=1
  2520.  end
  2521.  
  2522.  aok=wordpos('NOCACHE',accopts)   /* nocache trumps cache */
  2523.  if aok<>0 then do
  2524.     is_public=0 
  2525.  end
  2526.  
  2527.  IF IS_PUBLIC=0 THEN CACHE_YES=0
  2528.  
  2529. /* see if suppress alias and/or suppress of this url*/
  2530. if wordpos('NO_ALIAS',accopts)>0 then
  2531.     check_alias=0
  2532. if wordpos('NO_POSTFILTER',accopts)>0 | force_norecord=1 then
  2533.         no_postfilter=1
  2534. if wordpos('NO_VIRTUAL',accopts)>0 then
  2535.         no_virtual=1
  2536. if wordpos('NO_HTACCESS',accopts)>0 then
  2537.        do_htaccess=0
  2538. if wordpos('SUPERUSER',privset)>0 then
  2539.        do_htaccess=0
  2540.  
  2541. if del_send=1 then do  /* del_send has limited "mobility", regardless of cache privilege */
  2542.    cache_yes=0; is_public=0 ; no_virtual=1 ; check_alias=0
  2543. end
  2544.  
  2545. return 1
  2546.  
  2547.  
  2548. /*****************************/
  2549. /* do a special request */
  2550. do_a_special:
  2551.  
  2552.   usel=upper(sel)
  2553.   if abbrev(usel,'!DIR')=1 then do
  2554.       parse var sel action '?' stuff
  2555.       dir_cache_size=value('SREF_DIR_CACHE_SIZE',,'os2environment')
  2556.       dir_cache_duration=value('SREF_DIR_CACHE_DURATION',,'os2environment')
  2557.  
  2558.       response_status=sref_dir(ddir,tempfile,action,stuff,tempdata_dir, ,
  2559.            dir_cache_duration,dir_cache_size,enmadd, ,
  2560.            transaction,verbose,servername,host_nickname,home_dir,privset,doing_autodir,seloriginal,protocol)
  2561.        if response_status=-1 then do
  2562.           response_status=  not_found_response(seloriginal,' the <tt>' stuff' </tt>directory could not be found.',not_found_url)
  2563.        end
  2564.        return 1
  2565.    end
  2566.  
  2567.    if abbrev(usel,'!SSI')=1 then do
  2568.       quick_interp=value("SREF_QUICK_INTERP",,'os2environment')
  2569.       quick_interp_code=value('SREF_QUICK_INTERP_CODE',,'os2environment')
  2570.       quick_replace=value('SREF_QUICK_REPLACE',,'os2environment')
  2571.       parse var sel action '?' args ; args=strip(args)
  2572.       if wordpos('SUPERUSER',upper(privset))+wordpos('CONTROL',upper(privset))=0 then do
  2573.             response_status=sref_ask_auth(the_realm,,servername,isstale)
  2574.        end
  2575.        else do
  2576.          DIRLIST=SERVDIR||' '||CGI_BIN_DIR||' '||DDIR||' '||HOME_DIR
  2577.          call check_owner_suppress 
  2578.          foo=sref_do_ssi('*'||strip(args),0,0,0,seloriginal,privset,enmadd, ,
  2579.                    DIRLIST,verbose,transaction,tempfile, ,
  2580.                   key_preface||' , '||quick_interp||' , '||quick_interp_code||' , '||quick_replace,,
  2581.                    servername||' '||host_nickname,home_name, ,
  2582.                    no_processing||' '||no_interpret_code||' '||force_norecord||' '||is_owner_suppress||' 0 ', ,
  2583.                    myqueue' 'mysem' 'basesem,who)
  2584.        end
  2585.        return 1
  2586.    end
  2587.  
  2588.   if abbrev(usel,'!AUTH')=1 then do
  2589.             response_status=sref_ask_auth('Force_authorization',,servername,isstale)
  2590.             return 1
  2591.   end
  2592.  
  2593. /* otherwise, one of the generic ones */
  2594.    post_filter_message=sref_special_request(sel,privset,the_realm,os2e,enmadd,tempfile)
  2595.    if post_filter_message=-1 then   do  /* !special requests require special privs */
  2596.         response_status=sref_ask_auth(the_realm,,servername,isstale)
  2597.    end
  2598.    if abbrev(post_filter_message,'Unknown') then do
  2599.          response_status=sref_response('badreq', 'asked for unknown Special control "'sel'"',servername)
  2600.    end
  2601.  
  2602. return 1
  2603.  
  2604.  
  2605. /*********************************/
  2606. /* process a non-html file */
  2607. process_non_Html:
  2608.  
  2609. doerase=''
  2610.  
  2611. /* IF HERE, not a byte range request */
  2612. if del_send=1 then do                   /* a "delete after send" rquest */
  2613.     response_status='200 '||dosdir(file,'s')
  2614.     doerase='ERASE'
  2615. end
  2616. else do
  2617.     response_status='200 '||dosdir(file,'s')
  2618. end
  2619.  
  2620. if file<>'' then fooo=stream(file,'c','close')
  2621.  
  2622. okpr=0
  2623. select 
  2624.   WHEN CACHE_YES=1 & IS_PUBLIC=2 THEN DOCACHE='CACHE* MAXAGE 1 '
  2625.   WHEN CACHE_YES=2 & IS_PUBLIC=1 THEN DOCACHE='CACHE'
  2626.   when proxy_cache=0  then docache='NOCACHE*'
  2627.   when selnotfound<>'' then docache='NOCACHE* RESPONSE 404%20Not%20Found'
  2628.   when is_public=0 then docache='NOCACHE'
  2629.   when is_public=2 then docache='CACHE*'
  2630.   otherwise docache=' '
  2631. end
  2632.  
  2633. if del_send<>1 then okpr=get_value('ACCEPT_RANGE')
  2634.  
  2635. if dodebug=1 then   
  2636.   say "!DEB:MA4 "||left(transaction,5)' 'left(time('l'),11)' pre srefgos(nonhtml)'
  2637.  
  2638.  
  2639. filex='"'||file||'"'
  2640.  
  2641. FOO=sref_gos('FILE 'doerase ' type ' atype ' 'docache' NAME" 'filex ' ENCRYPT 'is_encrypt' VLV 'vlv' !RANGE 'range_stuff,, ,
  2642.               okpr,adv_opts, ,
  2643.               enmadd,protocol,,
  2644.               response_status,servername,,host_nickname,no_postfilter,,reqprivs)
  2645.  
  2646.  
  2647. select
  2648.   when (word(foo,1)='200' | word(foo,1)='201') & datatype(word(foo,3))='NUM' then do
  2649.      response_status=word(foo,1)' 'word(foo,3)
  2650.   end
  2651.   when word(foo,1)=206 then do
  2652.      ofo=extract('bytessent')-base_sent
  2653.      RESPONSE_STATUS='206 '||ofo
  2654.    end
  2655.   when abbrev(foo,'2')=0 then do
  2656.      ofo=extract('bytessent')-base_sent
  2657.      response_status=word(foo,1)||' '||ofo 
  2658.   end
  2659.   otherwise nop
  2660. end
  2661.  
  2662. return 1
  2663.  
  2664.  
  2665. /*********************************/
  2666. /* response_s */
  2667. /* process an html file */
  2668. process_html:
  2669.  
  2670. call check_owner_suppress
  2671. NOT_SSI=0
  2672.  
  2673.  
  2674. sxp=' '
  2675.  
  2676. quick_interp=value("SREF_QUICK_INTERP",,'os2environment')
  2677. quick_interp_code=value('SREF_QUICK_INTERP_CODE',,'os2environment')
  2678. quick_replace=value('SREF_QUICK_REPLACE',,'os2environment')
  2679. dofile1=do_includes(file,action,awords,is_remote,no_postfilter,range_stuff)  /* process file for ssis */
  2680. dynfile=''
  2681. parse var dofile1 astat','cfile
  2682. if dodebug=1 then   
  2683.   say "!DEB:MA5 "||left(transaction,5)' 'left(time('l'),11)' pre do_includes'
  2684.  
  2685. parse var astat istat maxage dynfile   /*maxage may be time (if non dynamic ssis')
  2686.                                  or file name (semi-dynamicss                   
  2687.                                  or nothing (if fully dynamic) */
  2688.  
  2689. sxp=' '
  2690. if maxage<>'' & datatype(maxage)='NUM' then  sxp='MAXAGE 'maxage
  2691.  
  2692. aah=0
  2693. if auto_header='ALWAYS' then 
  2694.         aah=1
  2695. if auto_header='HEAD' & verb='HEAD' then
  2696.         aah=2
  2697.  
  2698. okpr=0
  2699. if del_send<>1 then okpr=get_value('ACCEPT_RANGE')
  2700.  
  2701. select 
  2702.   WHEN CACHE_YES=1 & IS_PUBLIC=2 THEN DOCACHE='CACHE* MAXAGE 1 '
  2703.   WHEN CACHE_YES=2 & IS_PUBLIC=1 THEN DOCACHE='CACHE'
  2704.   when proxy_cache=0  then docache='NOCACHE*'
  2705.   when selnotfound<>'' then docache='NOCACHE* RESPONSE 404%20Not%20Found'
  2706.   when is_public=0 then docache='NOCACHE'
  2707.   when is_public=2 then docache='CACHE*'
  2708.   otherwise docache=' '
  2709. end
  2710. doerase=' '
  2711. if del_send=1 then doerase='ERASE'
  2712.  
  2713. /* ISTAT=0:  "no ssis, or not allowed to do ssis" */
  2714. if trunc(istat)=0 then do 
  2715.    doerase=''
  2716.    if del_send=1 then do
  2717.              response_status='200 '||dosdir(file,'s')
  2718.    end
  2719.    else do
  2720.              response_status='200 '||dosdir(file,'s')
  2721.    end
  2722.    if selnotfound<>'' then do
  2723.      response_status='404 '||dosdir(file,'s')
  2724.    end
  2725.  
  2726.    filex='"'||file||'"'
  2727.  
  2728.    foo=sref_gos('FILE 'doerase ' 'sxp' type text/html  'docache ' NAME" 'filex' ENCRYPT 'is_encrypt' VLV 'vlv' !RANGE 'range_stuff,, ,
  2729.                okpr,adv_opts, ,
  2730.               enmadd,protocol,,
  2731.               response_status,servername,aah,host_nickname,no_postfilter,,reqprivs)
  2732.  
  2733.    select
  2734.      when (word(foo,1)=200 | word(foo,1)=201) & datatype(word(foo,3))='NUM' then do
  2735.         response_status=word(foo,1)' 'word(foo,3)
  2736.      end
  2737.      when word(foo,1)=206 then do
  2738.         ofo=extract('bytessent')-base_sent
  2739.         RESPONSE_STATUS='206 '||EXTRACT('BYTESSENT')
  2740.      end
  2741.      when abbrev(foo,'2')=0 then do
  2742.         ofo=extract('bytessent')-base_sent
  2743.         response_status=word(foo,1)||' '||ofo
  2744.      end
  2745.      otherwise nop
  2746.    end
  2747.    if selnotfound<>'' then do
  2748.      response_status='404 '||ofo
  2749.    end
  2750.  
  2751.  
  2752.  
  2753.    IF NOT_SSI=1 & VERBOSE>3 THEN call pmprintf( " HTML file was NOT checked for SSI's: "action)
  2754. end                   /* istat=0 == no ssis in file */
  2755.  
  2756. /* ISTAT=-1 : Problem (often a broken connection */
  2757. if istat=-1 then do           
  2758.    return 1
  2759. end
  2760.  
  2761. /* ISTAT=-2:  return a cached-as-is (static ssis) file */
  2762. if istat=-2 then do           
  2763.  
  2764.    foo=sref_gos('FILE type text/html  'sxp ' 'docache ' NAME 'cfile' ENCRYPT 'is_encrypt' VLV 'vlv' !RANGE 'RANGE_STUFF,,,
  2765.               okpr,adv_opts, ,
  2766.               enmadd,protocol, ,
  2767.               response_status,servername,aah,host_nickname,no_postfilter,,reqprivs,file)
  2768.  
  2769.     response_status='200 '||dosdir(cfile,'S')
  2770.     if (word(foo,1)=200 | word(foo,1)=201) & datatype(word(foo,3))='NUM' then do
  2771.         response_status=word(foo,1)' 'word(foo,3)
  2772.     end
  2773.    if word(foo,1)=206 then do
  2774.       ofo=extract('bytessent')-base_sent
  2775.       RESPONSE_STATUS='206 '||ofo
  2776.    end
  2777.    if abbrev(foo,'2')=0 then do
  2778.        ofo=extract('bytessent')-base_sent
  2779.        response_status=word(foo,1)||' '||ofo
  2780.    end
  2781.    
  2782. end
  2783.  
  2784. /* istat=-3: redirected or otherwise resolved */
  2785. if istat=-3 then do 
  2786.    ofo=extract('bytessent')-base_sent
  2787.    response_status='200 '||ofo
  2788. end   
  2789.  
  2790. /* ISTAT>0 == use VAR to return dynamic ssi containing document (or first
  2791.                static cache document. Note that these might be
  2792.                "semi dynamic" ssis (that can be handled by sreproxy,)
  2793.                 a condition noted by dynfile <>'' */
  2794. if istat>=1 then do
  2795.    if selnotfound='' & is_public=1 then docache='CACHE'   /* used to return ssi-cache files */
  2796.    foo=sref_gos('VAR type text/html 'sxp ' 'docache ' name  ' file ' ENCRYPT 'IS_ENCRYPT' VLV 'vlv' !RANGE ' RANGE_STUFF, ,
  2797.               cfile,0,adv_opts,enmadd,protocol,,
  2798.               response_status,servername,aah,host_nickname,no_postfilter,dynfile,reqprivs,file)
  2799.  
  2800.    if selnotfound='' then do
  2801.      response_status='200 '||istat
  2802.    end
  2803.    if (word(foo,1)=200 | word(foo,1)=201) & datatype(word(foo,3))='NUM' then do
  2804.         response_status=word(foo,1)' 'word(foo,3)
  2805.     end
  2806.    IF SELNOTFOUND<>'' THEN do
  2807.      response_status='404 '||dosdir(file,'s')
  2808.    end
  2809.  
  2810.    ofo=extract('bytessent')-base_sent
  2811.    if word(foo,1)=206 then  RESPONSE_STATUS='206 '||ofo
  2812.    if abbrev(foo,'2')=0 then response_status=word(foo,1)||' '||ofo
  2813.  
  2814. end
  2815.  
  2816. /* cleanup and return */
  2817. if del_Send=1  then do
  2818.    arf=sysfiledelete(file)
  2819. end
  2820.  
  2821. return 1
  2822.  
  2823.  
  2824. /* Look in advanced options file for a SET ENCRYPT entry */
  2825. sref_adv_opts_encrypt:procedure
  2826. parse upper arg is_encrypt,adv_opts,default_encryption
  2827. crlf='0d0a'x
  2828. do forever
  2829.   if adv_opts='' then leave
  2830.   parse var adv_opts aline (crlf) adv_opts
  2831.   aline=strip(space(aline))
  2832.   if abbrev(aline,'SET ENCRYPT')=0 then iterate
  2833.   is_encrypt=strip(word(aline,3))
  2834.   if is_encrypt='' then is_encrypt=default_encryption
  2835. end
  2836. return is_encrypt
  2837.  
  2838.  
  2839. /**********************************************************/
  2840. /* to be moved to macrospace */
  2841. /*****************************/
  2842. /**********************************************************/
  2843. /*****************************/
  2844.  
  2845.  
  2846.  
  2847.