home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / srev13h.zip / srefiltr.80 < prev    next >
Text File  |  2002-01-13  |  101KB  |  2,950 lines

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