home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / srev13h.zip / POSTFCHK.RXX < prev    next >
Text File  |  1999-11-22  |  45KB  |  1,518 lines

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