home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Spezial
/
SPEZIAL2_97.zip
/
SPEZIAL2_97.iso
/
ANWEND
/
ONLINE
/
SREFPRC1
/
DOCGI3.SRF
< prev
next >
Wrap
Text File
|
1997-07-13
|
17KB
|
467 lines
/* SREF_DOCGI_PIECES_2:
This is used when cgi_bin_pieces=2 -- send cgi-bin output "as it's written",
fileread mode (as opposed to named pipe mode).
This is a VERY heavily modified version of
don meyers cgi handler. The biggest change is the use of pipes
to capture stdout -- which allows sending output as recived.
*/
sref_DoCGI_pieces_2:
parse arg cgi_bin_dir, sel, verb, clientname0, filter_name, port ,,
servername, protocol, dir, who,tempfile,cmdfile,httpd_inc, ,
VERBOSE,morestuff,do_htaccess,htaccess_file,privset,empty_path_ok,basedir
if rxfuncquery('fileread_rxf')=1 then do
goti1=RxFuncAdd('Fileread_rxf', 'FILEREXX', 'fileread')
if goti1=1 then call pmprintf(" Error: unable to load FILEREAD FILEREXX functions; using named pipe mode ")
end
if rxfuncquery('fileopen_rxf')=1 then do
goti2=RxFuncAdd('Fileopen_rxf', 'FILEREXX', 'fileopen')
if goti2=1 then call pmprintf(" Error: unable to load FILEOPEN FILEREXX functions; using named pipe mode ")
end
if rxfuncquery('fileclose_rxf')=1 then do
goti3=RxFuncAdd('Fileclose_rxf', 'FILEREXX', 'fileclose')
if goti3=1 then call pmprintf(" Error: unable to load FILECLOSE FILEREXX function; using named pipe mode ")
end
parse var morestuff enmadd transaction homedir host_nickname ','fix_expire','myqueue', 'mysem
myqueue=strip(myqueue) ; mysem=strip(mysem);fix_expire=strip(fix_expire)
if datatype(fix_expire)<>'NUM' then fix_expire=0
/*
1) cgi_bin_dir is of form d:\goserv\progs (dir where progs located --
strip final \). Should be set by configurator.
Note: cgi-bin\mapimage request strings are captured by SRE-FILTER, and not processed here
2) Sel is parsed, with scriptname, pathparms and list removed:
i.e.; if sel = cgi-bin/turkey/joe/proj1?arg1=wow
scriptname= turkey
This will run cgi_bin_dir\turkey (a cmd or exe file).
If you want to run programs NOT in the cgi_bin_dir directory,
pathparms= joe/proj
list= arg1=wow
3) Other variables are generic variables set in sre-filter
*/
parse var sel t1 '?' list
foo1=translate(sel,'/','\')
parse var t1 foocgi '/' scriptname '/' pathparms
scriptname=strip(scriptname); cgi_bin_dir=strip(cgi_bin_dir)
scriptname=strip(scriptname,,'"')
scriptname=strip(scriptname,,"'")
/* see if we should use a different interpeter (i.e.; perl) */
/* check "call" type, using extention of scriptname */
parse upper var scriptname foo '.' aext ; aext=strip(aext)
calltype='CALL '
if aext<>' ' & aext<>'.CMD' & aext<>'.80' then do /* not a rexx extension -- check others */
checktypes=upper(value(enmadd||'INTERPRET_TYPES',,'os2environment'))
foo=strip(pos(aext||'=',checktypes))
if foo>0 then do
foo2=pos(' ',checktypes,foo)
if foo2=0 then foo2=length(checktypes)+1
wow=substr(checktypes,foo,foo2-foo)
parse var wow . '=' calltype
calltype=strip(calltype)||' '
end
end
IF VERBOSE>1 THEN call pmprintf_sref(calltype " CGI-Bin call for " scriptname " , SEL = " SEL)
/* begin meyer stuff */
scriptalias=strip(cgi_bin_dir,'t','\')
env='OS2ENVIRONMENT'
tempfile=translate(tempfile,'\','/')
if (verb == 'POST') then do
'read body var postedlist' /* get the incoming data */
if rc=-4 then /* body too large */
return response_dc('badreq', 'sent too much data')
if rc<>0 then /* e.g., invalid HTTP header */
return response_dc('badreq', 'sent data that could not be read')
end
ScriptName = translate(ScriptName)
/* we could check by extenstion (com, cmd, exe), but this might cause incorrect errors
So, we'll risk ugly errors below */
if do_htaccess=1 then do /* first check htaccess ? */
foo1=scriptalias'\'scriptname
tmp1=sref_htaccess(sel,foo1,htaccess_file,who,clientname0,,port,dir, ,
SERVERNAME,TEMPFILE,0)
if tmp1=-1 then
return '401 0'
end
aa=sysfiletree(scriptalias'\'scriptname,'yow1','F')
if yow1.1 =0 then
return response_dc( 'notfound', 'cannot be honored. <p>This server does not currently support any CGI service called "'ScriptName'".')
/* else, do the script */
parse var ScriptAlias Drive':'Rest
if (Drive == ScriptAlias) then Drive = '' /* means no drive info to parse off... */
i = 1
_acc = REQFIELD("accept")
acc = '%'
ClientAccepts = ''
do while (acc \= _acc)
acc = REQFIELD("accept", i)
if (ClientAccepts \= '') then ClientAccepts = ClientAccepts','acc
else ClientAccepts = acc
i = i+1
end
rc = 0
rc = stream(tempfile, 'c', 'close') /* Close the file to avoid preventing process from access. */
/* This is pretty touchy stuff below, be very careful if you edit any of this... */
InputFile = translate( tempfile, '#', '$')
ReturnCode = '200' /* default return code */
call lineout CmdFile, "/**/"
call lineout CmdFile, "'@ECHO OFF'"
call lineout cmdfile,'myq="'myqueue'"'
call lineout cmdfile,'mysem="'mysem'"'
if (Drive \= '') then call lineout CmdFile, "'"Drive":'"
call lineout CmdFile, "'CD "ScriptAlias"'"
call lineout CmdFile, "env = '"env"'"
SrvVersionText = server('H')||' '||filter_name
rc = value('SERVER_SOFTWARE', SrvVersionText, env)
rc = value('GATEWAY_INTERFACE','CGI/1.1',env)
rc = value('SERVER_NAME',ServerName,env)
rc = value('SERVER_PORT',port,env)
i =1
l =1
ClientAccepts = ''
HeaderFile = translate( tempfile, '~', '$')
'READ HEADER FILE NAME 'HeaderFile /* get the incoming header data */
hd = linein( HeaderFile, 1)
do while (hd \= '')
hd = linein( HeaderFile)
parse var hd Hkey': 'content
Hkey = translate(Hkey, '_', '-')
Hkey = translate(Hkey)
select
when (Hkey == 'ACCEPT') then do
parse var content content'; 'q
if (i > 1) then ClientAccepts = ClientAccepts', 'content
else ClientAccepts = content
if (l == 5) then do
call lineout CmdFile, "'SET HTTP_ACCEPT=%HTTP_ACCEPT%"ClientAccepts"'"
ClientAccepts = ''
l = 1
end
l = l+1
i = i+1
end /* accept */
/* Handle other, unrecognized headers to conform to CGI/1.1 spec. */
otherwise do
if (Hkey \= '') then rc = lineout(CmdFile, "rc = value('HTTP_"Hkey"','"content"',env)")
end
end /*select */
end
rc = lineout( HeaderFile)
if (ClientAccepts \= '') then call lineout CmdFile, "'SET HTTP_ACCEPT=%HTTP_ACCEPT%"ClientAccepts"'"
crlf = '0d0a'x
if empty_path_ok=1 & strip(pathparms)='' then do
pathparms='' ; tt1=''
end
else do
if pathparms<>" " then
tt1=sref_do_virtual(dir,pathparms,enmadd,0,transaction,homedir,host_nickname)
else
tt1=dir
tt1=translate(tt1,'/','\')
pathparms='/'||strip(translate(pathparms,'/','\'),'l','/')
end
pathparms=upper(pathparms) ; tt1=upper(tt1)
if empty_path_ok=1 then
scn='/CGI-BIN/'||scriptname
else
scn=scriptname
remuser=' '
authtype=' '
goo=reqfield('AUTHORIZATION:')
if goo<>" " then do
parse var goo authtype m64 . /* get the encoded cookie */
dec=pack64(m64) /* and decode it */
parse upper var dec remuser ':' . /* split to userid and password */
end
/* fixed auth_Type and remote_user, 1/97)
added sref_privest, 2/97 */
mytid=dostid();mypid=dospid()
/* note that script_dir and caller_process caller_thread are sre-filter addons */
output_text = "rc = value('SCRIPT_NAME','"ScN"',env)"crlf,
"rc = value('REQUEST_METHOD','"verb"',env)"crlf,
"rc = value('SREF_PRIVSET','"privset"',env)"crlf,
"rc = value('REMOTE_ADDR','"who"',env)"crlf,
"rc = value('SERVER_ROOT','"basedir"',env)"crlf,
"rc = value('SERVER_PROTOCOL','"protocol"',env)"crlf,
"rc = value('PATH_INFO','"PathParms"',env)"crlf,
"rc = value('PATH_TRANSLATED','"tt1"',env)"crlf,
"rc = value('REMOTE_USER','"||remuser||"',env)"crlf,
"rc = value('AUTH_TYPE','"||authtype||"',env)"crlf,
"rc = value('CONTENT_TYPE','"REQFIELD("Content-type")"',env)"crlf,
"rc = value('CONTENT_LENGTH','"REQFIELD("Content-length")"',env)"crlf,
"rc = value('REMOTE_HOST','"clientname0"',env)"crlf,
"rc = value('QUERY_STRING','"list"',env)"crlf,
"rc = value('CALLER_THREAD','"mytid"',env)"crlf,
"rc = value('SERVER_PID','"mypid"',env)"crlf,
"rc = value('SCRIPT_DIR','"upper(scriptalias)"',env)"
call lineout CmdFile, output_text
/* Change suggested by someone (lost the email) to allow 4OS2 to be used as shell. */
ScriptAlias = translate( ScriptAlias, '\', '/')
plist=packur(list) /* pack escape sequences in list */
if (plist \= '') then do
if (pos('&', plist) > 0) | (pos('=', plist) > 0) | (pos("'", plist) > 0) then
/* plist = '"'plist'"' / * This line "quotes" the parameter list. Actual HTTPDs */
plist = '' /* simply omit the parameter list in this case. */
else do /* Process the parameter list back to original ascii format */
plist = translate( plist, ' ', '+')
end
end
/* setup stuff for interprocess communication */
call lineout cmdfile,"mypid=dospid();mytid=dostid()"
call lineout cmdfile,"foo=rxqueue('s',myq) "
call lineout cmdfile,"push mypid mytid "
if verbose>3 then
call lineout cmdfile,' call pmprintf(" (FILEREXX mode) about to call script 'scriptname'")'
if (verb == 'POST') then do
rc = charout( InputFile, postedlist, 1)
rc = stream( InputFile, 'C', 'close') /* Close file */
call lineout CmdFile, "'" calltype ScriptAlias"\"ScriptName" "plist" <"InputFile" >>"tempfile"'"
end
else do
call lineout CmdFile, "'" CALLtype ScriptAlias"\"ScriptName" "plist" >>"tempfile"'"
end
if verbose>3 then call lineout cmdfile,' call pmprintf(" done with script 'scriptname' (" rc)'
call lineout cmdfile,' exit 0'
call lineout CmdFile /* Close file */
/* clear queue */
aa1=-1 ;idid=0
a=rxqueue('s',myqueue)
do while queued()<>0
pull .
end
/* detach and run the cgi-bin caller */
address cmd
'DETACH 'CmdFile
rcode=RC
address
/* get from queue: the process of the detached job */
a=rxqueue('s',myqueue)
do until 1=2
if queued()=0 then do
call delay(0.05)
iterate
end
pull chkpid .
leave
end
if verbose>3 then call pmprintf_sref(" CGI-BIN using process " chkpid)
/* ready to read info: with special treatment of the header */
crlf='0d0a'x
pud="" ;nohd=1;sendstart=0 ;handle=0
do until dn=0
are=readit() /* use fileread_rxl function to read temporary file */
if length(are)>0 & nohd=1 then do /* is there a blank line delimited header */
pud=pud||are
pud2=pud ; inpud=0
do until pud2=""
parse var pud2 al1 (crlf) pud2
if al1="" & length(pud2)>0 then do /* blank line, must be end of headers */
gotem.0=inpud
aa=do_cgi_header()
'SEND TYPE ' aa ' AS ' SCRIPTNAME
'SET NETBUFFER OFF '
'VAR NAME pud2 '
nohd=0 ; sendstart=1
leave
end /* processed header */
inpud=inpud+1 ; gotem.inpud=al1 /* add to heders list */
end
end /* checking header? */
else do /* header's been done, got someting */
if length(are)>0 then 'VAR NAME ARE '
end
if dosprocinfo('s',chkpid)<0 then leave
call delay(0.02)
end
are=readit(1)
if length(are)>0 & nohd=0 then 'VAR NAME ARE'
if sendstart=1 then
'SEND COMPLETE '
else
return response_dc('badreq', 'problem with CGI script "'scriptname'".')
if verbose>3 then do
cm1=filespec('d',cmdfile)||filespec('p',cmdfile)||'FSMP.CMD'
oo=sysfiledelete(cm1)
oo=dosrename(cmdfile,cm1)
call pmprintf_sref(" Save cgi-bin invoker to " cm1)
end
else do
rc = SysFileDelete( CmdFile) /* delete CmdFile, we're done with it. */
end
if (verb == 'POST') then rc = SysFileDelete( InputFile) /* delete InputFile, we're done with it. */
rc = SysFileDelete( HeaderFile) /* delete HeaderFile, we're done with it. */
if handle<>0 then aa=fileclose_rxf(handle)
rc = SysFileDelete(tempfile)
return returncode||' '||extract('bytessent')
/********/
/* read from tempfile, using filerexx functions
Read until you get a null string */
readit:procedure expose handle tempfile
parse arg getall
bld=""
if handle=0 then do
handle=fileopen_rxf(tempfile, 'rs', "e")
end
if handle=0 then return ""
if getall<>1 then do
addx=fileread_rxf(handle,10000)
return addx
end
do forever
addx=fileread_rxf(handle,10000)
if addx="" then return bld
bld=bld||addx
end
/***********/
/* routine to deal with header */
do_cgi_header:procedure expose gotem. fix_expire handle
ContentType = 'text/html'
ContentLength = 0
do ipoop=1 to gotem.0
Hder = gotem.ipoop
parse var Hder Hkey': 'content
_Hkey = Hkey
_Hkey = translate( _Hkey)
/* This should handle the special header case of nph-* scripts... */
if (word(_Hkey,1) == 'HTTP/1.0') then do
parse var Hder Hkey content
_Hkey = 'STATUS'
'HEADER NOAUTO'
end
select
when (_Hkey == 'CONTENT-LENGTH') then ContentLength = content
when (_Hkey == 'CONTENT-TYPE') then ContentType = content
when (_Hkey == 'LOCATION') | (_Hkey == 'URI') then do
/* It is not 'spec' to assume a redirect if URI is included, but 'LOCATION' isn't really even 'spec'... */
if (_Hkey == 'LOCATION') then do
ReturnCode = '302'
'RESPONSE HTTP/1.0 'ReturnCode' Found' /* Set HTTP response line */
end
'HEADER ADD 'Hkey': 'content
end
when (_Hkey == 'STATUS') then do
parse var content ReturnCode rest
'RESPONSE HTTP/1.0 'content /* Set HTTP response line */
end
otherwise 'HEADER ADD 'Hkey': 'content /* oo */
end
end /* do loop */
if contentlength>0 then 'HEADER ADD Content-length: ' ContentLength
if fix_expire>0 then do
alen=contentlength ; if contentlength=0 then alen=' '
foo=sref_expire_response(fix_expire,alen,contenttype)
end
return contenttype
/* ----------------------------------------------------------------------- */
/* RESPONSE_dc: Standard [mostly error] responses. */
/* ----------------------------------------------------------------------- */
/* This routine should stay in the main filter program. */
/* Arguments are: response type and extended message information. */
/* It returns the GoServe command to handle the result file. */
response_dc: procedure expose tempfile seloriginal request0 source0 servername
parse arg request, message
select
when request='badreq' then use='400 Bad request syntax'
when request='notfound' then use='404 Not found'
when request='forbid' then use='403 Forbidden'
when request='unauth' then use='401 Unauthorized'
otherwise do
use='404 Not found'
say 'weird response ' request message
end
end /* Add others to this list as needed */
/* Now set the response and build the response file */
'RESPONSE HTTP/1.0' use /* Set HTTP response line */
parse var use code text
call lineout tempfile, '<!doctype html public "-//IETF//DTD HTML 2.0//EN">'
call lineout tempfile, "<html><head><title>"text"</title></head>"
call lineout tempfile, "<body><h2>Sorry...</h2>"
call lineout tempfile, "<p>Problem detected:" message"."
call lineout tempfile, "<hr><em>HTTP response code:</em>" code '['text']'
call lineout tempfile, "<br><em>From server at:</em>" servername
call lineout tempfile, "<br><em>Running:</em>" server()
call lineout tempfile, "</body></html>"
call lineout tempfile /* close */
a2=dosdir(tempfile,'s')
'FILE ERASE TYPE text/html NAME' tempfile
a1=word(use,1)
if handle<>0 then aa=fileclose_rxf(handle)
return a1||' '||a2