home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / srev13g.zip / POSTFCHK.RXX < prev    next >
Text File  |  1999-06-27  |  44KB  |  1,496 lines

  1. /* Recording and postfilter module for SRE-http */  
  2.  
  3. /* Some comments on the "record_all_file" cache algorithim:
  4.    To speed up performance, SRE-http caches all writes
  5.    to the record_all_file.  This saves disk i/o (and repetitive
  6.    parsing of the entries).
  7.  
  8.    There are a few points worth considering in regards to this caching:
  9.       1) More memory is required to store the cache.  One
  10.          can limit the size of the cache by changing the record_cache_lines
  11.          variable, with smaller values yielding smaller caches.
  12.          For example, the default value of 1000 means "1000 entries".
  13.          At an average size of 50 bytes, that's around
  14.          5000 bytes total storage.
  15.  
  16.       2) If you have a lot of files being requested, with each having
  17.          their own entry  (that is, few if any wildcards), you may fill up
  18.          this cache. When this happens, SRE-http will write the
  19.          current cache to an archive file (with name .1 to .999),
  20.          and reset all values. "Reset" means:
  21.                 a) Set "counter" values on wildcards to 0
  22.                 b) Remove non-wildcard entries
  23.         Of course, this new file could also fill up quickly, yielding
  24.         a multiplicity of archive files.
  25.         Should this happen, you should probably increase the size of the cache.
  26.  
  27.       3) As a safety measure, the cache will be written to the record_all_file
  28.          every 5 minutes. When doing this, the current record_all_file
  29.          is given the name .bak (overwriting a preexisting .bak file).
  30.  
  31.       4) If you should change the record_all_file by hand (you add
  32.          a wildcard entry), SRE-http will detect the change and
  33.          re-read the file into the cache.  This will ERASE
  34.          all "recorded in cache but not written to file" entries --
  35.          that is, everything in the (up to) last 5 minutes.
  36.          If this minor inaccuracy (assuming that adding entries to
  37.          the Record_all_file is a rare event) can be avoided by:
  38.                 1) Turning off caching (set RECORD_CACHE_LINES=0)
  39.                 2) Setting a very fast update rate (set UPDATE_RATE=0.2,
  40.                    see below for details)
  41.                 3) Issue a !WRITE_CACHE request just prior to editing
  42.                    the record_all_file (though this any changes that
  43.                    occur whilst editing the file will be missed).
  44.          Only method #1 is guaranteed to work, but it also is the slowest.
  45.          Then again, absolute accuracy in this type of general audit
  46.          file is usually not a priority (you should use SENDFILE
  47.          for greater precision)
  48.  
  49.      5) When writing the cache, SRE-http will
  50.            a)put ALL comments at the top
  51.            b)write the list of "wildcard entries" (if any)
  52.            c)write the "non-wildcard entries" (if any)
  53.         Thus, placements of comments in between entries will be
  54.         lost (sorry, if that's really a problem contact us
  55.         and we'll consider keeping track of placement so as
  56.         to preserve order on writes).
  57.  
  58.         In fact, the most frequent "non-wildcard" entries will
  59.         be written first!
  60.  
  61.       6) If active, the HIT_CACHE will be examined before
  62.          recording an entry.
  63.  
  64. */
  65.  
  66. /* -----------------------------------------*/
  67. /* Some user configurable parameters -- you have to restart goserve
  68. for them to take effect*/
  69.  
  70. /* enter frequency, in minutes, for writing record_all cache to file (0.2 < x < 60)
  71. Note: to suppress caching, set record_cache_lines=0 in srefiltr.80
  72. */
  73. update_rate=5
  74.  
  75.  
  76. /* enter lazy_write time for common log cache, in seconds */
  77. lazy_clog=22
  78.  
  79. /* Note: as of 1.3b.1098b; log_toobig is no longer used */
  80.  
  81. /* starting verbosity level */
  82. verbose=1
  83.  
  84.  
  85. /* ---- Do NOT change code below here ---------------------------*/
  86.  
  87. parse upper arg   usequeue , USESEM,basesem,max_semwait, stuff,serverport,logfile_maxsize
  88. parse var stuff record_cache_lines workdir
  89. workdir=strip(workdir,'t','\')
  90.  
  91. if logfile_maxsize='' then logfile_maxsize=0
  92. if datatype(logfile_maxsize)<>'NUM' then logfile_maxsize=0
  93. if logfile_maxsize<0 then logfile_maxsize=0
  94. ttlog=logfile_maxsize
  95. if ttlog=0 then ttlog='unlimited'
  96.  
  97. logfile_maxsize=logfile_maxsize*1000
  98.  
  99. /*
  100. foo=pmprintf_sref(' SRE-http post filter thread: queue='||usequeue,,serverport)
  101. foo=pmprintf_sref(' SRE-http post filter thread: semaphore='||usesem,,serverport) 
  102. foo=pmprintf_sref(' SRE-http post filter thread: thread id='||mytid,,serverport)
  103. */
  104.  
  105. mytid=dostid()
  106. foo=pmprintf_sref(' SRE-http Postfilter: thread and queue= '||mytid', 'usequeue,,serverport)
  107.  
  108. myqueue=usequeue||'_X'
  109. mysem=usesem||'_X'
  110. a=rxqueue('d',myqueue)
  111. a=rxqueue('c',myqueue)
  112. if a<>myqueue then do
  113.   bb=rxqueue('d',a)
  114.   a=rxqueue('s',myqueue)
  115.   do queued()
  116.        pull
  117.   end /* do */
  118. end
  119.  
  120. a=eventsem_close(mysem)
  121. A=EVENTSEM_CREATE(mySEM)
  122. IF A<>0 then DO
  123.     foo=pmprintf_sref('SRE-http Postfilter ERROR: Error creating own semaphore: 'A' 'mysem,,serverport)
  124.     return 0
  125. end
  126.  
  127.  
  128. if  usequeue="" | USESEM="" then do
  129.    foo=pmprintf_sref('SRE-http Postfilter ERROR: initialization ERROR: '||accessfile||','||usequeue,,serverport)
  130.    exit
  131. end
  132.  
  133. signal on error name iserror
  134. signal on syntax name iserror
  135.  
  136. comments.filestamp=0
  137. if datatype(update_rate)<>'NUM' then update_rate=5
  138. update_rate=max(min(update_rate,60),0.2)
  139. update_rate=update_rate/(24*60)
  140.  
  141. if datatype(lazy_clog)<>'NUM' then lazy_clog=30
  142. if lazy_clog>1000 then lazy_clog=1000   /* in case some on messes up */
  143.  
  144. if datatype(log_toobig)<>'NUM' then log_toobig=1000
  145.  
  146. /* get sreflogs.ini from cfgsdir (or from workdir, if not found in cfgsdir) */
  147.  
  148. cfgsdir=value('SRE_CFGS_DIR',,'os2environment')
  149. logini=stream(cfgsdir||'\SREFLOGS.INI','c','query exists')
  150. if logini='' then do  
  151.       logini=stream(workdir||'\SREFLOGS.INI','c','query exists')
  152. end
  153.  
  154. sched_file=cfgsdir'\SCHEDULE.CFG'
  155.  
  156. got_log=1 
  157. if logini="" then got_log=0   /* no .ini file -- no log writing */
  158. if got_log=1 then 
  159.   foo=pmprintf_sref(' SRE-http Postfilter: using 'logini'; w/ max file size='ttlog'K',,serverport)
  160. else
  161.   foo=pmprintf_sref(' SRE-http Postfilter:  Warning, no common-log configuration file=SREFLOGS.INI',,serverport)
  162.  
  163. foo=GET_sreflogs()
  164. blog.0=0; clog.0=0 ; rlog.0=0 ; alllog.0=0
  165. lasttime=time('s') ; THISTIME=LASTTIME
  166. do_write_cache=0 
  167. last_hour_checked=-1
  168.  
  169. /* loop forevvefeerrrererere ...... */
  170. bakme:
  171.  thistime=time('s')
  172. /* write common log, and perhaps update the .ini file */
  173.  eekit=10000
  174.  if datatype(thistime)='NUM' & datatype('LASTTIME')='NUM' then eekit=thistime-lasttime
  175.  if ( abs(eekit)>lazy_clog  | do_wRITE_CACHE=1) & got_log=1 then do
  176.        do_write_cache=0
  177.        foo=write_clog()
  178.        foo=write_blog()
  179.        foo=write_rlog()
  180.        foo=write_alllog()
  181.        if (write_logs<>0) & ( (verbose>2 & (blog.0+clog.0+rlog.0)>0) |  (abbrev(upper(seloriginal),'!WRITE_CACHE')=1) ) then
  182.           foo=pmprintf_sref(' Writing common-log entries: 'clog.0','blog.0','rlog.0','alllog.0,,serverport)
  183.        ostamp=sysfiletree(logini,'FOO','F');OSTAMP=FOO.1
  184.        sstamp=sysfiletree(sched_file,'FOO','F');sstamp=foo.1
  185.        if  ostamp<>stuff.!stamp | sstamp<>stuff.!sstamp then do
  186.          if verbose>1 then foo=pmprintf_sref(' SRE-http Postfilter: updating 'logini,,serverport)
  187.          foo=GET_sreflogs()
  188.        end
  189.  
  190.        lasttime=thistime
  191.        blog.0=0; clog.0=0 ; rlog.0=0 ; alllog.0=0
  192.  end
  193.  
  194.  foo=do_scheduler()   /* take this opportunity to run scheduled events */
  195.  signal on error name iserror
  196.  signal on syntax name iserror
  197.  
  198.  a=rxqueue('s',usequeue)
  199.  goo=queued()
  200.  if goo=0 then do
  201.     WOW=EVENTSEM_WAIT(USESEM,max_semwait)
  202.  
  203.     if wow=640 then do
  204.         signal bakme
  205.     end
  206.     IF WOW<>0 THEN do         /* FATAL ERROR */
  207.         EXIT
  208.     end
  209.  end
  210.  wow=EVENTSEM_RESET(usesem)
  211.  if queued()<1 then signal bakme
  212.  parse pull isit0
  213.  isit0=translate(isit0,' ','000d0a09'x)
  214.  
  215.  if isit0=" " then signal bakme
  216.  
  217.  if abbrev(strip(translate(isit0)),'*DIE*')=1 then do
  218.      foo=pmprintf_sref('SRE-http Postfilter: terminating ',,serverport)
  219.      exit
  220.  end
  221.  if isit0="" then do
  222.       foo=pmprintf_sref('SRE-http Postfilter: bad message ',,serverport)
  223.      signal bakme
  224. end
  225.  
  226. parse var isit0 record_option ',' record_all_file ',' post_filter ',' postfilter_name ',' serverport ',' ,
  227.                  post_filter_message ',' source0 ',' request0a ',' ,
  228.                sel0 ',' tempfile ','  servername ',' host_nickname ',' used_file ',' who  ',' ,
  229.                enmadd ',' thereferer ',' req_num ',' REcord2 ',' write_logs ',' clientname0 ',' user ','  browser ',' verbose ',' ,
  230.                privset ',' privset_secret',' meterdo
  231.  
  232. parse var record2 record_status record_bytes
  233. write_logs=strip(write_logs) ; clientname0=upper(strip(clientname0))
  234. if got_Log=0 then write_logs=0
  235. browser=strip(browser) ; user=strip(user)
  236. if user=' ' then user='-'
  237. verbose=strip(verbose)
  238. req_num=strip(req_num) /* the request number */
  239.  
  240. record_option=strip(record_option) ; post_filter=strip(post_filter)
  241. if post_filter=0 then 
  242.    postfilter_name=' '
  243. else
  244.    postfilter_name=strip(postfilter_name) 
  245.  
  246. record_all_file=strip(record_all_file)
  247. serverport=strip(serverport) ; servername=strip(servername)
  248. host_Nickname=strip(Host_nickname) ; used_file=strip(used_file)
  249. parse var sel0 doorig sel0
  250. seloriginal=packur(strip(sel0)) 
  251.  
  252. who=strip(who)
  253. request0=strip(request0a)
  254. parse upper var request0 method .
  255. post_filter_message=packur(post_filter_message)
  256. enmadd=strip(enmadd) ; 
  257. thereferer=strip(thereferer)
  258.  
  259. parse var seloriginal doit '?' .
  260.  
  261. if abbrev(upper(seloriginal),'!WRITE_CACHE')=1 then do_write_cache=1
  262.  
  263. if record_option<>"NO" then do
  264.      select
  265.         when record_option="YES" then
  266.                 parse var seloriginal doit '?' .
  267.         when record_option='YES_ALL' then
  268.                 doit=seloriginal
  269.         otherwise                       /* file */
  270.               doit=used_File
  271.      end
  272.  
  273.      doit=strip(strip(doit),'l','/')
  274.      if host_Nickname<>"" & record_option<>'FILE' then
  275.                doit=host_Nickname'//'doit
  276.       njust=' '
  277.       if do_write_cache<>1 then   njust=look_hit_cache('P',doit,who,enmadd)
  278.  
  279.       if njust=' ' then do      /* not in cache, so record */
  280.          zfoo=0                   /* do we use a recordall file cache? */
  281.          if record_cache_lines>0 then do
  282.             zfoo=do_cache_record(record_all_file,doit,seloriginal)
  283.          end
  284.          if zfoo=0 then do
  285.              foo=sref_lookup_count(record_all_file,doit,'ADD','OK',2)
  286.          end
  287.          foo=add_hit_cache("P",doit,who,enmadd,zfoo)
  288.       end               /* not just hit */
  289.  end                   /* record option */
  290.  
  291.  
  292. if strip(meterdo)<>'0' then do          /* add to hit-meter tree */
  293.   call add_hitmeter
  294. end
  295.  
  296.  
  297. /* log this one (uses stuff. */
  298.  iik=is_logok(seloriginal,doorig,clientname0,record_status,write_logs,user,method)
  299.  if iik=1 then do               /* write to the common log file */
  300.       d1=space(strip(date('n'))); 
  301.       parse var d1 d1a d1b d1c
  302.       if d1a<10 then d1a='0'||d1a
  303.       d1=d1a||'/'||d1b||'/'||d1c
  304.       t1=time('n')
  305.       d1t1=d1||':'||t1
  306.       agmt=gmtoffset() ; if datatype(agmt)<>'NUM' then agmt=0
  307.  
  308.       if datatype(agmt)='NUM' then do
  309.          agmt=agmt/36
  310.          if agmt=0 then do
  311.             agmt='+0000'
  312.          end
  313.          else do
  314.            if abs(agmt)<1000 then do
  315.                if agmt>0 then
  316.                    agmt='0'||agmt
  317.                else
  318.                    agmt='-0'||abs(agmt)
  319.            end
  320.          end
  321.       end
  322.       d1t1_0=d1t1
  323.       d1t1=d1t1||' '||agmt
  324.       parse var request0 mkme a2a a3
  325.       thereq=strip(a2a)
  326.       if stuff.!nooptions=1 then parse var thereq thereq '?' .
  327.       mkme=mkme||' '||thereq
  328.       if stuff.!nohttp=0 then mkme=mkme||' '||a3
  329.       d1t1='['||d1t1||']'
  330.       d1t1_0='['||d1t1_0||']'
  331. /* this is the output to the common-log file */
  332.       ii=clog.0+1
  333.       clogq=clientname0||' - '||user||' '||d1t1||' "'||mkme||'" '||strip(record2)
  334.  
  335.       clog.ii=clogq
  336.       clog.ii.!file=which_logs(serverport,host_nickname,'COMMONLOG')
  337.       clog.0=ii
  338.  
  339. /* the browser log */
  340.       ii=blog.0+1
  341.       blog.ii.!file=which_logs(serverport,host_nickname,'BROWSERLOG')
  342.       if stuff.!apache_mode=1 then
  343.          blogq=d1t1_0||' '||browser
  344.       else
  345.          blogq=d1t1||' '||clientname0||' '||browser
  346.       blog.ii=blogq
  347.       blog.0=ii
  348.  
  349. /* the referer log */
  350.       if stuff.!force_referer=1 & thereferer=' ' then thereferer=' - '
  351.       if thereferer<>" " then do
  352.           parse var thereferer . '//' refip '/' .
  353.           iik=is_logok(-1,,refip)
  354.           if iik=1 then do
  355.              ii=rlog.0+1
  356.              if stuff.!apache_mode=1 then
  357.                 rlogq=d1t1_0||' '||thereferer||' -> '||thereq
  358.              else
  359.                 rlogq=d1t1||' "'||thereq||'" '||thereferer
  360.              rlog.ii.!file=which_logs(serverport,host_nickname,'REFERERLOG')
  361.              rlog.ii=rlogq
  362.              rlog.0=ii
  363.           end
  364.       end
  365.  
  366. /* the combined log */
  367. /* eg: (all on one line) :
  368. lion.statslab.cam.ac.uk - - [18/Jan/1996:12:04:23 +0000]
  369. "GET /~sret1/analog/ HTTP/1.0" 200 578 
  370. "http://www.statslab.cam.ac.uk/~sret1/"
  371. "Mozilla/2.0 (X11; I; HP-UX A.09.05 9000/735)"
  372. */
  373.      ii=alllog.0+1
  374.      alllog.ii=clogq||' "'||thereferer||'" "'||browser||'"'
  375.      alllog.ii.!file=which_logs(serverport,host_nickname,'COMBINEDLOG')
  376.      alllog.0=ii
  377.      if verbose>0 then  foo=pmprintf_sref(clogq,1,serverport)  /* do NOT write to srehttp.log */
  378.  
  379.   end
  380.  
  381.  tookie=postfilter_name
  382.  
  383.  do mm=1 to words(tookie)
  384.    postfilter_name=word(tookie,mm)
  385.    if pos('.',postfilter_name)=0 then
  386.         postfilter_name=postfilter_name||'.'||serverport
  387.  
  388.    signal on syntax name bad2
  389.    signal on error name bad2
  390.    yow='foo3='||postfilter_name||'(post_filter_message,source0,request0a,sel0,tempfile,servername,HOST_NICKNAME,used_file,thereferer,req_num,record2,privset,privset_secret)'
  391.    interpret yow
  392.  
  393.    signal off syntax;  signal off error
  394.  
  395.  end
  396.  
  397.  signal bakme
  398.  
  399. bad2:
  400.   signal off syntax; signal off error
  401.   foo=pmprintf_sref(" SRE-http Postfilter: Problem in post_filter routine " postfilter_name " ("seloriginal,,serverport)
  402.   signal bakme
  403.  
  404.  
  405. iserror:
  406. signal off error ; signal off syntax
  407. foo=pmprintf_sref(' error in postfilter : resetting 'sigl' (rc='rc,,serverport)
  408. a=rxqueue('d',usequeue)
  409. a=rxqueue('c',usequeue)
  410. a=eventsem_close(usesem)
  411. a=eventsem_create(usesem)
  412. foo=pmprintf_sref(' done resetting postfilter ',,serverport)
  413. signal on error name iserror
  414. signal on syntax name iserror
  415. signal bakme
  416.  
  417.  
  418. /* ========================================================== */
  419. /* --- handle "cached recordall_file -----*/
  420. do_cache_record:procedure expose record_cache_lines wilds. comments. simples. ,
  421.                 update_rate verbose serverport
  422.  
  423. parse arg record_all_file,doit,doit0
  424.  
  425. numeric digits 15
  426.  
  427. /* no cache -- then get one */
  428. if comments.filestamp=0 then do
  429.     nrecs=open_record_cache(record_all_file)
  430.    if verbose>0 then foo=pmprintf_sref(" First read of RECORD_ALL_FILE: " nrecs,,serverport)
  431.     if nrecs=0 then return 0
  432. end
  433. else do
  434.     nrecs=comments.0+simples.0+wilds.0
  435. end  /* Do */
  436.  
  437. /* cache too big? */
  438. if nrecs>record_cache_lines then do
  439.     nrecs=reset_cache(record_all_file,record_cache_lines)
  440. end
  441.  
  442. /* add current hit,  or re-read file  */
  443. foo=update_cache(doit)
  444.  
  445. /* do a timed updated to disk */
  446. d1=date('b')
  447. t1=time('s')/(24*60*60)
  448. nowtime=d1+t1
  449. yeeks=comments.istime+update_rate
  450. if (yeeks<nowtime) | strip(upper(doit0))="!WRITE_CACHE" then do
  451.    foo=save_cache(record_all_file)
  452. end
  453.  
  454.  
  455. return 1
  456.  
  457.  
  458. /* ---------------- read recordall file into cache */
  459. open_record_cache:procedure expose wilds. comments. simples. verbose serverport
  460. parse arg record_all_file
  461.  
  462. aa=sref_fileread(record_all_file,thelines,,'E')
  463. if aa<0 then return 0                /* error, use default method */
  464.  
  465. drop wilds. comments. simples.
  466.  
  467. nsimples=0 ; ncomments=0 ; nwilds=0
  468. simples.0=0 ; comments.0=0 ; wilds.0=0
  469. do mm=1 to thelines.0
  470.    aline=strip(thelines.mm)
  471.    if abbrev(aline,';')=1 | aline=' '  then do
  472.         if aline=' ' then iterate
  473.         ncomments=ncomments+1
  474.         comments.ncomments=aline
  475.         comments.0=ncomments
  476.    end
  477.    else do
  478.        parse  var aline aname act amess
  479.        if pos('*',aname)>0 then do
  480.            aname=strip(aname)
  481.            aname=translate(aname,'/','\')
  482.            aname=strip(aname,'l','/')
  483.            if act="" | datatype(act)<>'NUM' then act=0
  484.            nwilds=nwilds+1
  485.            wilds.nwilds.qname=aname ; wilds.nwilds.qct=act
  486.            wilds.nwilds.qmess=amess
  487.            wilds.0=nwilds
  488.        end
  489.        else do
  490.             nsimples=nsimples+1
  491.             if act="" | datatype(act)<>'NUM' then act=0
  492.             simples.nsimples.qname=aname; simples.nsimples.qct=act
  493.             simples.nsimples.qmess=amess
  494.             simples.0=nsimples
  495.        end
  496.    end
  497. end
  498.  
  499. /* get time stamp */
  500. d1=date('b')
  501. t1=time('s')/(24*60*60)
  502. comments.istime=d1+t1
  503.  
  504. /* get file stamp */
  505. oo=sysfiletree(record_all_file,'yow')
  506. comments.filestamp=strip(upper(yow.1))
  507.  
  508.  
  509. return nwilds+ncomments+nsimples
  510.  
  511.  
  512. /* ------------------- Write cache---------------*/
  513. write_cache:procedure expose comments. wilds. simples. verbose serverport
  514. parse arg rfile,addtimestamp
  515.  
  516.  
  517. nj=0
  518. if addtimestamp=1 then do
  519.    nj=1
  520.    alines.nj="; File reset on: "||time('N')||' '||date('N')
  521. end  /* Do */
  522.  
  523. do mm=1 to comments.0
  524.   nj=nj+1
  525.   alines.nj=comments.mm
  526. end
  527. do mm=1 to wilds.0
  528.   nj=nj+1
  529.   alines.nj=wilds.mm.qname||' '||wilds.mm.qct||' '||wilds.mm.qmess
  530. end
  531.  
  532.  
  533. /* sort simples in descending order, by frequency */
  534. do iy=1 to simples.0
  535.    foobar.iy=simples.iy.qct'         'iy
  536. end
  537. if simples.0>0 then wow=arraysort(foobar,1,simples.0,1,8,'D','N')
  538.  
  539. do mm=1 to simples.0
  540.     parse var foobar.mm act indx ; indx=strip(indx)
  541.     nj=nj+1
  542.     alines.nj=simples.indx.qname||' '||simples.indx.qct||' '||simples.indx.qmess
  543. end
  544.  
  545. alines.0=nj
  546.  
  547.  
  548.  
  549. wow=sref_filewrite(rfile,alines)
  550.  
  551. /* get time stamp */
  552. d1=date('b')
  553. t1=time('s')/(24*60*60)
  554. comments.istime=d1+t1
  555.  
  556. /* get file stamp */
  557. oo=sysfiletree(rfile,'yow')
  558. comments.filestamp=strip(upper(yow.1))
  559.  
  560.  
  561. if wow=0 then return 0
  562.  
  563. return nj
  564.  
  565.  
  566. /* ------------- Reset the cache: --------------------- */
  567. /*     Save current cache to a backup recordall file, delete current
  568.      cache file, and rewrite minimal (just wildcards and comments)
  569.      set
  570. */
  571.  
  572. reset_cache:procedure expose comments. wilds. simples. verbose serverport
  573. parse arg rfile,maxlines
  574.  
  575. /* but update if external changes occured  (might obviate need to shrink cache) */
  576. isold=cache_unsync(rfile,comments.filestamp)
  577. if isold=1 then do
  578.      nrecs=open_record_cache(rfile)
  579.      if verbose>0 then foo=pmprintf_sref(' External change, reread RECORD_ALL_FILE into cache ',,serverport)
  580.      return nrecs
  581. end
  582.  
  583. rfile2=rfile
  584. /* rename recordallfile to record.nnn (nnn=01 .. 999) */
  585. foofoo=lastpos('.',rfile)
  586. if foofoo>0 then
  587.    rfile2=delstr(rfile,foofoo)
  588.  
  589. useme=' '
  590. do mm=1 to 999
  591.    if stream(rfile2||'.'||mm,'c','query exists')=' ' then do
  592.        useme=rfile2||'.'||mm
  593.        leave
  594.    end
  595. end
  596. if useme=' ' then useme=dostempname(rfile2||'.???') /* should never happen ..*/
  597. foo=dosrename(rfile,useme)
  598. if foo=0 then return 0
  599. if verbose>0 then foo=pmprintf_sref('SRE-http Postfilter: RECORD_ALL_FILE too big; reset (old file renamed to '||useme,,serverport)
  600.  
  601. if wilds.0+comments.0> maxlines then do
  602.    if verbose>0 then foo=pmprintf_sref("SRE-http Postfilter: Warning: truncating comments in (RECORD_ALL_FILE) " rfile,,serverport)
  603.    comments.0=trunc(maxlines/2)
  604. end
  605.  
  606. /* reset counts */
  607. simples.0=0
  608. do mm=1 to wilds.0
  609.    wilds.mm.qct=0
  610. end
  611.  
  612. nrec=write_cache(rfile,1)
  613. if verbose>0 then foo=pmprintf_sref(" SRE-http Postfilter: Write RECORD_ALL_FILE cache: " nrec,,serverport)
  614.  
  615. return wilds.0
  616.  
  617.  
  618.  
  619.  
  620.  
  621. /* --------------------- update cache ---------*/
  622. /* match an entry to existing cache -- augment the match
  623. or add a new entry */
  624.  
  625. update_cache:procedure expose wilds. simples. verbose serverport
  626.  
  627. parse arg doit
  628.  
  629. /* fix up doit */
  630. doit=translate(strip(doit),'/','\')
  631. doit=strip(doit,'l','/')
  632.  
  633. nsimples=simples.0
  634. do mm=1 to nsimples
  635.    if upper(simples.mm.qname)=upper(doit) then do
  636.         simples.mm.qct=simples.mm.qct+1
  637.         simples.mm.qmess=date('o')
  638.         return 1
  639.    end
  640. end
  641.  
  642.  
  643. nwilds=wilds.0
  644. asterat=0 ; afterstar=0 ; gotit=0
  645. do mm=1 to nwilds
  646.     ares=sref_wildcard(upper(doit),upper(wilds.mm.qname),0)
  647.     parse var ares astat "," aurl ;  astat=strip(astat)
  648.     if astat=0 then iterate   /* no match */
  649.  
  650.    foo1=pos('*',wilds.mm.qname)
  651.    if foo1 >= asterat then do
  652.        tmp1=length(wilds.mm.qname)-foo1
  653.        if foo1>asterat | tmp1>afteraster then  do
  654.           asterat=foo1 ; afteraster=tmp1
  655.           gotit=mm
  656.        end              /* either condition */
  657.     end
  658. end
  659.  
  660. if gotit>0 then do
  661.     wilds.gotit.qct=wilds.gotit.qct+1
  662.     wilds.gotit.qmess=date('O')
  663.     return 1
  664. end
  665.  
  666.  
  667. nsimples=nsimples+1 ;simples.0=nsimples
  668. simples.nsimples.qname=doit
  669. simples.nsimples.qct=1
  670. simples.nsimples.qmess=date('o')
  671.  
  672.  
  673. return 1
  674.  
  675.  
  676. /* ------------- save the cache: --------------------- */
  677. /*     Save current cache to recordall file, rename current
  678.       file to .bak
  679. */
  680.  
  681. save_cache:procedure expose comments. wilds. simples. verbose serverport
  682. parse arg rfile
  683.  
  684.  
  685. /* but update if external changes occured  */
  686. isold=cache_unsync(rfile,comments.filestamp)
  687. if isold=1 then do
  688.      nrecs=open_record_cache(rfile)
  689.      if verbose>0 then foo=pmprintf_sref('SRE-http Postfilter: RECORD_ALL_FILE changed, did not write cache (reread RECORD_ALL_FILE instead ',,serverport)
  690.      return nrecs
  691. end
  692.  
  693.  
  694.  
  695. rfile2=rfile
  696. /* rename recordallfile to record.nnn (nnn=01 .. 999) */
  697. foofoo=lastpos('.',rfile)
  698. if foofoo>0 then
  699.    rfile2=delstr(rfile,foofoo)
  700. useme=rfile2||'.bak'
  701. a=sysfiledelete(useme)
  702. a=dosrename(rfile,useme)
  703. if verbose>1 then  foo=pmprintf_sref('SRE-http Postfilter: Writing current RECORD_ALL_FILE cache ',,serverport)
  704.  
  705. nrec=write_cache(rfile,0)
  706.  
  707. return nrec
  708.  
  709.  
  710. /* --- return 1 if filestamp has changed */
  711. cache_unsync:procedure expose verbose serverport
  712. parse arg record_all_file,thestamp
  713.  
  714. /* get file stamp */
  715.  
  716. oo=sysfiletree(record_all_file,'yow')
  717. afilestamp=strip(upper(yow.1))
  718.  
  719. if afilestamp=thestamp then return 0
  720. return 1
  721.  
  722.  
  723. /* -------- get julian date/time of file ----*/
  724. file_jul_date:procedure expose serverport
  725. parse arg afile
  726.  
  727. how0=dosfileinfo(afile,'W')
  728. parse var how0 how hh ':' mm ':' ss
  729. nsec=((hh*60*60) + (mm*60) + ss)/(24*60*60)
  730. if right(strip(how),2)<80 then do  /* y2k correction */
  731.    parse var how a1 '/' a2 '/' a3
  732.    how=2000+a3
  733.    how=how||a1||a2
  734.    ndays=dateconv(how,'S','B')
  735. end
  736. else do
  737.   ndays=dateconv(how,'U','B')
  738. end
  739. return ndays+nsec
  740.  
  741.  
  742. /***************************/
  743. /* check for log suppression condition */
  744. is_logok:procedure expose stuff. serverport
  745. parse upper arg sel1,doorig,clientname0,record_status,write_logs,user,method
  746.  
  747.  
  748. if sel1=-1 then do
  749.     aa=stuff.!noreferer
  750.     if aa=' ' then return 1
  751. end
  752. else do
  753.     if write_logs=0 then return 0
  754.  /* check status */
  755.     aa=stuff.!nocodes
  756.    if wordpos(strip(record_status),aa)>0 then return 0
  757.    if method<>'' & wordpos(strip(method),aa)>0 then return 0
  758. /* check clientname */
  759.  
  760.     aa=stuff.!nouser
  761. /* is it a direct match to the "user" */
  762.     if wordpos(upper(user),aa)>0 then return 0
  763. end
  764.  
  765. /* nope, so now check ip addresses  (possibly noreferer) */
  766. c1=translate(clientname0,' ','.')
  767. do ll=1 to words(aa)
  768.    aa1=upper(strip(word(aa,ll)))  /* for each entry in the nouser list */
  769.    if clientname0=aa1 then return 0       /* exact match */
  770.    if user=aa1 then return 0       /* exact match */
  771.  
  772.    if pos('*',aa1)>0 then do     /* possible wild card match */
  773.         aa1=translate(aa1,' ','.')
  774.         if words(aa1) <> words(c1) then iterate /* can't be a match */
  775.         die=1
  776.         do ll2=1 to words(c1)
  777.              c1q=strip(word(c1,ll2)) ; aa1q=strip(word(aa1,ll2))
  778.              if aa1q='*' then iterate
  779.              if c1q=aa1q then iterate
  780.              die=0 ; leave              /* if here, segment did not match */
  781.         end /* do */
  782.         if die=1 then return 0  /* all segments matched */
  783.    end  /* Do wildcard  */
  784. end /* do */
  785.  
  786. if sel=-1 then return 1         /* noreferer did NOT match */
  787.  
  788. /* check urls */
  789. theurl=strip(sel1)
  790. if doorig=1 then theurl=' '
  791. ido=stuff.!nourl.0
  792. starat=0 ; afterstar=0
  793.  
  794. do mm=1 to ido
  795.     aurl0=stuff.!nourl.mm
  796.     ares=sref_wildcard(theurl,aurl0,0)
  797.     parse var ares astat  .
  798.     astat=strip(astat)
  799.     if astat=0 then iterate   /* no match */
  800.     return 0  /* match, so it's dead */
  801. end
  802. return 1
  803.  
  804.  
  805.  
  806. /***************************/
  807. /* read sreflogs.ini file, return stuff in stuff. */
  808. get_sreflogs:procedure expose stuff. workdir verbose serverport logini sched_file
  809. parse arg afl
  810. /* possible varialbes */
  811.   varlist="COMMONLOG BROWSERLOG REFERERLOG COMBINEDLOG NOOPTIONS FORCE_REFERER APACHE_MODE NOHTTP NOCODES NOUSER NOREFERER NOURL SCHED"
  812.   stemlist="COMMONLOG BROWSERLOG REFERERLOG COMBINEDLOG NOURL SCHED "
  813.  
  814. /* default values */
  815.  stuff.!nooptions=0 ; stuff.!nohttp=0
  816.  stuff.!nourl.0=0 ; stuff.!noreferer=' '
  817.  stuff.!nocodes=' ' ; stuff.!nouser=' '
  818.  stuff.!commonlog=workdir||'\COMMON.LOG'
  819.  stuff.!browserlog=workdir||'\BROWSER.LOG'
  820.  stuff.!refererlog=workdir||'\REFEFER.LOG'
  821.  stuff.!combinedlog=workdir||'\COMBINED.LOG'
  822.  
  823.  stuff.!list='COMMONLOG BROWSERLOG REFERERLOG COMBINEDLOG'
  824.  stuff.!stamp=' '
  825.  stuff.!sstamp=' '
  826.  stuff.!sched.0=0
  827.  
  828. /* look in sreflogs.ini for info */
  829. afl=logini
  830. foo=sref_fileread(afl,'logsl',,'E')
  831. if foo<0 then do 
  832.    if verbose >2 then foo=pmprintf_sref(' SRE-http Postfilter: ' foo ' problem in sreflogs.ini file: 'afl,,serverport)
  833.    return 1
  834. end
  835. if logsl.0=0 then signal jumpsched       /* use the defaults */
  836.  
  837. stuff.!stamp=sysfiletree(afl,'FOO','f')
  838. STUFF.!STAMP=FOO.1
  839.  
  840.  
  841. do mm=1 to logsl.0
  842.    aline=strip(upper(logsl.mm))
  843.    if aline="" | abbrev(aline,';')=1 then iterate
  844.    parse upper var aline avar '=' aval
  845.    aval=strip(translate(aval,' ','"'||"'"))
  846.    avar0=strip(avar)
  847.    avar=translate(avar0,' ','.')
  848.    avar1=strip(word(avar,1))
  849.    if words(avar)=1 then do      /* check the 1 word opts */
  850.       if wordpos(avar1,varlist)=0 then iterate  /* not a valid variable */
  851.       if wordpos(avar1,'COMMONLOG BROWSERLOG REFERERLOG COMBINEDLOG')>0 then do /* check validity */
  852.           aval=chk_file(workdir,aval)
  853.       end
  854.  
  855.       exx='!'||avar1
  856.       stuff.exx=aval
  857.  
  858.       if avar1<>'SCHED' & avar1<>'NOURL' then iterate
  859.    end
  860. /* else, one of the stem boys */
  861.  
  862.   if wordpos(avar1,stemlist)=0 then iterate  /* not valid stem var */
  863.   select
  864.        when avar1="NOURL" then do
  865.           inq=stuff.!nourl.0+1
  866.           if pos('?',aval)>0 then do
  867.                parse var aval a1 '?' a2
  868.                a1=strip(translate(a1,'/','\'),'l','/')
  869.                aval=a1||'?'||a2
  870.           end
  871.           else do
  872.              aval=strip(translate(aval,'/','\'),'l','/')
  873.           end
  874.           stuff.!nourl.inq=aval
  875.           stuff.!nourl.0=inq
  876.         end
  877.        when avar1="SCHED" then do       /* deprecated -- use SCHEDULE.CFG instead */
  878.           if aval<>0 then do
  879.              inq=stuff.!sched.0+1
  880.              stuff.!sched.inq=aval
  881.              stuff.!sched.0=inq
  882.           end
  883.         end
  884.  
  885.         otherwise  do      /* check for allowables */
  886.             useme=chk_file(workdir,aval)
  887.             if useme=0 then iterate
  888.             exx=avar1||'.!'||word(avar,2)
  889.             if words(avar)>2 then exx=exx||'.!'||word(avar,3)
  890.              exx2='!'||exx
  891.             stuff.exx2=useme
  892.             stuff.!list=stuff.!list||' '||exx
  893.         end             /*otherwise */
  894.   end                /* select */
  895.  
  896. end          /* logsl */
  897.  
  898. jumpsched:
  899. aa=sysfiletree(sched_file,'FOO','F')
  900. stuff.!sstamp=foo.1
  901.  
  902. /* now get schedule.cfg; add to stuff.Sched */
  903. foo=sref_fileread(sched_file,'logsl',,'E')
  904. do mm=1 to logsl.0
  905.  
  906.    aline=strip(upper(logsl.mm))
  907.    if aline="" | abbrev(aline,';')=1 then iterate
  908.    inq=stuff.!sched.0+1
  909.    stuff.!sched.inq=aline
  910.    stuff.!sched.0=inq
  911. end   
  912.  
  913. if verbose >2 then foo=pmprintf_sref(' SRE-http Postfilter: Log file list:loglist 'stuff.!list,,serverport)
  914. return 1
  915.  
  916. /************/
  917. /* check for valid file name, and return it. Return 0 if no good */
  918. chk_file:procedure expose serverport
  919. parse arg workdir, aval
  920.  
  921.   fn1=translate(strip(upper(aval)),'\','/')  /* the filename */
  922.   if fn1=0 then return 0
  923.  
  924.   fn1=strip(translate(fn1,' ',"'"||'"'))
  925.   if abbrev(fn1,'\')=1 | pos(':',fn1)>0 then
  926.        fuse=fn1
  927.    else
  928.        fuse=workdir||'\'||fn1
  929.    foo=strip(filespec('d',fuse)||filespec('p',fuse),'t','\')
  930.    if right(foo,1)=':' then foo=foo||'\'
  931.  
  932.    if dosisdir(foo)=0 then do
  933.        call pmprintf_sref('  SRE-http Postfilter ERROR: bad log file: 'aval)
  934.        return 0  /* no such dir--error, so ignore */
  935.    end
  936.  
  937.    return fuse
  938.  
  939.  
  940.  
  941. /***************/
  942. /* write to the log files */
  943. write_clog:procedure expose clog. serverport logfile_maxsize thistime
  944. parse arg ttime,ltime
  945.  
  946. if clog.0=0 then return 0
  947.  
  948. /* are they all to the same file? */
  949. bname=clog.1.!file
  950. idid=1
  951. do mm=2 to clog.0
  952.       if clog.mm.!file<>bname then leave
  953.       idid=mm
  954. end
  955. if idid=clog.0  then do  /* all same name, dump the bunch */
  956.  
  957.    if bname=0 then return 0 /* all suppressed */
  958.     do nn=1 to clog.0
  959.        tt.nn=clog.nn
  960.     end
  961.     foo2=check_too_big(bname,logfile_maxsize)
  962.     tt.0=clog.0
  963.     foo=sref_filewrite(bname,tt,'A')
  964.     
  965. /*    cfoo=jeepers(bname,lbig) */
  966. end
  967. else do         /* several files (multi host system */
  968.   tt.0=1
  969.   do nn=1 to clog.0
  970.     if clog.nn.!file=0 then iterate
  971.     tt.1=clog.nn
  972.     foo=check_too_big(clog.nn.!file,logfile_maxsize)
  973.     foo=sref_filewrite(clog.nn.!file,tt,'A')
  974. /*    foo=jeepers(clog.nn.!file,lbig) */
  975.  end
  976. end
  977.  
  978. return 1
  979.  
  980.  
  981. /***********/
  982. /* is logfile too big? if so, rename it */
  983. check_too_big:procedure expose serverport thistime
  984. parse arg fname,mxsize
  985. if mxsize=0 then return 0               /* no max size specified*/
  986. if right(thistime,1)<9 then return 0     /* only check on every 10th request */
  987. foo=stream(fname,'c','query size')
  988. if foo='' then return 0         /* no such file means 0 length */
  989. if foo<mxsize then return 0     /* small enough */
  990.  
  991. yow=lastpos('.',fname)
  992. if yow=0 then do
  993.     f2name=fname||'.???'
  994. end
  995. else do
  996.    f2name=left(fname,yow)||'???'
  997. end
  998. f3name=dostempname(f2name)
  999. if f3name='' then do 
  1000.    call pmprintf(' SRE-http Postfilter: Can not find new name for 'fname)
  1001.    return 0
  1002. end
  1003. foo=dosrename(fname,f3name)
  1004. if foo=0 then do
  1005.    call pmprintf(' SRE-http Postfilter: Can not find rename  'fname)
  1006.    return 0
  1007. end
  1008.  
  1009. foo=pmprintf_sref(' **** SRE-http Postfilter: renamed large logfile: ',,serverport)
  1010. foo=pmprintf_sref('     'fname' -->  to --> 'f3name,,serverport)
  1011.  
  1012. return 1
  1013.  
  1014.  
  1015. /********/
  1016. /*****************
  1017.  is log file too big (check every 4th time?  -- DEPRECATED 
  1018.  
  1019. jeepers:procedure expose  serverport
  1020. parse arg bname0,toob
  1021.  
  1022. if toob=0 then return 1
  1023. foo1=random(1,5)
  1024. if foo1<5 then return 0   /* every 5th write */
  1025.  
  1026. foo=sysfiletree(bname0,'boo','F')
  1027.  
  1028. if boo.0>0 then do
  1029.   ih=strip(word(boo.1,3))
  1030.   if ih>(1000*toob) then do
  1031.       foo=pmprintf_sref(' ',,serverport)
  1032.       foo=pmprintf_sref(' ******             WARNING                  ****** ',,serverport)
  1033.       foo=pmprintf_sref(' SRE-http Postfilter: Your log file ('bname0') is becoming large ('ih,,serverport)
  1034.       foo=pmprintf_sref(' ******             WARNING                  ****** ',,serverport)
  1035.       foo=pmprintf_sref(' ',,serverport)
  1036.  
  1037.   end
  1038. end
  1039. return 0
  1040.  
  1041. ****************************************************/
  1042.  
  1043.  
  1044.  
  1045. /***************/
  1046. /* this is sort of a stupid algorithim, but it's probably adequate
  1047. (given rexx's problems with passing stem variables */
  1048.  
  1049. /* write to the common log files */
  1050. write_blog:procedure expose blog.  serverport logfile_maxsize thistime
  1051.  
  1052. if blog.0=0 then return 0
  1053.  
  1054. /* are they all to the same file? */
  1055. bname=blog.1.!file
  1056. idid=1
  1057. do mm=2 to blog.0
  1058.       if blog.mm.!file<>bname then leave
  1059.       idid=mm
  1060. end
  1061. if idid=blog.0  then do  /* all same name, dump the bunch */
  1062.    if bname=0 then return 0 /* all suppressed */
  1063.     do nn=1 to blog.0
  1064.        tt.nn=blog.nn
  1065.     end
  1066.     tt.0=blog.0
  1067.     foo=check_too_big(bname,logfile_maxsize)
  1068.     foo=sref_filewrite(bname,tt,'A')
  1069. end
  1070. else do         /* several files (multi host system */
  1071.   tt.0=1
  1072.   do nn=1 to blog.0
  1073.     if blog.nn.!file=0 then iterate
  1074.     tt.1=blog.nn
  1075.     foo=check_too_big(blog.nn.!file,logfile_maxsize)
  1076.     foo=sref_filewrite(blog.nn.!file,tt,'A')
  1077.  end
  1078. end
  1079. return 1
  1080.  
  1081.  
  1082. /***************/
  1083. /* write to the refeerer log files */
  1084. write_rlog:procedure expose rlog.  serverport logfile_maxsize thistime
  1085.  
  1086. if rlog.0=0 then return 0
  1087.  
  1088. /* are they all to the same file? */
  1089. bname=rlog.1.!file
  1090. idid=1
  1091. do mm=2 to rlog.0
  1092.       if rlog.mm.!file<>bname then leave
  1093.       idid=mm
  1094. end
  1095. if idid=rlog.0  then do  /* all same name, dump the bunch */
  1096.    if bname=0 then return 0 /* all suppressed */
  1097.     do nn=1 to rlog.0
  1098.        tt.nn=rlog.nn
  1099.     end
  1100.     tt.0=rlog.0
  1101.     foo=check_too_big(bname,logfile_maxsize)
  1102.     foo=sref_filewrite(bname,tt,'A')
  1103. end
  1104. else do         /* several files (multi host system */
  1105.   tt.0=1
  1106.   do nn=1 to rlog.0
  1107.     if rlog.nn.!file=0 then iterate
  1108.     tt.1=rlog.nn
  1109.     foo=check_too_big(rlog.nn.!file,logfile_maxsize)
  1110.     foo=sref_filewrite(rlog.nn.!file,tt,'A')
  1111.  end
  1112. end
  1113. return 1
  1114.  
  1115.  
  1116. /***************/
  1117. /* write to the common log files */
  1118. write_alllog:procedure expose alllog.  serverport logfile_maxsize thistime
  1119.  
  1120. if alllog.0=0 then return 0
  1121.  
  1122. /* are they all to the same file? */
  1123. bname=alllog.1.!file
  1124. idid=1
  1125. do mm=2 to alllog.0
  1126.       if alllog.mm.!file<>bname then leave
  1127.       idid=mm
  1128. end
  1129. if idid=alllog.0  then do  /* all same name, dump the bunch */
  1130.    if bname=0 then return 0 /* all suppressed */
  1131.     do nn=1 to alllog.0
  1132.        tt.nn=alllog.nn
  1133.     end
  1134.     tt.0=alllog.0
  1135.     foo=check_too_big(bname,logfile_maxsize)
  1136.     foo=sref_filewrite(bname,tt,'A')
  1137. end
  1138. else do         /* several files (multi host system */
  1139.   tt.0=1
  1140.   do nn=1 to alllog.0
  1141.     if alllog.nn.!file=0 then iterate
  1142.     tt.1=alllog.nn
  1143.     foo=check_too_big(alllog.nn.!file,logfile_maxsize)
  1144.     foo=sref_filewrite(alllog.nn.!file,tt,'A')
  1145.  end
  1146. end
  1147. return 1
  1148.  
  1149.  
  1150.  
  1151. /************/
  1152. /* which log file to use */
  1153. which_logs:procedure expose stuff.  serverport
  1154. parse arg sport,hname,dalog
  1155. if hname<>' ' then do
  1156.   alist=dalog||'.!'||hname||'.!'||sport
  1157.   alist=alist||' '||dalog||'.!'||hname||' '||dalog
  1158. end
  1159. else do
  1160.     alist=dalog||'.!'||sport||' '||dalog
  1161. end
  1162. alist=upper(alist)
  1163. do li=1 to words(alist)
  1164.    a1=strip(word(alist,li))
  1165.    if wordpos(a1,stuff.!list)>0 then do
  1166.        axe='!'||a1
  1167.        return stuff.axe
  1168.     end
  1169. end
  1170. return 0
  1171.  
  1172.  
  1173. /*************/
  1174. /* The scheduler */
  1175.  
  1176. do_scheduler:procedure expose stuff. last_hour_checked verbose  serverport
  1177.  
  1178. if verbose>3 & stuff.!sched.0>0 then foo=pmprintf_sref('SRE-http Postfilter: Checking ' stuff.!sched.0' SCHED. entries',,serverport)
  1179.  
  1180. if stuff.!sched.0=0  | datatype(stuff.!sched.0)<>'NUM'then return 0   /* no scheduled programs to run */
  1181.  
  1182. atime=time('n')
  1183. parse var atime ahr ':' amin ':' asec
  1184. if ahr=last_hour_checked then return 0
  1185. adate=date('n')
  1186. parse var adate mday .
  1187. aweekday=upper(date('w'))
  1188.  
  1189. /* else, check scheduled programs */
  1190. do ii=1 to stuff.!sched.0
  1191.   parse upper var stuff.!sched.ii  afreq aprog stuff ; aprog=strip(aprog); afreq=strip(afreq)
  1192.   doit=0
  1193.   select
  1194.      when abbrev(afreq,'HOUR')=1 then   doit=1
  1195.      when abbrev(afreq,'DA')=1 & ahr=0 then doit=1
  1196.      when abbrev(afreq,'WE')=1 & aweekday="SUNDAY" then doit=1
  1197.      when abbrev(afreq,'MO')=1 & mday=1 then doit=1
  1198.      otherwise doit=0
  1199.    end
  1200.    signal off error  ; signal off syntax
  1201.    signal on error name hoy1
  1202.    signal on syntax name  hoy1
  1203.    if doit =1 then do
  1204.         astat=rexxrun('f',aprog,,stuff)
  1205.         if verbose>1 & astat<>0 then foo=pmprintf_sref('SRE-http Postfilter: REXXLIB REXXRUN error code = ' astat ' on scheduled event: 'aprog,,serverport)
  1206.    end
  1207. end
  1208.  
  1209. last_hour_checked=ahr
  1210.  
  1211. signal off error ; signal off syntax
  1212. return 0
  1213.  
  1214. hoy1:
  1215. foo=pmprintf_sref('SRE-http Postfilter ERROR: Error: could not execute scheduled program: 'aprog,,serverport)
  1216. signal off error ; signal off syntax
  1217. return 0
  1218.  
  1219.  
  1220. /******************************/
  1221. /* Add entry to the hit cache*/        
  1222.  
  1223. add_hit_cache:procedure expose myqueue basesem mysem mytid  serverport
  1224. parse arg  thetype, theurl0, who , enmadd,stuff
  1225. theurl0=upper(theurl0) ; thetype=upper(thetype)
  1226.  
  1227. nogi=digits()
  1228.  
  1229. lenc=value(enmadd||'HIT_CACHE_LEN',,'OS2ENVIRONMENT')
  1230.  
  1231. if lenc=0 then return ' '               /* suppressed */
  1232. transaction=mytid
  1233.  
  1234. numeric digits 11
  1235. ttc=value(enmadd||'HIT_CACHE_DURATION',,'OS2ENVIRONMENT')
  1236. ttc=ttc/(60*24)
  1237. d1=date('b')
  1238. t1=time('m')/(24*60)
  1239. nowtime=d1+t1
  1240. endtime=nowtime+ttc
  1241. theurl0=translate(theurl0,'/','\')
  1242. moo=lenc||' '||thetype||' '||theurl0||' '||who||' '||endtime||' '||stuff
  1243.  
  1244. if lenc='FILE' then do          /* add to cache file */
  1245.   itis=file_addhitc(moo,nowtime)
  1246.   numeric digits nogi
  1247.   return 0
  1248. end
  1249.  
  1250. /* or use VARSTORE thread  */
  1251. goober=enmadd||'VARSTORE'
  1252. a=rxqueue('s',goober)
  1253.     queue  transaction ' ' host_nickname ',' myqueue ',' mysem ',' 'PUT_HIT,'||moo
  1254. dothread=basesem||'VARSTORE'
  1255. a=eventsem_post(dothread)  /* no return expected */
  1256. return 0
  1257.  
  1258.  
  1259. /* --------------- */
  1260. /* add to the  .stem  file (slower, but perhaps better for huge numbers of hits */
  1261. file_addhitc:procedure expose enmadd   serverport
  1262. parse arg  moo,nowtime
  1263.  
  1264. arf=serverport
  1265.  
  1266. adir=strip(value(enmadd||'TEMPDATA_DIR',,'os2environment'),'t','\')||'\'
  1267.  
  1268. cfile=adir||'_HITCACH.'||arf
  1269. if stream(cfile,'c','query exists')=' ' then do
  1270.    foo=pmprintf_sref("SRE-http Postfilter: Creating hit-cache file " cfile,,serverport)
  1271.    eek.1=";The SRE-http hit cache file-- do NOT edit ! "
  1272.    foo=sref_filewrite(cfile,'eek','R',1,1)
  1273.    if foo=0 then do
  1274.         foo=pmprintf_sref( " SRE-http Postfilter ERROR: Error creating hit-cache file: " cfile,,serverport)
  1275.         return
  1276.    end
  1277. end
  1278.  
  1279. /* wait for it to be unlocked */
  1280. isnow=time('r')
  1281. do until twait>30
  1282.   twait=time('e')
  1283.   aa=sref_fileread(cfile,'yy',,'E')
  1284.   if aa>=0 then leave
  1285.   ddt=syssleep(0.2)
  1286. end
  1287. if aa<0 then do
  1288.    foo=pmprintf_sref("SRE-http Postfilter: Hit cache file could not be opened for augmentation: " cfile,,serverport)
  1289.    return ' '
  1290. end
  1291.  
  1292. /* now lock it! We'll clean it up, and add current hit to beginning */
  1293. aa=sref_open_read(cfile,10,'write')
  1294. if aa<0 then do
  1295.    foo=pmprintf_sref("SRE-http Postfilter: Hit cache file could not be opened for augmentation: " cfile,,serverport)
  1296.    return ' '
  1297. end
  1298.  
  1299.  
  1300. newl.1=moo
  1301. i1=1
  1302. /* remove expired entries */
  1303. do iu=1 to yy.0
  1304.    aline=yy.iu
  1305.    if aline=' ' then iterate
  1306.    if abbrev(strip(aline),';')=1 then do
  1307.        i1=i1+1
  1308.        newl.i1=aline
  1309.        iterate
  1310.     end
  1311.     parse var aline atype aurl aip  aendtime .
  1312.     aendtime=strip(aendtime)
  1313.     if aendtime >= nowtime then do
  1314.         i1=i1+1
  1315.         newl.i1=aline
  1316.     end
  1317.     else do
  1318.     end
  1319.     if i1>10000 then leave   /* prevent too big */
  1320. end
  1321. newl.0=i1
  1322. aa=stream(cfile,'c','close')
  1323. foo=sref_filewrite(cfile,'newl','R',i1,1)
  1324. if foo=0 | foo<=0 then
  1325.   foo=pmprintf_sref( "SRE-http Postfilter: Could not augment&update hit-cache file ",,serverport)
  1326. return ' '              
  1327.  
  1328.  
  1329. /*****************************/
  1330. /* see if url is in the  "hit cache"  */
  1331. look_hit_cache:procedure expose basesem mysem myqueue mytid  serverport
  1332. parse upper arg thetype, theurl, who , enmadd
  1333.  
  1334. theurl=translate(theurl,'/','\')
  1335.  
  1336. lenc=value(enmadd||'HIT_CACHE_LEN',,'OS2ENVIRONMENT')
  1337. if lenc=0 then return ' '               /* suppresed */
  1338. transaction=mytid
  1339. nogi=digits()
  1340.  
  1341. numeric digits 12
  1342. d1=date('b')
  1343. t1=time('m')/(24*60)
  1344. nowtime=d1+t1
  1345.  
  1346. if lenc='FILE' then do
  1347.   itis=file_lenhitc(thetype,theurl,who,enmadd,nowtime)
  1348.    numeric digits nogi
  1349.   return itis
  1350. end
  1351.  
  1352.  
  1353. /* here to read from VARSTORE thread */
  1354. /* or use VARSTORE thread  */
  1355. goober=enmadd||'VARSTORE'
  1356. moo=thetype||' '||who||' '||theurl
  1357. a=eventsem_reset(mysem)
  1358. a=rxqueue('s',goober)
  1359.     queue  transaction ' ' host_nickname ',' myqueue ',' mysem ',' 'GET_HIT, '||moo
  1360. dothread=basesem||'VARSTORE'
  1361. a=eventsem_post(dothread)  
  1362.  
  1363. a=eventsem_wait(mysem) /* wait for answer */
  1364.  
  1365. if a<>0 then do
  1366.    foo=pmprintf_sref(' A Fatal Semaphore failure in POSTF-Look_hit_cache: 'a,,serverport)
  1367.    return ' '
  1368. end
  1369. a=rxqueue('s',myqueue)
  1370.  
  1371. parse pull aline
  1372.  
  1373. PARSE VAR ALINE idnum ',' aline
  1374.  
  1375. idnum=strip(translate(idnum,' ','000d0a'x));TRANSACTION=STRIP(TRANSACTION)
  1376. if idnum<>transaction then  do /*wierd error: got someone else's message, give up */
  1377.       say ' Read odd id from VARSTORE queue :' transaction ',' idnum
  1378.       return ' '
  1379. end
  1380. return strip(aline)
  1381.  
  1382.  
  1383. /* --------------- */
  1384. /* read from cachelist from an .idx file,, slower but perhaps better for huge number of hits */
  1385.  
  1386. file_lenhitc:procedure  expose  serverport
  1387. parse arg thetype,theurl,who,enmadd,nowtime
  1388.  
  1389. arf=serverport
  1390. adir=strip(value(enmadd||'TEMPDATA_DIR',,'os2environment'),'t','\')||'\'
  1391. theurl=strip(translate(theurl,'/','\'))
  1392.  
  1393. cfile=adir||'_HITCACH.'||arf
  1394. if stream(cfile,'c','query exists')=' ' then do
  1395.    say "  No hit cache file " cfile
  1396.    return ' '
  1397. end
  1398.  
  1399. /* wait for it to be unlocked */
  1400. isnow=time('r')
  1401. do until twait>30
  1402.   twait=time('e')
  1403.   aa=sref_fileread(cfile,'yy')
  1404.   if aa>=0 then leave
  1405.   ddt=syssleep(0.2)
  1406. end
  1407. if aa<0 then do
  1408.    say " Hit cache file could not be opened: " cfile
  1409.    return ' '
  1410. end
  1411.  
  1412. /* see if a match exists */
  1413. do iu=1 to aa
  1414.    aline=yy.iu
  1415.    if aline=' ' then iterate
  1416.    if abbrev(strip(aline),';')=1 then iterate
  1417.     parse var aline atype aurl aip  aendtime stuff
  1418.     atype=strip(atype) ; aurl=strip(aurl) ; aip=strip(aip)
  1419.     aendtime=strip(aendtime)
  1420.    if theurl<>aurl | aip<>who | atype<>thetype then iterate
  1421.    if aendtime >= nowtime then do
  1422.         return stuff
  1423.    end
  1424. end
  1425. return ' '              /* no match */
  1426.  
  1427.  
  1428.  
  1429.  
  1430.  
  1431. /**************/
  1432. /* add to hitmeter file */
  1433. add_hitmeter:
  1434.  
  1435. mfile=value('SREF_HITMETER_FILE',,'os2environment')
  1436. /* now lock it! */
  1437. aa=sref_open_read(mfile,10,'BOTH')
  1438. if aa<0 then do
  1439.       foo=pmprintf_sref("SRE-http Postfilter: Hit-meterfile could not be opened for augmentation: " mfile,,serverport)
  1440.       return 0
  1441. end
  1442. iaa=stream(mfile,'c','query size')
  1443. if iaa=0 | iaa='' then do
  1444.    foo=pmprintf_sref("SRE-http Postfilter: unable to read hit-meterfile: " mfile,,serverport)
  1445.    return 0
  1446. end
  1447.  
  1448. parse var meterdo n3a '/' n4a
  1449. if datatype(n3a)<>'NUM' then n3a=0
  1450. if datatype(n4a)<>'NUM' then n4a=0
  1451.  
  1452. mstuff=strip(charin(mfile,1,iaa),'t','1a'x)
  1453.  
  1454. lookfor=host_nickname'//'||translate(seloriginal)
  1455. lookfor=left(lookfor,min(80,length(lookfor)))
  1456. iat=pos(' 'lookfor,mstuff)
  1457. A0=RIGHT(0,7); A1=RIGHT(1,7)
  1458. if iat=0 then do        /* add to end */
  1459.   IF RECORD_STATUS=304 THEN
  1460.      mstuff=mstuff||'0d0a'x||a0||a1||right(n3a,7)||right(n4a,7)||'  '||lookfor
  1461.   ELSE
  1462.      mstuff=mstuff||'0d0a'x||a1||a0||right(n3a,7)||right(n4a,7)||'  '||lookfor
  1463.  
  1464.   foo=charout(mfile,mstuff,1)
  1465.   foo=stream(mfile,'c','close')
  1466.   return 0
  1467. end
  1468.  
  1469. /* else, augment entry  -- iat2 will be start of this record */
  1470. iat2=lastpos('0d0a'x,mstuff,iat)
  1471. if iat2=0 then
  1472.    iat2=1
  1473. else
  1474.    iat2=iat2+2
  1475.  
  1476. iat3=pos('0d0a'x,mstuff,iat2)           /* to end of record */
  1477. if iat3=0 then 
  1478.   iat3=length(mstuff)
  1479. else
  1480.   iat3=iat3-1
  1481. rlen=1+iat3-iat2
  1482. aline=substr(mstuff,iat2,rlen)
  1483. parse VAR aline n1 n2 n3 n4 itis
  1484. IF RECORD_STATUS<>304 THEN
  1485.    n1=n1+1
  1486. ELSE
  1487.    n2=n2+1
  1488. n3=n3a+n3
  1489. n4=n4a+n4     
  1490. aline=right(n1,7)||right(n2,7)||right(n3,7)||right(n4,7)||'  '||lookfor
  1491. mstuff=overlay(aline,mstuff,iat2)
  1492. foo=charout(mfile,mstuff,1)
  1493. foo=stream(mfile,'c','close')
  1494. return 0
  1495.  
  1496.