/* Mike Cowlishaw's Server-side includes parser, excerpted from GoRemote.80. */ /* ...slightly modified by D.L. Meyer... */ /* ...slightly modified by V. Phaniraj... */ /* Upon call from GoHTTP.v20, the current directory will have been changed */ /* to the REXX script directory. Subsequent calls to scripts located there */ /* need not change directory... */ /* ---------------------------------------------------------------- */ /* DOINCL: process a block of html for server-side includes */ /* ---------------------------------------------------------------- */ /* ARG(1) is block of data */ /*DoIncl: procedure */ rc = RxFuncAdd("SysLoadFuncs","RexxUtil","SysLoadFuncs") call SysLoadFuncs parse arg data, _filename, _ServerAdmin out='' /* result */ do forever parse var data pre '' data /* find expression */ out=out''pre /* pre-stuff */ if expr='' then if data='' then leave /* no more '{' */ out=out''eval(expr, '') /* add evaluation */ end return out /* [called as function] */ /* ---------------------------------------------------------------- */ /* EVAL: return an expression evaluation [protected] */ /* ---------------------------------------------------------------- */ /* ARG(1) is expression to evaluate */ /* ARG(2) is passed from PAGE, usually an arbitrary text message */ /* An expression starting with '?' is a direct EXTRACT, special- */ /* cased for simplicity. ({?foo} == {extract(foo)}) */ /*eval: procedure / * no variables visible */ eval: procedure expose _filename _ServerAdmin /* few variables visible */ /* arbitrary expression expected -- assume CRLF and tabs are whitespace */ parse arg expr result='' if(pos('#',expr)=0) then return result parse var expr . '#' expr /* strip anything before the # */ trigger = word(expr,1) /* find the 1st word in the expression */ if (trigger='include') then do /* these are the NCSA keywords */ parse var expr . 'file="' filen '"' . result=charin(filen,,chars(filen)) end else if (trigger ='flastmod') then result=LastModified() else if (trigger ='exec') then do parse var expr . 'cmd="' to_be_done '"' . if (to_be_done \= '') then do /* cmd tag */ tempfile=execute2(to_be_done) result=charin(tempfile,,chars(tempfile)) rc=lineout(tempfile) rc=SysFileDelete(tempfile) end else do /* cgi tag */ parse var expr . 'cgi="' command '"' . if (command='counter') then result=access_count() /* special handling of the counter internally */ /* now for rest of cgi code to go here */ end /* end of cgi */ end /* end of exec trigger handling */ return result /* done */ evaloops: return '[?]' /* ---------------------------------------------------------------- */ /* FILENAME: return the name of the file being processed. */ /* ---------------------------------------------------------------- */ /* Rather like C's "?" operation */ filename: return _filename /* ---------------------------------------------------------------- */ /* LASTMODIFIED: return the modification time & date of the file. */ /* ---------------------------------------------------------------- */ LastModified: procedure expose _filename parse arg filename if (filename == '') then filename = _filename call SysFileTree translate(filename,'\','/'),'files.' if (files.0 \= 1) then return '[?]' parse var files.1 date time . return time'm on 'date /* ---------------------------------------------------------------- */ /* FOOTER: a link to an external footer routine. */ /* ---------------------------------------------------------------- */ Footer: procedure expose _filename _ServerAdmin parse arg filename if (filename == '') then filename = _filename contents = '' interpret 'contents = Footer.Rxx(filename, contents, _ServerAdmin)' return contents /* ---------------------------------------------------------------- */ /* IF: select string based on ARG(1) */ /* ---------------------------------------------------------------- */ /* Rather like C's "?" operation */ if: if arg(1) then return arg(2); else return arg(3) /* ---------------------------------------------------------------- */ /* QFLAG: return 'checked' for a flag that's ON, null otherwise */ /* QFLAGN: return 'checked' for a flag that's OFF, null otherwise */ /* ---------------------------------------------------------------- */ qflag: if extract(arg(1))='ON' then return 'checked'; else return '' qflagn: if extract(arg(1))='OFF' then return 'checked'; else return '' /* ---------------------------------------------------------------- */ /* GMTWARN: return warning if GMT unavailable, null otherwise */ /* ---------------------------------------------------------------- */ gmtwarn: if extract('GMTSET')='ON' then return '' return '[TZ was not set - GMT is not available]' /* ----------------------------------------------------------------------- */ /* EXECUTE2: Executes an OS/2 command and sends the result to the remote */ /* client. Care should be taken to prevent creating a security */ /* hole. */ /* ----------------------------------------------------------------------- */ execute2: procedure parse arg command This_path="i:\goserve\" tempfile = SysTempFileName(This_path'tempfx.???') call lineout tempfile, "
" call lineout tempfile address cmd command ">>"tempfile call lineout tempfile, "" call lineout tempfile /* close */ return tempfile extension: procedure arg filename /* If no period or only period is first char, then return "" */ if lastpos(".",filename)<2 then return "" return translate(substr(filename, lastpos('.',filename)+1)) access_count: procedure expose _filename count_file='access.count' /* ASCII file that contains the counts */ sem_file='acc.semaphore' /* semaphore file for protection */ exclude_ips = '134.129.123.181', '134.129.123.182' URL=strip(_filename)||'/' parse upper var URL URL /* protection against multiple processes messing with the access count file simultaneously */ count =0 do forever rc = stream(sem_file,'c','query exists') if(rc='') then leave if (count < 10) then do count = count +1 say 'semaphore conflict ' end /* end of count if */ end /* end of do forever */ rc=lineout(sem_file, 'junk') rc=lineout(sem_file) /* read the access file into result and close the file */ result=charin(count_file,,chars(count_file)) rc=lineout(count_file) /* look for the URL in the string, and find the number of accesses stored in the file. Try not to use linein to avoid keeping the file open too long. */ locate = pos(URL,result) if (locate\=0) then do locate = locate+length(URL) number=substr(result,locate,200) parse var number 'Accesses:' number 'here' . say number datatype(number) /* This is the IP exclusion part, skip incrementing the number of accesses and delete the semaphore file */ 'EXTRACT CLIENTADDR' if (pos(CLIENTADDR, exclude_ips) \= 0) then do rc=SysFileDelete(sem_file) return number end /* end of clientaddr if */ /* increment the number of accesses */ number=number+1 /* This is the updating of the file, if URL is found */ rc=charout(count_file,,locate) rc=lineout(count_file,'') rc=lineout(count_file,'Accesses: '|| number || ' here') rc=lineout(count_file) end else do /* This is the updating of the file, if URL is not found A new entry is created in the file */ rc=lineout(count_file,URL) rc=lineout(count_file,'Accesses: 1 here') rc=lineout(count_file,' ') rc=lineout(count_file) number = 1 end /* end of locate if */ /* delete the semaphore file that protects the access file */ rc=SysFileDelete(sem_file) return number