#include "ep.h"
#include "epmacro.h"
static
char
sVersion [] = VERSION ;
static
int
bInitDone = 0 ;
static
char
sEnvHashName [] =
"ENV"
;
static
char
sFormHashName [] =
"HTML::Embperl::fdat"
;
static
char
sUserHashName [] =
"HTML::Embperl::udat"
;
static
char
sStateHashName [] =
"HTML::Embperl::sdat"
;
static
char
sModHashName [] =
"HTML::Embperl::mdat"
;
static
char
sFormSplitHashName [] =
"HTML::Embperl::fsplitdat"
;
static
char
sFormArrayName [] =
"HTML::Embperl::ffld"
;
static
char
sInputHashName [] =
"HTML::Embperl::idat"
;
static
char
sHeaderHashName [] =
"HTML::Embperl::http_headers_out"
;
static
char
sTabCountName [] =
"HTML::Embperl::cnt"
;
static
char
sTabRowName [] =
"HTML::Embperl::row"
;
static
char
sTabColName [] =
"HTML::Embperl::col"
;
static
char
sTabMaxRowName [] =
"HTML::Embperl::maxrow"
;
static
char
sTabMaxColName [] =
"HTML::Embperl::maxcol"
;
static
char
sTabModeName [] =
"HTML::Embperl::tabmode"
;
static
char
sEscModeName [] =
"HTML::Embperl::escmode"
;
#ifdef EP2
static
char
sCurrNodeName [] =
"HTML::Embperl::_ep_node"
;
static
char
sTokenHashName [] =
"HTML::Embperl::Syntax::Default"
;
#endif
static
char
sDefaultPackageName [] =
"HTML::Embperl::DOC::_%d"
;
static
char
sUIDName [] =
"_ID"
;
static
char
sSetCookie [] =
"Set-Cookie"
;
static
char
sCookieNameDefault [] =
"EMBPERL_UID"
;
static
int
nPackNo = 1 ;
static
tReq * pReqFree = NULL ;
tReq InitialReq ;
tReq * pCurrReq ;
static
HV * pCacheHash ;
#if PERL_VERSION >= 8
SV ep_sv_undef ;
#endif
char
* LogError (
register
req * r,
int
rc)
{
const
char
* msg ;
char
* sText ;
SV * pSV ;
SV * pSVLine = NULL ;
SV ** ppSV ;
STRLEN l ;
int
n ;
EPENTRY (LogError) ;
r -> errdat1 [
sizeof
(r -> errdat1) - 1] =
'\0'
;
r -> errdat2 [
sizeof
(r -> errdat2) - 1] =
'\0'
;
GetLineNo (r) ;
if
(rc != rcPerlWarn)
r -> bError = 1 ;
switch
(rc)
{
case
ok: msg =
"[%d]ERR: %d: %s ok%s%s"
;
break
;
case
rcStackOverflow: msg =
"[%d]ERR: %d: %s Stack Overflow%s%s"
;
break
;
case
rcArgStackOverflow: msg =
"[%d]ERR: %d: %s Argumnet Stack Overflow (%s)%s"
;
break
;
case
rcStackUnderflow: msg =
"[%d]ERR: %d: %s Stack Underflow%s%s"
;
break
;
case
rcEndifWithoutIf: msg =
"[%d]ERR: %d: %s endif without if%s%s"
;
break
;
case
rcElseWithoutIf: msg =
"[%d]ERR: %d: %s else without if%s%s"
;
break
;
case
rcEndwhileWithoutWhile: msg =
"[%d]ERR: %d: %s endwhile without while%s%s"
;
break
;
case
rcEndtableWithoutTable: msg =
"[%d]ERR: %d: %s blockend <%s> does not match blockstart <%s>"
;
break
;
case
rcTablerowOutsideOfTable: msg =
"[%d]ERR: %d: %s <tr> outside of table%s%s"
;
break
;
case
rcCmdNotFound: msg =
"[%d]ERR: %d: %s Unknown Command %s%s"
;
break
;
case
rcOutOfMemory: msg =
"[%d]ERR: %d: %s Out of memory%s%s"
;
break
;
case
rcPerlVarError: msg =
"[%d]ERR: %d: %s Perl variable error %s%s"
;
break
;
case
rcHashError: msg =
"[%d]ERR: %d: %s Perl hash error, %%%s does not exist%s"
;
break
;
case
rcArrayError: msg =
"[%d]ERR: %d: %s Perl array error , @%s does not exist%s"
;
break
;
case
rcFileOpenErr: msg =
"[%d]ERR: %d: %s File %s open error: %s"
;
break
;
case
rcLogFileOpenErr: msg =
"[%d]ERR: %d: %s Logfile %s open error: %s"
;
break
;
case
rcMissingRight: msg =
"[%d]ERR: %d: %s Missing right %s%s"
;
break
;
case
rcNoRetFifo: msg =
"[%d]ERR: %d: %s No Return Fifo%s%s"
;
break
;
case
rcMagicError: msg =
"[%d]ERR: %d: %s Perl Magic Error%s%s"
;
break
;
case
rcWriteErr: msg =
"[%d]ERR: %d: %s File write Error%s%s"
;
break
;
case
rcUnknownNameSpace: msg =
"[%d]ERR: %d: %s Namespace %s unknown%s"
;
break
;
case
rcInputNotSupported: msg =
"[%d]ERR: %d: %s Input not supported in mod_perl mode%s%s"
;
break
;
case
rcCannotUsedRecursive: msg =
"[%d]ERR: %d: %s Cannot be called recursivly in mod_perl mode%s%s"
;
break
;
case
rcEndtableWithoutTablerow: msg =
"[%d]ERR: %d: %s </tr> without <tr>%s%s"
;
break
;
case
rcEndtextareaWithoutTextarea: msg =
"[%d]ERR: %d: %s </textarea> without <textarea>%s%s"
;
break
;
case
rcEvalErr: msg =
"[%d]ERR: %d: %s Error in Perl code: %s%s"
;
break
;
case
rcNotCompiledForModPerl: msg =
"[%d]ERR: %d: %s Embperl is not compiled for mod_perl. Rerun Makefile.PL and give the correct Apache source tree location %s%s"
;
break
;
case
rcExecCGIMissing: msg =
"[%d]ERR: %d: %s Forbidden %s: Options ExecCGI not set in your Apache configs%s"
;
break
;
case
rcIsDir: msg =
"[%d]ERR: %d: %s Forbidden %s is a directory%s"
;
break
;
case
rcXNotSet: msg =
"[%d]ERR: %d: %s Forbidden %s X Bit not set%s"
;
break
;
case
rcNotFound: msg =
"[%d]ERR: %d: %s Not found %s%s"
;
break
;
case
rcUnknownVarType: msg =
"[%d]ERR: %d: %s Type for Variable %s is unknown %s"
;
break
;
case
rcPerlWarn: msg =
"[%d]ERR: %d: %s Warning in Perl code: %s%s"
;
break
;
case
rcVirtLogNotSet: msg =
"[%d]ERR: %d: %s EMBPERL_VIRTLOG must be set, when dbgLogLink is set %s%s"
;
break
;
case
rcMissingInput: msg =
"[%d]ERR: %d: %s Sourcedata missing %s%s"
;
break
;
case
rcUntilWithoutDo: msg =
"[%d]ERR: %d: %s until without do%s%s"
;
break
;
case
rcEndforeachWithoutForeach:msg =
"[%d]ERR: %d: %s endforeach without foreach%s%s"
;
break
;
case
rcMissingArgs: msg =
"[%d]ERR: %d: %s Too few arguments%s%s"
;
break
;
case
rcNotAnArray: msg =
"[%d]ERR: %d: %s Second Argument must be array/list%s%s"
;
break
;
case
rcCallInputFuncFailed: msg =
"[%d]ERR: %d: %s Call to Input Function failed: %s%s"
;
break
;
case
rcCallOutputFuncFailed: msg =
"[%d]ERR: %d: %s Call to Output Function failed: %s%s"
;
break
;
case
rcSubNotFound: msg =
"[%d]ERR: %d: %s Call to unknown Embperl macro %s%s"
;
break
;
case
rcImportStashErr: msg =
"[%d]ERR: %d: %s Package %s for import unknown%s"
;
break
;
case
rcCGIError: msg =
"[%d]ERR: %d: %s Setup of CGI.pm failed: %s%s"
;
break
;
case
rcUnclosedHtml: msg =
"[%d]ERR: %d: %s Unclosed HTML tag <%s> at end of file %s"
;
break
;
case
rcUnclosedCmd: msg =
"[%d]ERR: %d: %s Unclosed command [$ %s $] at end of file %s"
;
break
;
case
rcNotAllowed: msg =
"[%d]ERR: %d: %s Forbidden %s: Does not match EMBPERL_ALLOW %s"
;
break
;
case
rcNotHashRef: msg =
"[%d]ERR: %d: %s %s need hashref in %s"
;
break
;
case
rcTagMismatch: msg =
"[%d]ERR: %d: %s Endtag '%s' doesn't match starttag '%s'"
;
break
;
case
rcCleanupErr: msg =
"[%d]ERR: %d: %s Error in cleanup %s%s"
;
break
;
case
rcCryptoWrongHeader: msg =
"[%d]ERR: %d: %s Decrypt-error: Not encrypted (%s)%s"
;
break
;
case
rcCryptoWrongSyntax: msg =
"[%d]ERR: %d: %s Decrypt-error: Wrong syntax (%s)%s"
;
break
;
case
rcCryptoNotSupported: msg =
"[%d]ERR: %d: %s Decrypt-error: Not supported (%s)%s"
;
break
;
case
rcCryptoBufferOverflow: msg =
"[%d]ERR: %d: %s Decrypt-error: Buffer overflow (%s)%s"
;
break
;
case
rcCryptoErr: msg =
"[%d]ERR: %d: %s Decrypt-error: OpenSSL error (%s)%s"
;
break
;
default
: msg =
"[%d]ERR: %d: %s Error %s%s"
;
break
;
}
if
((rc != rcPerlWarn && rc != rcEvalErr) || r -> errdat1[0] ==
'\0'
)
{
char
* p = NULL ;
char
buf[20] =
""
;
if
(!r -> Buf.pFile || !r -> Buf.pFile -> sSourcefile)
p =
""
;
if
(!p)
p =
strrchr
(r -> Buf.pFile -> sSourcefile,
'/'
) ;
if
(p)
p++ ;
else
{
p =
strrchr
(r -> Buf.pFile -> sSourcefile,
'\\'
) ;
if
(!p)
p = r -> Buf.pFile -> sSourcefile ;
else
p++ ;
}
if
(r -> Buf.nSourceline)
sprintf
(buf,
"(%d)"
, r -> Buf.nSourceline) ;
pSVLine = newSVpvf (
"%s%s:"
, p, buf) ;
}
pSV = newSVpvf (msg, r -> nPid , rc, pSVLine?SvPV(pSVLine, l):
""
, r -> errdat1, r -> errdat2) ;
if
(r -> bOptions & optShowBacktrace)
{
req * l = r ;
while
(l && l != &InitialReq)
{
sv_catpvf(pSV,
"\n * %s"
, (!l -> Buf.pFile || !l -> Buf.pFile -> sSourcefile)?
"<no filename available>"
:l -> Buf.pFile -> sSourcefile) ;
l = l -> pLastReq ;
}
}
if
(pSVLine)
SvREFCNT_dec(pSVLine) ;
sText = SvPV (pSV, l) ;
lprintf (r,
"%s\n"
, sText) ;
#ifdef APACHE
if
(r -> pApacheReq)
#ifdef APLOG_ERR
if
(rc != rcPerlWarn)
aplog_error (APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r -> pApacheReq -> server,
"%s"
, sText) ;
else
aplog_error (APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, r -> pApacheReq -> server,
"%s"
, sText) ;
#else
log_error (sText, r -> pApacheReq -> server) ;
#endif
else
#endif
{
#ifdef WIN32
if
(r -> nIOType != epIOCGI)
#endif
{
PerlIO_printf (PerlIO_stderr(),
"%s\n"
, sText) ;
fflush
(stderr) ;
}
}
if
(rc == rcPerlWarn)
strncpy
(r -> lastwarn, r -> errdat1,
sizeof
(r -> lastwarn) - 1) ;
if
(r -> pErrArray)
{
av_push (r -> pErrArray, pSV) ;
av_store (r -> pErrFill, r -> nMarker, newSViv (AvFILL(r -> pErrArray))) ;
av_store (r -> pErrState, r -> nMarker, newSViv (r -> bError)) ;
n = r -> nMarker ;
while
(n-- > 0)
{
ppSV = av_fetch (r -> pErrFill, n, 0) ;
if
(ppSV && SvOK (*ppSV))
break
;
av_store (r -> pErrFill, n, newSViv (r -> nLastErrFill)) ;
av_store (r -> pErrState, n, newSViv (r -> bLastErrState)) ;
}
r -> nLastErrFill = AvFILL(r -> pErrArray) ;
r -> bLastErrState = r -> bError ;
}
r -> errdat1[0] =
'\0'
;
r -> errdat2[0] =
'\0'
;
return
sText ;
}
void
CommitError (
register
req * r)
{
int
f = AvFILL(r -> pErrArray) ;
int
n ;
SV ** ppSV ;
if
(f == -1)
return
;
av_store (r -> pErrFill, r -> nMarker, newSViv (f)) ;
av_store (r -> pErrState, r -> nMarker, newSViv (r -> bError)) ;
n = r -> nMarker ;
while
(n-- > 0)
{
ppSV = av_fetch (r -> pErrFill, n, 0) ;
if
(ppSV && SvOK (*ppSV))
break
;
av_store (r -> pErrFill, n, newSViv (r -> nLastErrFill)) ;
av_store (r -> pErrState, n, newSViv (r -> bLastErrState)) ;
}
}
void
RollbackError (
register
req * r)
{
SV * pFill ;
SV * pState ;
SV ** ppSV ;
I32 f = AvFILL (r -> pErrFill) ;
int
n ;
int
i ;
if
(f < r -> nMarker)
return
;
for
(i = f; i > r -> nMarker; i--)
{
pFill = av_pop(r -> pErrFill) ;
pState = av_pop(r -> pErrState) ;
SvREFCNT_dec (pFill) ;
SvREFCNT_dec (pState) ;
}
ppSV = av_fetch(r -> pErrFill, r -> nMarker, 0) ;
if
(ppSV)
n = SvIV (*ppSV) ;
else
{
n = 0 ;
}
ppSV = av_fetch(r -> pErrState, r -> nMarker, 0) ;
if
(ppSV)
r -> bError = SvIV (*ppSV) ;
else
r -> bError = 1 ;
f = AvFILL (r -> pErrArray) ;
if
(f > n)
lprintf (r,
"[%d]ERR: Discard the last %d errormessages, because they occured after the end of a table\n"
, r -> nPid, f - n) ;
for
(i = f; i > n; i--)
{
SvREFCNT_dec (av_pop(r -> pErrArray)) ;
}
r -> nLastErrFill = AvFILL(r -> pErrArray) ;
r -> bLastErrState = r -> bError ;
}
void
NewEscMode (
register
req * r,
SV * pSV)
{
if
(r -> nEscMode & escHtml && !r -> bEscInUrl)
r -> pNextEscape = Char2Html ;
else
if
(r -> nEscMode & escUrl)
r -> pNextEscape = Char2Url ;
else
r -> pNextEscape = NULL ;
if
(r -> bEscModeSet < 1)
{
r -> pCurrEscape = r -> pNextEscape ;
r -> nCurrEscMode = r -> nEscMode ;
}
if
(r -> bEscModeSet < 0 && pSV && SvOK (pSV))
r -> bEscModeSet = 1 ;
}
static
int
notused ;
INTMG (TabCount, pCurrReq -> TableStack.State.nCount, pCurrReq -> TableStack.State.nCountUsed, ;)
INTMG (TabRow, pCurrReq -> TableStack.State.nRow, pCurrReq -> TableStack.State.nRowUsed, ;)
INTMG (TabCol, pCurrReq -> TableStack.State.nCol, pCurrReq -> TableStack.State.nColUsed, ;)
INTMG (TabMaxRow, pCurrReq -> nTabMaxRow, notused, ;)
INTMG (TabMaxCol, pCurrReq -> nTabMaxCol, notused, ;)
INTMG (TabMode, pCurrReq -> nTabMode, notused, ;)
INTMG (EscMode, pCurrReq -> nEscMode, notused, NewEscMode (pCurrReq, pSV))
#ifdef EP2
INTMGshort (CurrNode, pCurrReq -> xCurrNode)
#endif
OPTMGRD (optDisableVarCleanup , pCurrReq -> bOptions)
OPTMG (optDisableEmbperlErrorPage, pCurrReq -> bOptions)
OPTMG (optReturnError , pCurrReq -> bOptions)
OPTMGRD (optSafeNamespace , pCurrReq -> bOptions)
OPTMGRD (optOpcodeMask , pCurrReq -> bOptions)
OPTMG (optRawInput , pCurrReq -> bOptions)
OPTMG (optSendHttpHeader , pCurrReq -> bOptions)
OPTMGRD (optDisableChdir , pCurrReq -> bOptions)
OPTMG (optDisableHtmlScan , pCurrReq -> bOptions)
OPTMGRD (optEarlyHttpHeader , pCurrReq -> bOptions)
OPTMGRD (optDisableFormData , pCurrReq -> bOptions)
OPTMG (optDisableInputScan , pCurrReq -> bOptions)
OPTMG (optDisableTableScan , pCurrReq -> bOptions)
OPTMG (optDisableMetaScan , pCurrReq -> bOptions)
OPTMGRD (optAllFormData , pCurrReq -> bOptions)
OPTMGRD (optRedirectStdout , pCurrReq -> bOptions)
OPTMG (optUndefToEmptyValue , pCurrReq -> bOptions)
OPTMG (optNoHiddenEmptyValue , pCurrReq -> bOptions)
OPTMGRD (optAllowZeroFilesize , pCurrReq -> bOptions)
OPTMGRD (optKeepSrcInMemory , pCurrReq -> bOptions)
OPTMG (optKeepSpaces , pCurrReq -> bOptions)
OPTMG (optOpenLogEarly , pCurrReq -> bOptions)
OPTMG (optNoUncloseWarn , pCurrReq -> bOptions)
OPTMG (dbgStd , pCurrReq -> bDebug)
OPTMG (dbgMem , pCurrReq -> bDebug)
OPTMG (dbgEval , pCurrReq -> bDebug)
OPTMG (dbgCmd , pCurrReq -> bDebug)
OPTMG (dbgEnv , pCurrReq -> bDebug)
OPTMG (dbgForm , pCurrReq -> bDebug)
OPTMG (dbgTab , pCurrReq -> bDebug)
OPTMG (dbgInput , pCurrReq -> bDebug)
OPTMG (dbgFlushOutput , pCurrReq -> bDebug)
OPTMG (dbgFlushLog , pCurrReq -> bDebug)
OPTMG (dbgAllCmds , pCurrReq -> bDebug)
OPTMG (dbgSource , pCurrReq -> bDebug)
OPTMG (dbgFunc , pCurrReq -> bDebug)
OPTMG (dbgLogLink , pCurrReq -> bDebug)
OPTMG (dbgDefEval , pCurrReq -> bDebug)
OPTMG (dbgHeadersIn , pCurrReq -> bDebug)
OPTMG (dbgShowCleanup , pCurrReq -> bDebug)
OPTMG (dbgProfile , pCurrReq -> bDebug)
OPTMG (dbgSession , pCurrReq -> bDebug)
OPTMG (dbgImport , pCurrReq -> bDebug)
static
int
GetFormData (
register
req * r,
char
* pQueryString,
int
nLen)
{
int
num ;
char
* p ;
char
* pMem ;
int
nVal ;
int
nKey ;
char
* pKey ;
char
* pVal ;
SV * pSVV ;
SV * pSVK ;
SV * * ppSV ;
EPENTRY (GetFormData) ;
hv_clear (r -> pFormHash) ;
hv_clear (r -> pFormSplitHash) ;
#ifdef HASHTEST
pHash = perl_get_hv (sFormHashName, FALSE) ;
if
(pHash != r -> pFormHash)
{
strcpy
(r -> errdat1, sFormHashName) ;
strcpy
(r -> errdat2,
" !!C-Adress differs from Perl-Adress!! in GetFormData"
) ;
LogError (r, rcHashError) ;
}
#endif
if
(nLen == 0)
return
ok ;
if
((pMem = _malloc (r, nLen + 4)) == NULL)
return
rcOutOfMemory ;
p = pMem ;
nKey = nVal = 0 ;
pKey = pVal = p ;
while
(1)
{
switch
(nLen > 0?*pQueryString:
'\0'
)
{
case
'+'
:
pQueryString++ ;
nLen-- ;
*p++ =
' '
;
break
;
case
'%'
:
pQueryString++ ;
nLen-- ;
num = 0 ;
if
(*pQueryString)
{
if
(
toupper
(*pQueryString) >=
'A'
)
num += (
toupper
(*pQueryString) -
'A'
+ 10) << 4 ;
else
num += ((*pQueryString) -
'0'
) << 4 ;
pQueryString++ ;
}
if
(*pQueryString)
{
if
(
toupper
(*pQueryString) >=
'A'
)
num += (
toupper
(*pQueryString) -
'A'
+ 10) ;
else
num += ((*pQueryString) -
'0'
) ;
pQueryString++ ;
nLen-- ;
}
*p++ = num ;
break
;
case
'='
:
nKey = p - pKey ;
*p++ = r -> pConf -> cMultFieldSep ;
nVal = 0 ;
pVal = p ;
pQueryString++ ;
nLen-- ;
break
;
case
';'
:
case
'&'
:
pQueryString++ ;
nLen-- ;
case
'\0'
:
nVal = p - pVal ;
*p++ =
'\0'
;
if
(nKey > 0 && (nVal > 0 || (r -> bOptions & optAllFormData)))
{
char
* sid = r -> pConf -> sCookieName ;
if
(sid)
{
if
(
strncmp
(pKey, sid, nKey) != 0)
sid = NULL ;
}
if
(sid == NULL)
{
if
(pVal > pKey)
pVal[-1] =
'\0'
;
if
((ppSV = hv_fetch (r -> pFormHash, pKey, nKey, 0)))
{
sv_catpvn (*ppSV, &r -> pConf -> cMultFieldSep, 1) ;
sv_catpvn (*ppSV, pVal, nVal) ;
}
else
{
pSVV = newSVpv (pVal, nVal) ;
if
(hv_store (r -> pFormHash, pKey, nKey, pSVV, 0) == NULL)
{
_free (r, pMem) ;
return
rcHashError ;
}
pSVK = newSVpv (pKey, nKey) ;
av_push (r -> pFormArray, pSVK) ;
}
if
(r -> bDebug & dbgForm)
lprintf (r,
"[%d]FORM: %s=%s\n"
, r -> nPid, pKey, pVal) ;
}
}
pKey = pVal = p ;
nKey = nVal = 0 ;
if
(*pQueryString ==
'\0'
)
{
_free (r, pMem) ;
return
ok ;
}
break
;
default
:
*p++ = *pQueryString++ ;
nLen-- ;
break
;
}
}
}
#ifdef comment
static
int
GetInputData_CGIProcess (
register
req * r)
{
char
* p ;
int
rc = ok ;
int
state = 0 ;
int
len = 0 ;
char
sLine [1024] ;
SV * pSVE ;
int
savewarn = dowarn ;
dowarn = 0 ;
EPENTRY (GetInputData_CGIProcess) ;
hv_clear (r -> pEnvHash) ;
if
(r -> bDebug)
lprintf (r,
"\n[%d]Waiting for Request... SVs: %d OBJs: %d\n"
, r -> nPid, sv_count, sv_objcount) ;
if
((rc = OpenInput (r, sCmdFifo)) != ok)
{
dowarn = savewarn ;
return
rc ;
}
if
(r -> bDebug)
lprintf (r,
"[%d]Processing Request...\n"
, r -> nPid) ;
while
(igets (sLine,
sizeof
(sLine)))
{
len =
strlen
(sLine) ;
while
(len >= 0 &&
isspace
(sLine [--len]))
;
sLine [len + 1] =
'\0'
;
if
(
strcmp
(sLine,
"----"
) == 0)
{ state = 1 ;
if
(r -> bDebug) lprintf (r,
"[%d]Environment...\n"
, r -> nPid) ;}
else
if
(
strcmp
(sLine,
"****"
) == 0)
{ state = 2 ;
if
(r -> bDebug) lprintf (r,
"[%d]Formdata...\n"
, r -> nPid) ;}
else
if
(state == 1)
{
p =
strchr
(sLine,
'='
) ;
*p =
'\0'
;
p++ ;
pSVE = newSVpv (p,
strlen
(p)) ;
if
(hv_store (r -> pEnvHash, sLine,
strlen
(sLine), pSVE, 0) == NULL)
{
dowarn = savewarn ;
return
rcHashError ;
}
if
(r -> bDebug & dbgEnv)
lprintf (r,
"[%d]ENV: %s=%s\n"
, r -> nPid, sLine, p) ;
}
else
if
(state == 2)
{
len =
atoi
(sLine) ;
if
((p = _malloc (len + 1)) == NULL)
{
dowarn = savewarn ;
return
rcOutOfMemory ;
}
iread (p, len) ;
p[len] =
'\0'
;
rc = GetFormData (p, len) ;
_free (p) ;
break
;
}
else
{
if
(r -> bDebug) lprintf (r,
"[%d]Unknown Input: %s\n"
, r -> nPid, sLine) ;}
}
CloseInput () ;
dowarn = savewarn ;
return
rc ;
}
#endif
static
int
GetInputData_CGIScript (
register
req * r)
{
char
* p = NULL ;
char
* f ;
int
rc = ok ;
STRLEN len = 0 ;
char
sLen [20] ;
EPENTRY (GetInputData_CGIScript) ;
#ifdef APACHE
if
(r -> pApacheReq && (r -> bDebug & dbgHeadersIn))
{
int
i;
array_header *hdrs_arr;
table_entry *hdrs;
hdrs_arr = table_elts (r -> pApacheReq->headers_in);
hdrs = (table_entry *)hdrs_arr->elts;
lprintf (r,
"[%d]HDR: %d\n"
, r -> nPid, hdrs_arr->nelts) ;
for
(i = 0; i < hdrs_arr->nelts; ++i)
if
(hdrs[i].key)
lprintf (r,
"[%d]HDR: %s=%s\n"
, r -> nPid, hdrs[i].key, hdrs[i].val) ;
}
#endif
if
(r -> bDebug & dbgEnv)
{
SV * psv ;
HE * pEntry ;
char
* pKey ;
I32 l ;
int
savewarn = dowarn ;
dowarn = 0 ;
hv_iterinit (r -> pEnvHash) ;
while
((pEntry = hv_iternext (r -> pEnvHash)))
{
pKey = hv_iterkey (pEntry, &l) ;
psv = hv_iterval (r -> pEnvHash, pEntry) ;
lprintf (r,
"[%d]ENV: %s=%s\n"
, r -> nPid, pKey, SvPV (psv, na)) ;
}
dowarn = savewarn ;
}
#ifdef APACHE
if
(r -> pApacheReq)
{
const
char
* sLength = table_get(r -> pApacheReq->headers_in,
"Content-Length"
) ;
len = sLength?
atoi
(sLength):0 ;
}
else
#endif
{
sLen [0] =
'\0'
;
GetHashValue (r -> pEnvHash,
"CONTENT_LENGTH"
,
sizeof
(sLen) - 1, sLen) ;
len =
atoi
(sLen) ;
}
if
(len == 0)
{
SV * * ppSV = hv_fetch(r -> pEnvHash,
"QUERY_STRING"
,
sizeof
(
"QUERY_STRING"
) - 1, 0) ;
if
(ppSV != NULL)
{
p = SvPV (*ppSV ,len) ;
}
else
len = 0 ;
f = NULL ;
}
else
{
if
((p = _malloc (r, len + 1)) == NULL)
return
rcOutOfMemory ;
if
((rc = OpenInput (r, NULL)) != ok)
{
_free (r, p) ;
return
rc ;
}
iread (r, p, len) ;
CloseInput (r) ;
p[len] =
'\0'
;
f = p ;
}
if
(r -> bDebug)
lprintf (r,
"[%d]Formdata... length = %d\n"
, r -> nPid, len) ;
rc = GetFormData (r, p, len) ;
#ifdef EP2
if
(!f && len > 0)
{
if
((f = _malloc (r, len + 1)) == NULL)
return
rcOutOfMemory ;
memcpy
(f, p, len) ;
p[len] =
'\0'
;
}
if
(len > 0)
{
r -> sQueryInfo = f ;
f[len] =
'\0'
;
}
#else
if
(f)
_free (r, f) ;
#endif
return
rc ;
}
static
int
ScanCmdEvals (
register
req * r,
char
* p)
{
int
rc ;
char
* c ;
char
* a ;
char
nType ;
SV * pRet ;
struct
tCmd * pCmd ;
char
* pAfterWS ;
int
nFilepos = p - r -> Buf.pBuf ;
SV ** ppSV ;
AV * pAV ;
HV * pHV ;
STRLEN l ;
I32 li ;
EPENTRY (ScanCmdEvals) ;
p++ ;
r -> Buf.pCurrPos = p ;
if
((nType = *p++) ==
'\0'
)
return
ok ;
r -> Buf.pCurrPos = p ;
if
(nType !=
'+'
&& nType !=
'-'
&& nType !=
'$'
&& nType !=
'!'
&& nType !=
'#'
)
{
if
(r -> CmdStack.State.bProcessCmds == cmdAll)
{
if
(nType !=
'['
)
oputc (r,
'['
) ;
oputc (r, nType) ;
}
return
ok ;
}
ppSV = hv_fetch(r -> Buf.pFile -> pCacheHash, (
char
*)&nFilepos,
sizeof
(nFilepos), 1) ;
if
(ppSV == NULL)
return
rcHashError ;
if
(*ppSV != NULL && SvTYPE (*ppSV) == SVt_IV)
{
p = p + SvIV(*ppSV) ;
}
else
{
do
{
p++ ;
if
((p =
strchr
(p,
']'
)) == NULL)
break
;
}
while
(p[-1] != nType) ;
if
(p == NULL)
{
sprintf
(r -> errdat1,
"%c]"
, nType) ;
return
rcMissingRight ;
}
SvREFCNT_dec (*ppSV) ;
*ppSV = newSViv (p - r -> Buf.pCurrPos) ;
}
p [-1] =
'\0'
;
p++ ;
pAfterWS = p;
if
((r -> bOptions & optKeepSpaces) == 0)
{
while
(
isspace
(*pAfterWS))
pAfterWS++ ;
if
(nType ==
'+'
&& pAfterWS > p)
pAfterWS-- ;
}
switch
(nType)
{
case
'+'
:
if
(r -> CmdStack.State.bProcessCmds == cmdAll)
{
r -> bEscModeSet = -1 ;
r -> pNextEscape = r -> pCurrEscape ;
rc = EvalTrans (r, r -> Buf.pCurrPos, (r -> Buf.pCurrPos - r -> Buf.pBuf), &pRet) ;
if
(rc != ok && rc != rcEvalErr)
return
rc ;
if
(pRet)
{
if
(r -> bEscInUrl && SvTYPE(pRet) == SVt_RV && (pAV = (AV *)SvRV(pRet)))
{
if
(SvTYPE(pAV) == SVt_PVAV)
{
SV ** ppSV ;
int
i ;
int
f = AvFILL(pAV) ;
for
(i = 0; i <= f; i++)
{
ppSV = av_fetch (pAV, i, 0) ;
if
(ppSV && *ppSV)
{
OutputToHtml (r, SvPV (*ppSV, l)) ;
}
if
((i & 1) == 0)
oputc (r,
'='
) ;
else
if
(i < f)
oputs (r,
"&"
) ;
}
}
else
if
(SvTYPE(pAV) == SVt_PVHV)
{
int
i = 0 ;
HE * pEntry ;
char
* pKey ;
SV * pSVValue ;
pHV = (HV *)pAV ;
hv_iterinit (pHV) ;
while
(pEntry = hv_iternext (pHV))
{
if
(i++ > 0)
oputs (r,
"&"
) ;
pKey = hv_iterkey (pEntry, &li) ;
OutputToHtml (r, pKey) ;
oputc (r,
'='
) ;
pSVValue = hv_iterval (pHV , pEntry) ;
if
(pSVValue)
OutputToHtml (r, SvPV (pSVValue, l)) ;
}
}
}
else
{
if
(r -> pCurrEscape == NULL)
{
char
* p = SvPV (pRet, l) ;
owrite (r, p, l) ;
}
else
OutputToHtml (r, SvPV (pRet, l)) ;
}
SvREFCNT_dec (pRet) ;
}
r -> pCurrEscape = r -> pNextEscape ;
r -> bEscModeSet = 0 ;
}
p [-2] = nType ;
r -> Buf.pCurrPos = pAfterWS ;
break
;
case
'-'
:
if
(r -> CmdStack.State.bProcessCmds == cmdAll)
{
rc = EvalTrans (r, r -> Buf.pCurrPos, (r -> Buf.pCurrPos - r -> Buf.pBuf), &pRet) ;
if
(rc != ok && rc != rcEvalErr)
return
rc ;
if
(pRet)
SvREFCNT_dec (pRet) ;
}
p [-2] = nType ;
r -> Buf.pCurrPos = pAfterWS ;
break
;
case
'!'
:
if
(r -> CmdStack.State.bProcessCmds == cmdAll)
{
rc = EvalTransOnFirstCall (r, r -> Buf.pCurrPos, (r -> Buf.pCurrPos - r -> Buf.pBuf), &pRet) ;
if
(rc != ok && rc != rcEvalErr)
return
rc ;
if
(pRet)
SvREFCNT_dec (pRet) ;
}
p [-2] = nType ;
r -> Buf.pCurrPos = pAfterWS ;
break
;
case
'#'
:
p [-2] = nType ;
r -> Buf.pCurrPos = pAfterWS ;
break
;
case
'$'
:
TransHtml (r, r -> Buf.pCurrPos, 0) ;
while
(*r -> Buf.pCurrPos !=
'\0'
&&
isspace
(*r -> Buf.pCurrPos))
r -> Buf.pCurrPos++ ;
a = c = r -> Buf.pCurrPos ;
while
(*a !=
'\0'
&&
isalpha
(*a))
a++ ;
r -> Buf.pCurrPos = p ;
if
((rc = SearchCmd (r, c, a-c, a, FALSE, &pCmd)) != ok)
return
rc ;
if
((rc = ProcessCmd (r, pCmd, a)) != ok)
{
p [-2] = nType ;
return
rc ;
}
p [-2] = nType ;
if
(r -> Buf.pCurrPos == p)
r -> Buf.pCurrPos = pAfterWS ;
break
;
}
return
ok ;
}
int
ScanCmdEvalsInString (
register
req * r,
char
* pIn,
char
* * pOut,
size_t
nSize,
char
* * pFree)
{
int
rc ;
char
* pSaveCurrPos ;
char
* pSaveCurrStart ;
char
* pSaveEndPos ;
char
* pSaveLineNo ;
char
* p =
strchr
(pIn,
'['
);
EPENTRY (ScanCmdEvalsInString) ;
*pFree = NULL ;
if
(p == NULL)
{
*pOut = pIn ;
return
ok ;
}
pSaveCurrPos = r -> Buf.pCurrPos ;
pSaveCurrStart = r -> Buf.pCurrStart ;
pSaveEndPos = r -> Buf.pEndPos ;
pSaveLineNo = r -> Buf.pLineNoCurrPos ;
if
(r -> Buf.pLineNoCurrPos == NULL)
r -> Buf.pLineNoCurrPos = r -> Buf.pCurrPos ;
r -> Buf.pCurrPos = pIn ;
r -> Buf.pEndPos = pIn +
strlen
(pIn) ;
*pOut = _malloc (r, nSize) ;
if
(*pOut == NULL)
return
rcOutOfMemory ;
OutputToMemBuf (r, *pOut, nSize) ;
rc = ok ;
while
(r -> Buf.pCurrPos < r -> Buf.pEndPos && rc == ok)
{
if
(p == NULL || *p ==
'\0'
)
{
owrite (r, r -> Buf.pCurrPos, r -> Buf.pEndPos - r -> Buf.pCurrPos) ;
break
;
}
if
(r -> CmdStack.State.bProcessCmds == cmdAll)
{
owrite (r, r -> Buf.pCurrPos, p - r -> Buf.pCurrPos) ;
}
if
(r -> bDebug & dbgSource)
{
char
* s = p ;
char
* n ;
while
(*s &&
isspace
(*s))
s++ ;
if
(*s)
{
n =
strchr
(s,
'\n'
) ;
#ifdef CLOCKS_PER_SEC
if
(r -> bDebug & dbgProfile)
if
(n)
lprintf (r,
"[%d]SRC: Time: %d ms %*.*s\n"
, r -> nPid, ((
clock
() - r -> startclock) * 1000 / CLOCKS_PER_SEC), n-s, n-s, s) ;
else
lprintf (r,
"[%d]SRC: Time: %d ms %70.70s\n"
, r -> nPid, ((
clock
() - r -> startclock) * 1000 / CLOCKS_PER_SEC), s) ;
else
#endif
if
(n)
lprintf (r,
"[%d]SRC: %*.*s\n"
, r -> nPid, n-s, n-s, s) ;
else
lprintf (r,
"[%d]SRC: %70.70s\n"
, r -> nPid, s) ;
}
}
r -> Buf.pCurrStart = p ;
rc = ScanCmdEvals (r, p) ;
p =
strchr
(r -> Buf.pCurrPos,
'['
) ;
}
*pFree = *pOut = OutputToStd (r) ;
r -> Buf.pCurrPos = pSaveCurrPos ;
r -> Buf.pCurrStart = pSaveCurrStart ;
r -> Buf.pEndPos = pSaveEndPos ;
r -> Buf.pLineNoCurrPos = pSaveLineNo ;
return
rc ;
}
static
int
ScanHtmlTag (
register
req * r,
char
* p)
{
int
rc ;
char
ec ;
char
ea = 0 ;
char
* pec ;
char
* pea ;
char
* pCmd ;
char
* pArg ;
char
* pArgBuf = NULL ;
char
* pFreeBuf = NULL ;
struct
tCmd * pCmdInfo ;
EPENTRY (ScanHtmlTag) ;
r -> Buf.pCurrTag = p ;
p++ ;
while
(*p !=
'\0'
&&
isspace
(*p))
p++ ;
pCmd = p ;
while
(*p !=
'\0'
&& !
isspace
(*p) && *p !=
'>'
)
p++ ;
ec = *p ;
pec = p ;
*p++ =
'\0'
;
if
((rc = SearchCmd (r, pCmd, pec - pCmd,
""
, TRUE, &pCmdInfo)) != ok)
{
*pec = ec ;
oputc (r, *r -> Buf.pCurrTag) ;
r -> Buf.pCurrPos = r -> Buf.pCurrTag + 1 ;
if
(rc == rcCmdNotFound)
return
ok ;
return
rc ;
}
pArg = p ;
if
(ec ==
'>'
)
{
pArg = p - 1 ;
pea = NULL ;
}
else
{
char
nType =
'\0'
;
while
((*p !=
'>'
|| nType) && *p !=
'\0'
)
{
if
(nType ==
'\0'
&& *p ==
'['
&& (p[1] ==
'+'
|| p[1] ==
'-'
|| p[1] ==
'$'
|| p[1] ==
'!'
|| p[1] ==
'#'
))
nType = *++p ;
else
if
(nType && *p == nType && p[1] ==
']'
)
{
nType =
'\0'
;
p++ ;
}
p++;
}
if
(*p ==
'>'
)
{
ea = *p ;
pea = p ;
*p =
'\0'
;
p++ ;
}
else
{
p = pArg +
strlen
(pArg) ;
pea = NULL ;
}
}
r -> Buf.pCurrPos = p ;
if
(*pArg !=
'\0'
&& pCmdInfo -> bScanArg)
{
if
((rc = ScanCmdEvalsInString (r, (
char
*)pArg, &pArgBuf, nInitialScanOutputSize, &pFreeBuf)) != ok)
{
if
(pFreeBuf)
_free (r, pFreeBuf) ;
return
rc ;
}
}
else
pArgBuf = pArg ;
if
((rc = ProcessCmd (r, pCmdInfo, pArgBuf)) != ok)
{
if
(rc == rcCmdNotFound)
{
}
else
{
if
(pFreeBuf)
_free (r, pFreeBuf) ;
*pec = ec ;
if
(pea)
*pea = ea ;
return
rc ;
}
}
if
(p == r -> Buf.pCurrPos && r -> Buf.pCurrPos)
{
if
(pArg == pArgBuf)
{
*pec = ec ;
if
(pea)
*pea = ea ;
oputc (r, *r -> Buf.pCurrTag) ;
r -> Buf.pCurrPos = r -> Buf.pCurrTag + 1 ;
}
else
{
oputs (r, r -> Buf.pCurrTag) ;
oputc (r,
' '
) ;
oputs (r, pArgBuf) ;
oputc (r,
'>'
) ;
*pec = ec ;
if
(pea)
*pea = ea ;
}
}
else
{
*pec = ec ;
if
(pea)
*pea = ea ;
}
if
(r -> Buf.pCurrPos == NULL)
r -> Buf.pCurrPos = p ;
if
(pFreeBuf)
_free (r, pFreeBuf) ;
r -> Buf.pCurrTag = NULL ;
return
ok ;
}
static
int
AddMagic (
register
req * r,
char
* sVarName,
MGVTBL * pVirtTab)
{
SV * pSV ;
struct
magic * pMagic ;
EPENTRY (AddMagic) ;
pSV = perl_get_sv (sVarName, TRUE) ;
sv_magic (pSV, NULL, 0, sVarName,
strlen
(sVarName)) ;
sv_setiv (pSV, 0) ;
pMagic = mg_find (pSV, 0) ;
if
(pMagic)
pMagic -> mg_virtual = pVirtTab ;
else
{
LogError (r, rcMagicError) ;
return
1 ;
}
return
ok ;
}
int
AddMagicAV (
register
req * r,
char
* sVarName,
MGVTBL * pVirtTab)
{
SV * pSV ;
struct
magic * pMagic ;
EPENTRY (AddMagicAV) ;
pSV = (SV *)perl_get_av (sVarName, TRUE) ;
sv_magic (pSV, NULL,
'P'
, sVarName,
strlen
(sVarName)) ;
pMagic = mg_find (pSV, 0) ;
if
(pMagic)
pMagic -> mg_virtual = pVirtTab ;
else
{
LogError (r, rcMagicError) ;
return
1 ;
}
return
ok ;
}
int
Init (
int
_nIOType,
const
char
* sLogFile,
int
nDebugDefault)
{
int
rc ;
#ifdef EP2
HV * pTokenHash ;
#endif
req * r = &InitialReq ;
pCurrReq = r ;
r -> nIOType = _nIOType ;
#if PERL_VERSION >= 8
#if PERL_SUBVERSION >= 50 || PERL_VERSION >= 6
memcpy
(&ep_sv_undef, &PL_sv_undef,
sizeof
(PL_sv_undef)) ;
#else
memcpy
(&ep_sv_undef, &sv_undef,
sizeof
(sv_undef)) ;
#endif
#endif
#ifdef APACHE
r -> pApacheReq = NULL ;
if
(_nIOType == epIOMod_Perl)
{
embperl_ApacheAddModule () ;
}
#endif
r -> bReqRunning = 0 ;
r -> bDebug = nDebugDefault ;
r -> nPid = getpid () ;
r -> Buf.nSourceline = 1 ;
r -> Buf.pSourcelinePos = NULL ;
r -> Buf.pLineNoCurrPos = NULL ;
r -> nEscMode = escStd ;
r -> nCurrEscMode = escStd ;
if
((rc = OpenLog (r, sLogFile, ((r -> bDebug & dbgFunc) || (r -> bOptions & optOpenLogEarly))?1:0)) != ok)
{
r -> bDebug = 0 ;
LogError (r, rc) ;
}
EPENTRY (iembperl_init) ;
if
(r -> bDebug)
{
char
* p ;
switch
(r -> nIOType)
{
#ifdef APACHE
case
epIOMod_Perl: p =
"mod_perl"
;
break
;
#else
case
epIOMod_Perl: p =
"mod_perl UNSUPPORTED"
;
break
;
#endif
case
epIOPerl: p =
"Offline"
;
break
;
case
epIOCGI: p =
"CGI-Script"
;
break
;
case
epIOProcess: p =
"Demon"
;
break
;
default
: p =
"unknown"
;
break
;
}
}
#ifndef APACHE
if
(r -> nIOType == epIOMod_Perl)
{
LogError (r, rcNotCompiledForModPerl) ;
return
1 ;
}
#endif
if
(bInitDone)
return
ok ;
if
((r -> pFormHash = perl_get_hv (sFormHashName, TRUE)) == NULL)
{
LogError (r, rcHashError) ;
return
1 ;
}
if
((r -> pUserHash = perl_get_hv (sUserHashName, TRUE)) == NULL)
{
LogError (r, rcHashError) ;
return
1 ;
}
if
((r -> pStateHash = perl_get_hv (sStateHashName, TRUE)) == NULL)
{
LogError (r, rcHashError) ;
return
1 ;
}
if
((r -> pModHash = perl_get_hv (sModHashName, TRUE)) == NULL)
{
LogError (r, rcHashError) ;
return
1 ;
}
if
((r -> pFormSplitHash = perl_get_hv (sFormSplitHashName, TRUE)) == NULL)
{
LogError (r, rcHashError) ;
return
1 ;
}
if
((r -> pFormArray = perl_get_av (sFormArrayName, TRUE)) == NULL)
{
LogError (r, rcArrayError) ;
return
1 ;
}
if
((r -> pHeaderHash = perl_get_hv (sHeaderHashName, TRUE)) == NULL)
{
LogError (r, rcHashError) ;
return
1 ;
}
if
((r -> pInputHash = perl_get_hv (sInputHashName, TRUE)) == NULL)
{
LogError (r, rcHashError) ;
return
1 ;
}
if
((r -> pEnvHash = perl_get_hv (sEnvHashName, TRUE)) == NULL)
{
LogError (r, rcHashError) ;
return
1 ;
}
if
(!(pCacheHash = newHV ()))
{
LogError (r, rcHashError) ;
return
1 ;
}
if
(!(r -> pErrFill = newAV ()))
{
LogError (r, rcArrayError) ;
return
1 ;
}
if
(!(r -> pErrState = newAV ()))
{
LogError (r, rcArrayError) ;
return
1 ;
}
if
(!(r -> pErrArray = newAV ()))
{
LogError (r, rcArrayError) ;
return
1 ;
}
#ifdef EP2
if
(!(r -> pDomTreeAV = newAV ()))
{
LogError (r, rcArrayError) ;
return
1 ;
}
if
(!(r -> pCleanupAV = newAV ()))
{
LogError (r, rcArrayError) ;
return
1 ;
}
#endif
rc = 0 ;
ADDINTMG (TabCount)
ADDINTMG (TabRow)
ADDINTMG (TabCol)
ADDINTMG (TabMaxRow)
ADDINTMG (TabMaxCol)
ADDINTMG (TabMode)
ADDINTMG (EscMode)
#ifdef EP2
ADDINTMG (CurrNode)
#endif
ADDOPTMG (optDisableVarCleanup )
ADDOPTMG (optDisableEmbperlErrorPage)
ADDOPTMG (optReturnError)
ADDOPTMG (optSafeNamespace )
ADDOPTMG (optOpcodeMask )
ADDOPTMG (optRawInput )
ADDOPTMG (optSendHttpHeader )
ADDOPTMG (optDisableChdir )
ADDOPTMG (optDisableHtmlScan )
ADDOPTMG (optEarlyHttpHeader )
ADDOPTMG (optDisableFormData )
ADDOPTMG (optDisableInputScan )
ADDOPTMG (optDisableTableScan )
ADDOPTMG (optDisableMetaScan )
ADDOPTMG (optAllFormData )
ADDOPTMG (optRedirectStdout )
ADDOPTMG (optUndefToEmptyValue )
ADDOPTMG (optNoHiddenEmptyValue )
ADDOPTMG (optAllowZeroFilesize )
ADDOPTMG (optKeepSrcInMemory )
ADDOPTMG (optKeepSpaces )
ADDOPTMG (optOpenLogEarly )
ADDOPTMG (optNoUncloseWarn )
ADDOPTMG (dbgStd )
ADDOPTMG (dbgMem )
ADDOPTMG (dbgEval )
ADDOPTMG (dbgCmd )
ADDOPTMG (dbgEnv )
ADDOPTMG (dbgForm )
ADDOPTMG (dbgTab )
ADDOPTMG (dbgInput )
ADDOPTMG (dbgFlushOutput )
ADDOPTMG (dbgFlushLog )
ADDOPTMG (dbgAllCmds )
ADDOPTMG (dbgSource )
ADDOPTMG (dbgFunc )
ADDOPTMG (dbgLogLink )
ADDOPTMG (dbgDefEval )
ADDOPTMG (dbgHeadersIn )
ADDOPTMG (dbgShowCleanup )
ADDOPTMG (dbgProfile )
ADDOPTMG (dbgSession )
ADDOPTMG (dbgImport )
#ifdef EP2
DomInit () ;
#endif
bInitDone = 1 ;
return
rc ;
}
int
Term ()
{
req * r = pCurrReq ;
EPENTRY (iembperl_term) ;
if
(!bInitDone)
return
ok ;
CloseLog (r) ;
CloseOutput (r) ;
return
ok ;
}
int
ResetHandler (
SV * pApacheReqSV)
{
#ifdef APACHE
request_rec * pReq = (request_rec *)SvIV((SV*)SvRV(pApacheReqSV));
pReq -> handler = NULL ;
#endif
return
ok ;
}
static
void
opmask_addlocal(SV * opset,
char
* op_mask_buf)
{
char
*orig_op_mask = op_mask;
int
i,j;
char
*bitmask;
STRLEN len;
int
myopcode = 0;
int
opset_len = (maxo + 7) / 8 ;
SAVEPPTR(op_mask);
op_mask = &op_mask_buf[0];
if
(orig_op_mask)
Copy(orig_op_mask, op_mask, maxo,
char
);
else
Zero(op_mask, maxo,
char
);
bitmask = SvPV(opset, len);
for
(i=0; i < opset_len; i++)
{
U16 bits = bitmask[i];
if
(!bits)
{
myopcode += 8;
continue
;
}
for
(j=0; j < 8 && myopcode < maxo; )
op_mask[myopcode++] |= bits & (1 << j++);
}
}
tConf * SetupConfData (
HV * pReqInfo,
SV * pOpcodeMask)
{
#ifdef EP2
SV * * ppSV ;
SV * pSV ;
SV * * ppCV ;
int
rc ;
#endif
tConf * pConf =
malloc
(
sizeof
(tConf)) ;
if
(!pConf)
return
NULL ;
pConf -> bDebug = GetHashValueInt (pReqInfo,
"debug"
, pCurrReq -> pConf?pCurrReq -> pConf -> bDebug:pCurrReq -> bDebug) ;
pConf -> bOptions = GetHashValueInt (pReqInfo,
"options"
, pCurrReq -> pConf?pCurrReq -> pConf -> bOptions:pCurrReq -> bOptions) ;
pConf -> nEscMode = GetHashValueInt (pReqInfo,
"escmode"
, pCurrReq -> pConf?pCurrReq -> pConf -> nEscMode:escStd) ;
pConf -> sPackage = sstrdup (GetHashValueStr (pReqInfo,
"package"
, NULL)) ;
pConf -> sLogFilename = sstrdup (GetHashValueStr (pReqInfo,
"log"
, NULL)) ;
pConf -> sVirtLogURI = sstrdup (GetHashValueStr (pReqInfo,
"virtlog"
, pCurrReq -> pConf?pCurrReq -> pConf -> sVirtLogURI:NULL)) ;
pConf -> pOpcodeMask = pOpcodeMask ;
pConf -> sCookieName = sstrdup (GetHashValueStr (pReqInfo,
"cookie_name"
, sCookieNameDefault)) ;
pConf -> sCookieExpires = sstrdup (GetHashValueStr (pReqInfo,
"cookie_expires"
,
""
)) ;
pConf -> sCookieDomain = sstrdup (GetHashValueStr (pReqInfo,
"cookie_domain"
,
""
)) ; ;
pConf -> sCookiePath = sstrdup (GetHashValueStr (pReqInfo,
"cookie_path"
,
""
)) ; ;
pConf -> cMultFieldSep =
'\t'
;
pConf -> pOpenBracket =
"[*"
;
pConf -> pCloseBracket =
"*]"
;
pConf -> sPath = sstrdup (GetHashValueStr (pReqInfo,
"path"
, pCurrReq -> pConf?pCurrReq -> pConf -> sPath:NULL)) ;
pConf -> sReqFilename = sstrdup (GetHashValueStr (pReqInfo,
"reqfilename"
, pCurrReq -> pConf?pCurrReq -> pConf -> sReqFilename:NULL)) ;
pConf -> pReqParameter = pReqInfo ;
#ifdef EP2
pConf -> sRecipe = sstrdup (GetHashValueStr (pReqInfo,
"recipe"
,
"Embperl"
)) ;
pConf -> bEP1Compat = GetHashValueInt (pReqInfo,
"ep1compat"
, pCurrReq -> pConf?pCurrReq -> pConf -> bEP1Compat:pCurrReq -> bEP1Compat) ;
pConf -> sCacheKey = sstrdup (GetHashValueStr (pReqInfo,
"cache_key"
, pCurrReq -> pConf?pCurrReq -> pConf -> sCacheKey:NULL)) ; ;
pConf -> bCacheKeyOptions = GetHashValueInt (pReqInfo,
"cache_key_options"
, pCurrReq -> pConf?pCurrReq -> pConf -> bCacheKeyOptions:ckoptDefault) ;
ppCV = hv_fetch(pReqInfo,
"expires_func"
,
sizeof
(
"expires_func"
) - 1, 0) ;
if
(ppCV && *ppCV && SvOK (*ppCV))
{
if
((rc = EvalConfig (pCurrReq, *ppCV, 0, NULL, &pConf -> pExpiresCV)) != ok)
LogError (pCurrReq, rc) ;
}
else
pConf -> pExpiresCV = pCurrReq -> pConf?pCurrReq -> pConf -> pExpiresCV:NULL ;
ppCV = hv_fetch(pReqInfo,
"cache_key_func"
,
sizeof
(
"cache_key_func"
) - 1, 0) ;
if
(ppCV && *ppCV && SvOK (*ppCV))
{
if
((rc = EvalConfig (pCurrReq, *ppCV, 0, NULL, &pConf -> pCacheKeyCV)) != ok)
LogError (pCurrReq, rc) ;
}
else
pConf -> pCacheKeyCV = pCurrReq -> pConf?pCurrReq -> pConf -> pCacheKeyCV:NULL ;
pConf -> nExpiresIn = GetHashValueInt (pReqInfo,
"expires_in"
, pCurrReq -> pConf?pCurrReq -> pConf -> nExpiresIn:0) ;
#endif
return
pConf ;
}
void
FreeConfData (
tConf * pConf)
{
if
(!pConf)
return
;
if
(pConf -> sPackage)
free
(pConf -> sPackage) ;
if
(pConf -> sLogFilename)
free
(pConf -> sLogFilename) ;
if
(pConf -> sVirtLogURI)
free
(pConf -> sVirtLogURI) ;
if
(pConf -> sCookieName)
free
(pConf -> sCookieName) ;
if
(pConf -> sCookieExpires)
free
(pConf -> sCookieExpires) ;
if
(pConf -> sCookieDomain)
free
(pConf -> sCookieDomain) ;
if
(pConf -> sCookiePath)
free
(pConf -> sCookiePath) ;
if
(pConf -> sPath)
free
(pConf -> sPath) ;
if
(pConf -> sReqFilename)
free
(pConf -> sReqFilename) ;
#ifdef EP2
if
(pConf -> sCacheKey)
free
(pConf -> sCacheKey) ;
if
(pConf -> pCacheKeyCV)
SvREFCNT_dec (pConf -> pCacheKeyCV) ;
if
(pConf -> pExpiresCV)
SvREFCNT_dec (pConf -> pExpiresCV) ;
#endif
free
(pConf) ;
}
tFile * SetupFileData (
register
req * r,
char
* sSourcefile,
double
mtime,
long
nFilesize,
int
nFirstLine,
tConf * pConf)
{
SV * * ppSV ;
tFile * f ;
char
txt [
sizeof
(sDefaultPackageName) + 50] ;
char
* cache_key;
int
cache_key_len;
char
olddir[PATH_MAX] =
""
;
char
* pNew ;
EPENTRY (SetupFileData) ;
cache_key_len =
strlen
( sSourcefile ) ;
if
( pConf->sPackage )
cache_key_len +=
strlen
( pConf->sPackage );
if
(!(sSourcefile[0] ==
'/'
||
sSourcefile[0] ==
'\\'
||
(
isalpha
(sSourcefile[0]) && sSourcefile[1] ==
':'
&&
(sSourcefile[2] ==
'\\'
|| sSourcefile[2] ==
'/'
)) ||
(r -> pInData && SvROK(r -> pInData))))
getcwd (olddir,
sizeof
(olddir) - 1) ;
if
( olddir[0] )
cache_key_len +=
strlen
( olddir );
cache_key = _malloc( r, cache_key_len + 3 );
strcpy
( cache_key, sSourcefile );
if
( pConf->sPackage )
strcat
( cache_key, pConf->sPackage );
if
( olddir[0] )
strcat
( cache_key, olddir );
#ifdef EP2
if
( pConf->bEP1Compat && !pConf->sPackage )
{
strcat
( cache_key,
"-1"
);
cache_key_len += 2 ;
}
#endif
ppSV = hv_fetch(pCacheHash, cache_key, cache_key_len, 0);
if
(ppSV && *ppSV)
{
f = (tFile *)SvIV((SV*)SvRV(*ppSV)) ;
if
(mtime == 0 || f -> mtime != mtime)
{
hv_clear (f -> pCacheHash) ;
#ifdef EP2
UndefSub (r, EPMAINSUB, f -> sCurrPackage) ;
#endif
if
(r -> bDebug)
lprintf (r,
"[%d]MEM: Reload %s in %s\n"
, r -> nPid, sSourcefile, f -> sCurrPackage) ;
f -> mtime = mtime ;
f -> nFilesize = nFilesize ;
f -> bKeep = (r -> bOptions & optKeepSrcInMemory) != 0 ;
f -> nFirstLine = nFirstLine ;
if
(f -> pExportHash)
{
SvREFCNT_dec (f -> pExportHash) ;
f -> pExportHash = NULL ;
}
if
(f -> pBufSV)
{
SvREFCNT_dec (f -> pBufSV) ;
f -> pBufSV = NULL ;
}
}
pNew =
"Found"
;
}
else
{
if
((f =
malloc
(
sizeof
(*f))) == NULL)
{
_free(r,cache_key);
return
NULL ;
}
f -> sSourcefile = sstrdup (sSourcefile) ;
f -> mtime = mtime ;
f -> nFilesize = nFilesize ;
f -> pBufSV = NULL ;
f -> pNext2Free = NULL ;
f -> bKeep = (r -> bOptions & optKeepSrcInMemory) != 0;
f -> pExportHash = NULL ;
f -> nFirstLine = nFirstLine ;
f -> pCacheHash = newHV () ;
if
(pConf -> sPackage)
f -> sCurrPackage = strdup (pConf -> sPackage) ;
else
{
sprintf
(txt, sDefaultPackageName, nPackNo++ ) ;
f -> sCurrPackage = strdup (txt) ;
}
f -> nCurrPackage =
strlen
(f -> sCurrPackage);
hv_store(pCacheHash, cache_key, cache_key_len, newRV_noinc (newSViv ((IV)f)), 0) ;
if
(r -> bDebug)
lprintf (r,
"[%d]MEM: Load %s in %s\n"
, r -> nPid, sSourcefile, f -> sCurrPackage) ;
pNew =
"New"
;
}
if
(r -> bDebug)
lprintf (r,
"[%d]CACHE: %s File for '%s' (%x) in '%s' hash cache-key '%s'\n"
, r -> nPid, pNew, f -> sSourcefile, f, f -> sCurrPackage, cache_key) ;
_free(r,cache_key);
return
f ;
}
tFile * GetFileData (
char
* sSourcefile,
char
* sPackage,
double
mtime,
int
bEP1Compat)
{
SV * * ppSV ;
tFile * f ;
char
txt [
sizeof
(sDefaultPackageName) + 50] ;
char
* cache_key;
int
cache_key_len;
char
olddir[PATH_MAX] =
""
;
char
* pNew ;
EPENTRY (GetFileData) ;
cache_key_len =
strlen
( sSourcefile ) ;
if
( sPackage && *sPackage)
cache_key_len +=
strlen
( sPackage );
if
(!(sSourcefile[0] ==
'/'
||
sSourcefile[0] ==
'\\'
||
(
isalpha
(sSourcefile[0]) && sSourcefile[1] ==
':'
&&
(sSourcefile[2] ==
'\\'
|| sSourcefile[2] ==
'/'
))))
getcwd (olddir,
sizeof
(olddir) - 1) ;
if
( olddir[0] )
cache_key_len +=
strlen
( olddir );
cache_key =
malloc
(cache_key_len + 3 );
strcpy
( cache_key, sSourcefile );
if
( sPackage && *sPackage)
strcat
( cache_key, sPackage );
if
( olddir[0] )
strcat
( cache_key, olddir );
#ifdef EP2
if
( bEP1Compat )
{
strcat
( cache_key,
"-1"
);
cache_key_len += 2 ;
}
#endif
ppSV = hv_fetch(pCacheHash, cache_key, cache_key_len, 0);
if
(ppSV && *ppSV)
{
f = (tFile *)SvIV((SV*)SvRV(*ppSV)) ;
if
(mtime == 0 || f -> mtime != mtime)
{
hv_clear (f -> pCacheHash) ;
#ifdef EP2
UndefSub (pCurrReq, f -> sCurrPackage, EPMAINSUB) ;
#endif
f -> mtime = -1 ;
if
(f -> pExportHash)
{
SvREFCNT_dec (f -> pExportHash) ;
f -> pExportHash = NULL ;
}
}
pNew =
"Found "
;
}
else
{
if
((f =
malloc
(
sizeof
(*f))) == NULL)
{
free
(cache_key);
return
NULL ;
}
f -> sSourcefile = sstrdup (sSourcefile) ;
f -> mtime = -1 ;
f -> nFilesize = 0 ;
f -> pBufSV = NULL ;
f -> pNext2Free = NULL ;
f -> bKeep = 0 ;
f -> pExportHash = NULL ;
f -> nFirstLine = 0 ;
f -> pCacheHash = newHV () ;
if
( sPackage && *sPackage)
f -> sCurrPackage = strdup (sPackage) ;
else
{
sprintf
(txt, sDefaultPackageName, nPackNo++ ) ;
f -> sCurrPackage = strdup (txt) ;
}
f -> nCurrPackage =
strlen
(f -> sCurrPackage);
hv_store(pCacheHash, cache_key, cache_key_len, newRV_noinc (newSViv ((IV)f)), 0) ;
pNew =
"New "
;
}
if
(pCurrReq -> bDebug)
lprintf (pCurrReq,
"[%d]CACHE: %s File for %s (%x) in %s hash cache-key %s\n"
, pCurrReq -> nPid, pNew, f -> sSourcefile, f, f -> sCurrPackage, cache_key) ;
free
(cache_key);
return
f ;
}
static
void
FreeFileBuf (
register
req * r,
tFile * f)
{
if
(!f -> bKeep && f -> pBufSV)
{
SvREFCNT_dec (f -> pBufSV) ;
f -> pBufSV = NULL ;
if
(r -> bDebug)
lprintf (r,
"[%d]MEM: Free buffer for %s in %s\n"
, r -> nPid, f -> sSourcefile, f -> sCurrPackage) ;
}
else
if
(r -> bDebug && !f -> pBufSV)
lprintf (r,
"[%d]MEM: Warning! buffer for %s in %s is NULL\n"
, r -> nPid, f -> sSourcefile, f -> sCurrPackage) ;
}
static
SV * CreateSessionCookie (
register
req * r,
HV * pSessionHash,
char
type,
int
bReturnCookie)
{
SV ** ppSVID ;
SV * pSVID = NULL ;
SV * pSVUID = NULL ;
MAGIC * pMG ;
char
* pUID = NULL ;
char
* pInitialUID = NULL ;
STRLEN ulen = 0 ;
STRLEN ilen = 0 ;
IV bModified ;
SV * pCookie = NULL ;
STRLEN ldummy ;
if
(r -> nSessionMgnt)
{
SV * pUserHashObj = NULL ;
if
((pMG = mg_find((SV *)pSessionHash,
'P'
)))
{
dSP;
int
n ;
pUserHashObj = pMG -> mg_obj ;
PUSHMARK(sp);
XPUSHs(pUserHashObj) ;
XPUSHs(sv_2mortal(newSViv(bReturnCookie?0:1))) ;
PUTBACK;
n = perl_call_method (
"getids"
, G_ARRAY) ;
SPAGAIN;
if
(n > 2)
{
int
savewarn = dowarn ;
dowarn = 0 ;
bModified = POPi ;
pSVUID = POPs;
pUID = SvPV (pSVUID, ulen) ;
pSVID = POPs;
pInitialUID = SvPV (pSVID, ilen) ;
dowarn = savewarn ;
}
PUTBACK;
}
if
(r -> bDebug & dbgSession)
lprintf (r,
"[%d]SES: Received Cookie ID: %s New Cookie ID: %s %s data is%s modified\n"
, r -> nPid, pInitialUID, pUID, type ==
's'
?
"State"
:
"User"
, bModified?
""
:
" NOT"
) ;
if
(ilen > 0 && (ulen == 0 || (!bModified &&
strcmp
(
"!DELETE"
, pInitialUID) == 0)))
{
if
(bReturnCookie)
{
pCookie = newSVpvf (
"%s%s=; expires=Thu, 1-Jan-1970 00:00:01 GMT%s%s%s%s"
, r -> pConf -> sCookieName, type ==
's'
?
"s"
:
""
,
r -> pConf -> sCookieDomain[0]?
"; domain="
:
""
, r -> pConf -> sCookieDomain,
r -> pConf -> sCookiePath[0]?
"; path="
:
""
, r -> pConf -> sCookiePath) ;
}
if
(r -> bDebug & dbgSession)
lprintf (r,
"[%d]SES: Delete Cookie -> %s\n"
, r -> nPid, SvPV(pCookie, ldummy)) ;
}
else
if
(ulen > 0 &&
((bModified && (ilen == 0 ||
strcmp
(pInitialUID, pUID) !=0)) ||
(r -> nSessionMgnt & 4) || !bReturnCookie))
{
if
(bReturnCookie)
{
pCookie = newSVpvf (
"%s%s=%s%s%s%s%s%s%s"
, r -> pConf -> sCookieName, type ==
's'
?
"s"
:
""
, pUID,
r -> pConf -> sCookieDomain[0]?
"; domain="
:
""
, r -> pConf -> sCookieDomain,
r -> pConf -> sCookiePath[0]?
"; path="
:
""
, r -> pConf -> sCookiePath,
r -> pConf -> sCookieExpires[0]?
"; expires="
:
""
, r -> pConf -> sCookieExpires) ;
if
(r -> bDebug & dbgSession)
lprintf (r,
"[%d]SES: Send Cookie -> %s\n"
, r -> nPid, SvPV(pCookie, ldummy)) ;
}
else
{
pCookie = pSVUID ;
}
}
}
return
pCookie ;
}
tReq * SetupRequest (
SV * pApacheReqSV,
char
* sSourcefile,
double
mtime,
long
nFilesize,
int
nFirstLine,
char
* sOutputfile,
tConf * pConf,
int
nIOType,
SV * pIn,
SV * pOut,
char
* sSubName,
char
* sImport,
int
nSessionMgnt,
tTokenTable * pTokenTable)
{
int
rc ;
tReq * r = pCurrReq ;
char
* sMode ;
tFile * pFile ;
HV * pReqHV ;
#ifdef EP2
SV * * ppSV ;
STRLEN len ;
#endif
dTHR ;
tainted = 0 ;
if
(pConf -> bDebug)
if
((rc = OpenLog (pCurrReq, NULL, 2)) != ok)
{
LogError (pCurrReq, rc) ;
}
EPENTRY (SetupRequest) ;
if
(pReqFree)
{
r = pReqFree ;
pReqFree = pReqFree -> pNext ;
memcpy
(r, pCurrReq, (
char
*)&r -> zeroend - (
char
*)r) ;
r -> pNext = NULL ;
}
else
{
if
((r =
malloc
(
sizeof
(tReq))) == NULL)
return
NULL ;
memcpy
(r, pCurrReq,
sizeof
(*r)) ;
}
#ifdef EP2
r -> nPhase = phInit ;
#endif
r -> bSubReq = !(pCurrReq == &InitialReq) ;
r -> pLastReq = pCurrReq ;
pCurrReq = r ;
#ifdef APACHE
if
(SvROK (pApacheReqSV))
r -> pApacheReq = (request_rec *)SvIV((SV*)SvRV(pApacheReqSV));
else
r -> pApacheReq = NULL ;
r -> pApacheReqSV = pApacheReqSV ;
#endif
if
(!r -> pLastReq -> pReqSV)
pReqHV = newHV () ;
else
{
pReqHV = (HV *)SvRV (r -> pLastReq -> pReqSV) ;
SvREFCNT_inc (pReqHV) ;
}
sv_unmagic ((SV *)pReqHV,
'~'
) ;
sv_magic ((SV *)pReqHV, NULL,
'~'
, (
char
*)&r,
sizeof
(r)) ;
r -> pReqSV = newRV_noinc ((SV *)pReqHV) ;
if
(!r -> pLastReq -> pReqSV)
sv_bless (r -> pReqSV, gv_stashpv (
"HTML::Embperl::Req"
, 0)) ;
r -> startclock =
clock
() ;
r -> stsv_count = sv_count ;
r -> stsv_objcount = sv_objcount ;
r -> lstsv_count = sv_count ;
r -> lstsv_objcount = sv_objcount ;
r -> nPid = getpid () ;
r -> bDebug = pConf -> bDebug ;
#ifdef EP2
r -> bEP1Compat = pConf -> bEP1Compat ;
ppSV = hv_fetch(r -> pEnvHash,
"PATH_INFO"
,
sizeof
(
"PATH_INFO"
) - 1, 0) ;
if
(ppSV)
r -> sPathInfo = SvPV (*ppSV ,len) ;
r -> pTokenTable = pTokenTable ;
#else
r -> pTokenTable = (
void
*)pTokenTable ;
#endif
if
(rc != ok)
r -> bDebug = 0 ;
r -> bOptions = pConf -> bOptions ;
r -> sSubName = sSubName ;
r -> nSessionMgnt = nSessionMgnt ;
r -> pConf = pConf ;
r -> nInsideSub = 0 ;
r -> bExit = 0 ;
r -> pOutData = pOut ;
r -> pInData = pIn ;
r -> pFiles2Free = NULL ;
if
(r -> bSubReq && sSourcefile[0] ==
'?'
&& sSubName && sSubName[0] !=
'\0'
)
{
pFile = r -> pLastReq -> Buf.pFile ;
}
else
{
if
((pFile = SetupFileData (r, sSourcefile, mtime, nFilesize, nFirstLine, pConf)) == NULL)
return
NULL ;
}
if
(r -> bSubReq && sOutputfile[0] == 1 && r -> pLastReq && !SvROK (pOut))
{
r -> sOutputfile = r -> pLastReq -> sOutputfile ;
r -> bAppendToMainReq = TRUE ;
}
else
{
if
(sOutputfile[0] == 1)
r -> sOutputfile =
""
;
else
r -> sOutputfile = sOutputfile ;
r -> bAppendToMainReq = FALSE ;
}
r -> bReqRunning = 0 ;
r -> Buf.pFile = pFile ;
r -> pOutData = pOut ;
r -> pInData = pIn ;
r -> CmdStack.State.nCmdType = cmdNorm ;
r -> CmdStack.State.bProcessCmds = cmdAll ;
r -> HtmlStack.State.nCmdType = cmdNorm ;
r -> HtmlStack.State.bProcessCmds = cmdAll ;
r -> nTabMode = epTabRowDef | epTabColDef ;
r -> nTabMaxRow = 100 ;
r -> nTabMaxCol = 10 ;
r -> nEscMode = pConf -> nEscMode ;
NewEscMode (r, NULL) ;
r -> bEscModeSet = 0 ;
if
(r -> bOptions & optSafeNamespace)
{
r -> Buf.sEvalPackage =
"main"
;
r -> Buf.nEvalPackage =
sizeof
(
"main"
) - 1 ;
}
else
{
r -> Buf.sEvalPackage = r -> Buf.pFile -> sCurrPackage ;
r -> Buf.nEvalPackage = r -> Buf.pFile -> nCurrPackage ;
}
if
(sImport && *sImport)
{
if
((r -> pImportStash = gv_stashpv (sImport, 0)) == NULL)
{
strncpy
(r -> errdat1, sImport,
sizeof
(r -> errdat1) - 1);
LogError (r, rcImportStashErr) ;
}
r -> bOptions |= optDisableHtmlScan ;
}
else
r -> pImportStash = NULL ;
r -> Buf.nSourceline = r -> Buf.pFile -> nFirstLine ;
r -> Buf.pSourcelinePos = NULL ;
r -> Buf.pLineNoCurrPos = NULL ;
r -> bStrict = FALSE ;
r -> errdat1 [0] =
'\0'
;
r -> errdat2 [0] =
'\0'
;
r -> lastwarn [0] =
'\0'
;
if
(!r -> bSubReq)
{
r -> bError = FALSE ;
av_clear (r -> pErrFill) ;
av_clear (r -> pErrState) ;
av_clear (r -> pErrArray) ;
hv_clear (r -> pHeaderHash) ;
r -> nLastErrFill = AvFILL(r -> pErrArray) ;
r -> bLastErrState = r -> bError ;
r -> nLogFileStartPos = GetLogFilePos (r) ;
}
if
(r -> bDebug)
{
time_t
t ;
struct
tm
*
tm
;
time
(&t) ;
tm
=
localtime
(&t) ;
if
(!r -> bSubReq)
lprintf (r,
"[%d]REQ: Embperl %s starting... %s\n"
, r -> nPid, sVersion,
asctime
(
tm
)) ;
r -> numEvals = 0 ;
r -> numCacheHits = 0 ;
}
if
(r -> bDebug)
{
switch
(r -> nIOType)
{
case
epIOMod_Perl: sMode =
"mod_perl"
;
break
;
case
epIOPerl: sMode =
"Offline"
;
break
;
case
epIOCGI: sMode =
"CGI-Script"
;
break
;
case
epIOProcess: sMode =
"Demon"
;
break
;
default
: sMode =
"unknown"
;
break
;
}
lprintf (r,
"[%d]REQ: %s %s "
, r -> nPid, (r -> bOptions & optSafeNamespace)?
"SafeNamespace"
:
"No Safe Eval"
, (r -> bOptions & optOpcodeMask)?
"OpcodeMask"
:
"All Opcode allowed"
) ;
#ifdef EP2
lprintf (r,
" mode = %s (%d) %s recipe = %s\n"
, sMode, r -> nIOType, r -> bEP1Compat?
"EP 1.x"
:
"EP 2.x"
, r -> pConf -> sRecipe) ;
#else
lprintf (r,
" mode = %s (%d)\n"
, sMode, r -> nIOType) ;
#endif
lprintf (r,
"[%d]REQ: Package = %s\n"
, r -> nPid, r -> Buf.pFile -> sCurrPackage) ;
}
return
r ;
}
void
FreeRequest (
register
req * r)
{
FreeConfData (r -> pConf) ;
r -> pConf = NULL ;
if
(!r -> bAppendToMainReq && r -> ofd)
CloseOutput (r) ;
if
(r -> bSubReq)
{
tReq * l = r -> pLastReq ;
l -> bError = r -> bError ;
l -> nLastErrFill= r -> nLastErrFill ;
l -> bLastErrState= r -> bLastErrState ;
}
else
{
tFile * pFile ;
tFile * pNext ;
int
i ;
#ifdef HASHTEST
pHash = perl_get_hv (sFormHashName, FALSE) ;
if
(pHash != r -> pFormHash)
{
strcpy
(r -> errdat1, sFormHashName) ;
strcpy
(r -> errdat2,
" !!C-Adress differs from Perl-Adress!! in FreeRequest"
) ;
LogError (r, rcHashError) ;
}
#endif
hv_clear (r -> pHeaderHash) ;
av_clear (r -> pFormArray) ;
hv_clear (r -> pFormHash) ;
hv_clear (r -> pInputHash) ;
hv_clear (r -> pFormSplitHash) ;
#ifdef EP2
av_clear (r -> pDomTreeAV) ;
for
(i = 0 ; i < AvFILL (r -> pCleanupAV); i++)
{
sv_setsv (SvRV(*av_fetch (r -> pCleanupAV, i, 0)), &sv_undef) ;
}
av_clear (r -> pCleanupAV) ;
#endif
if
((pFile = r -> pFiles2Free))
{
do
{
FreeFileBuf (r, pFile) ;
pNext = pFile -> pNext2Free ;
pFile -> pNext2Free = NULL ;
}
while
(pFile != pNext && (pFile = pNext)) ;
}
#ifdef APACHE
r -> pApacheReq = NULL ;
r -> pApacheReqSV = &sv_undef ;
#endif
}
SvREFCNT_dec (r -> pReqSV) ;
pCurrReq = r -> pLastReq ;
if
(pCurrReq && pCurrReq -> pReqSV)
{
SV * pReqHV = SvRV (pCurrReq -> pReqSV) ;
sv_unmagic (pReqHV,
'~'
) ;
sv_magic (pReqHV, NULL,
'~'
, (
char
*)&pCurrReq,
sizeof
(pCurrReq)) ;
}
if
(r -> sSessionID)
_free (r, r -> sSessionID) ;
r -> pNext = pReqFree ;
pReqFree = r ;
}
static
void
SetupSafeNamespace (
register
req * r)
{
GV * gv;
dTHR ;
if
(r -> bOptions & optOpcodeMask)
opmask_addlocal(r -> pConf -> pOpcodeMask, r -> op_mask_buf);
if
(r -> bOptions & optSafeNamespace)
{
save_aptr(&endav);
endav = (AV*)sv_2mortal((SV*)newAV());
save_hptr(&defstash);
defstash = gv_stashpv(r -> Buf.pFile -> sCurrPackage, GV_ADDWARN);
if
(r -> bDebug)
lprintf (r,
"[%d]REQ: switch to safe namespace %s\n"
, r -> nPid, r -> Buf.pFile -> sCurrPackage) ;
gv = gv_fetchpv(
"main::"
, GV_ADDWARN, SVt_PVHV);
sv_free((SV*)GvHV(gv));
GvHV(gv) = (HV*)SvREFCNT_inc(defstash);
}
}
static
int
StartOutput (
register
req * r)
{
int
rc ;
SV * pOutData = r -> pOutData ;
int
bOutToMem = SvROK (pOutData) ;
if
(r -> pImportStash)
{
r -> bDisableOutput = 1 ;
}
else
if
(!bOutToMem)
{
if
(!r -> bAppendToMainReq)
{
if
((rc = OpenOutput (r, r -> sOutputfile)) != ok)
return
rc ;
}
else
OutputToStd (r) ;
}
else
{
r -> ofd = NULL ;
OpenOutput (r, NULL) ;
}
#ifdef APACHE
if
(r -> pApacheReq && r -> pApacheReq -> main)
r -> bOptions |= optEarlyHttpHeader ;
#endif
if
(bOutToMem)
r -> bOptions &= ~optEarlyHttpHeader ;
if
(r -> bSubReq || r -> pImportStash)
r -> bOptions &= ~optSendHttpHeader ;
if
(r -> bOptions & optEarlyHttpHeader)
{
#ifdef APACHE
if
(r -> pApacheReq == NULL)
{
#endif
if
(r -> nIOType != epIOPerl && (r -> bOptions & optSendHttpHeader))
oputs (r,
"Content-type: text/html\n\n"
) ;
#ifdef APACHE
}
else
{
if
(r -> pApacheReq -> main == NULL && (r -> bOptions & optSendHttpHeader))
send_http_header (r -> pApacheReq) ;
#ifndef WIN32
#endif
if
(r -> pApacheReq -> header_only)
{
if
(!r -> bAppendToMainReq)
CloseOutput (r) ;
return
ok ;
}
}
#endif
}
else
{
oBegin (r) ;
}
if
((r -> bOptions & optAddStateSessionToLinks) && !r -> bSubReq)
{
SV * pCookie = CreateSessionCookie (r, r -> pStateHash,
's'
, 0) ;
STRLEN l ;
lprintf (r,
"opt %x optadd %x options %x cookie %s\n"
, optAddStateSessionToLinks, r -> bOptions & optAddStateSessionToLinks, r -> bOptions, SvPV(pCookie, l)) ;
if
(pCookie)
{
r -> sSessionID = _memstrcat (r, r -> pConf -> sCookieName,
"="
, SvPV (pCookie, l), NULL) ;
}
}
if
((r -> bOptions & optAddUserSessionToLinks) && !r -> bSubReq)
{
SV * pCookie = CreateSessionCookie (r, r -> pUserHash,
'u'
, 0) ;
if
(pCookie)
{
STRLEN l ;
if
(r -> sSessionID)
r -> sSessionID = _memstrcat (r, r -> sSessionID,
":"
, SvPV (pCookie, l), NULL) ;
else
r -> sSessionID = _memstrcat (r, r -> pConf -> sCookieName,
"=:"
, SvPV (pCookie, l), NULL) ;
}
}
return
ok ;
}
static
int
EndOutput (
register
req * r,
int
rc,
SV * pOutData)
{
SV * pOut = NULL ;
int
bOutToMem = SvROK (pOutData) ;
SV * pCookie = NULL ;
SV * pCookie2 = NULL ;
int
bError = 0 ;
STRLEN ldummy ;
#ifdef EP2
int
bXSLT = 0 ;
if
(
strcmp
(r -> pConf -> sRecipe +
strlen
(r -> pConf -> sRecipe) - 4 ,
"XSLT"
) == 0)
{
bXSLT = 1 ;
}
#endif
r -> bEscModeSet = 0 ;
if
(rc != ok || r -> bError)
{
dSP;
PUSHMARK(sp);
XPUSHs(r -> pReqSV) ;
PUTBACK;
perl_call_method (
"MailErrorsTo"
, G_DISCARD) ;
if
(r -> bOptions & optReturnError)
{
r -> bError = 1 ;
oRollbackOutput (r, NULL) ;
if
(bOutToMem)
{
pOut = SvRV (pOutData) ;
sv_setsv (pOut, &sv_undef) ;
}
return
ok ;
}
else
if
(!(r -> bOptions & optDisableEmbperlErrorPage))
{
if
(!r -> bAppendToMainReq)
{
oRollbackOutput (r, NULL) ;
oBegin (r) ;
PUSHMARK(sp);
XPUSHs(r -> pReqSV) ;
PUTBACK;
perl_call_method (
"SendErrorDoc"
, G_DISCARD) ;
#ifdef APACHE
if
(r -> pApacheReq)
r -> pApacheReq -> status = 500 ;
#endif
}
bError = 1 ;
}
if
(!r -> bAppendToMainReq)
r -> bError = 0 ;
}
if
(!(r -> bOptions & optEarlyHttpHeader) && (r -> bOptions & optSendHttpHeader) && !bOutToMem)
{
if
(!r -> bAppendToMainReq)
{
if
(!(r -> bOptions & optNoSessionCookies))
pCookie = CreateSessionCookie (r, r -> pUserHash,
'u'
, 1) ;
#ifdef APACHE
if
(r -> pApacheReq)
{
SV * pHeader ;
char
* p ;
HE * pEntry ;
char
* pKey ;
I32 l ;
I32 i;
I32 len;
AV *arr;
SV **svp;
I32 loc;
hv_iterinit (r -> pHeaderHash) ;
while
((pEntry = hv_iternext (r -> pHeaderHash)))
{
pKey = hv_iterkey (pEntry, &l) ;
pHeader = hv_iterval (r -> pHeaderHash, pEntry) ;
loc = 0;
if
(pHeader && pKey)
{
if
(stricmp (pKey,
"location"
) == 0)
loc = 1;
if
(stricmp (pKey,
"content-type"
) == 0)
{
p = NULL;
if
( SvROK(pHeader) && SvTYPE(SvRV(pHeader)) == SVt_PVAV )
{
arr = (AV *)SvRV(pHeader);
if
(av_len(arr) >= 0)
{
svp = av_fetch(arr, 0, 0);
p = SvPV(*svp, ldummy);
}
}
else
{
p = SvPV(pHeader, ldummy);
}
if
(p)
r->pApacheReq->content_type = pstrdup(r->pApacheReq->pool, p);
}
else
if
(SvROK(pHeader) && SvTYPE(SvRV(pHeader)) == SVt_PVAV )
{
arr = (AV *)SvRV(pHeader);
len = av_len(arr);
for
(i = 0; i <= len; i++)
{
svp = av_fetch(arr, i, 0);
p = SvPV(*svp, ldummy);
table_add( r->pApacheReq->headers_out, pstrdup(r->pApacheReq->pool, pKey),
pstrdup(r->pApacheReq->pool, p ) );
if
(loc == 1)
{
loc = 2;
break
;
}
}
}
else
{
p = SvPV(pHeader, ldummy);
table_set(r -> pApacheReq->headers_out, pstrdup(r -> pApacheReq->pool, pKey), pstrdup(r -> pApacheReq->pool, p)) ;
if
(loc == 1) loc = 2;
}
if
(loc == 2) r->pApacheReq->status = 301;
}
}
if
(pCookie)
{
table_add(r -> pApacheReq->headers_out, sSetCookie, pstrdup(r -> pApacheReq->pool, SvPV(pCookie, ldummy))) ;
SvREFCNT_dec (pCookie) ;
}
if
(pCookie2)
{
table_add(r -> pApacheReq->headers_out, sSetCookie, pstrdup(r -> pApacheReq->pool, SvPV(pCookie2, ldummy))) ;
SvREFCNT_dec (pCookie2) ;
}
#ifdef EP2
if
(r -> bEP1Compat)
#endif
set_content_length (r -> pApacheReq, GetContentLength (r) + (r -> pCurrEscape?2:0)) ;
send_http_header (r -> pApacheReq) ;
#ifndef WIN32
#endif
if
(r -> bDebug & dbgHeadersIn)
{
int
i;
array_header *hdrs_arr;
table_entry *hdrs;
hdrs_arr = table_elts (r -> pApacheReq->headers_out);
hdrs = (table_entry *)hdrs_arr->elts;
lprintf (r,
"[%d]HDR: %d\n"
, r -> nPid, hdrs_arr->nelts) ;
for
(i = 0; i < hdrs_arr->nelts; ++i)
if
(hdrs[i].key)
lprintf (r,
"[%d]HDR: %s=%s\n"
, r -> nPid, hdrs[i].key, hdrs[i].val) ;
}
}
else
#endif
{
if
(r -> nIOType == epIOCGI)
{
char
txt[100] ;
int
save = r -> nMarker ;
SV * pHeader ;
char
* p ;
HE * pEntry ;
char
* pKey ;
I32 l ;
char
* pContentType =
"text/html"
;
r -> nMarker = 0 ;
hv_iterinit (r -> pHeaderHash) ;
while
((pEntry = hv_iternext (r -> pHeaderHash)))
{
pKey = hv_iterkey (pEntry, &l) ;
pHeader = hv_iterval (r -> pHeaderHash, pEntry) ;
if
(pHeader && pKey)
{
if
(SvROK(pHeader) && SvTYPE(SvRV(pHeader)) == SVt_PVAV )
{
AV * arr = (AV *)SvRV(pHeader);
I32 len = av_len(arr);
int
i ;
for
(i = 0; i <= len; i++)
{
SV ** svp = av_fetch(arr, i, 0);
p = SvPV(*svp, ldummy);
oputs (r, pKey) ;
oputs (r,
": "
) ;
oputs (r, p) ;
oputs (r,
"\n"
) ;
if
(r -> bDebug & dbgHeadersIn)
lprintf (r,
"[%d]HDR: %s: %s\n"
, r -> nPid, pKey, p) ;
}
}
else
{
p = SvPV (pHeader, na) ;
if
(stricmp (pKey,
"content-type"
) == 0)
pContentType = p ;
else
{
oputs (r, pKey) ;
oputs (r,
": "
) ;
oputs (r, p) ;
oputs (r,
"\n"
) ;
}
if
(r -> bDebug & dbgHeadersIn)
lprintf (r,
"[%d]HDR: %s: %s\n"
, r -> nPid, pKey, p) ;
}
}
}
oputs (r,
"Content-Type: "
) ;
oputs (r, pContentType) ;
oputs (r,
"\n"
) ;
sprintf
(txt,
"Content-Length: %d\n"
, GetContentLength (r) + (r -> pCurrEscape?2:0)) ;
oputs (r, txt) ;
if
(pCookie)
{
oputs (r, sSetCookie) ;
oputs (r,
": "
) ;
oputs (r, SvPV(pCookie, na)) ;
oputs (r,
"\n"
) ;
SvREFCNT_dec (pCookie) ;
}
if
(pCookie2)
{
oputs (r, sSetCookie) ;
oputs (r,
": "
) ;
oputs (r, SvPV(pCookie2, na)) ;
oputs (r,
"\n"
) ;
SvREFCNT_dec (pCookie2) ;
}
oputs (r,
"\n"
) ;
r -> nMarker = save ;
}
}
}
}
if
(bOutToMem)
pOut = SvRV (pOutData) ;
#ifdef APACHE
if
((r -> pApacheReq == NULL || !r -> pApacheReq -> header_only) &&
(!(r -> bOptions & optEarlyHttpHeader) || r -> bAppendToMainReq))
#else
if
(!(r -> bOptions & optEarlyHttpHeader) || r -> bAppendToMainReq)
#endif
{
#ifdef EP2
if
(r -> bEP1Compat && r -> pCurrEscape)
#else
if
(r -> pCurrEscape)
#endif
oputs (r,
"\r\n"
) ;
#ifdef EP2
if
(bXSLT && !bError && !r -> bEP1Compat)
{
char
* pData ;
int
l ;
tDomTree * pDomTree = DomTree_self (r -> xCurrDomTree) ;
Node_toString (r, pDomTree, pDomTree -> xDocument, 0) ;
pOut = newSVpv (
""
, 0) ;
oputs (r,
"\r\n"
) ;
l = GetContentLength (r) + 1 ;
SvGROW (pOut, l) ;
pData = SvPVX (pOut) ;
oCommitToMem (r, NULL, pData) ;
oRollbackOutput (r, NULL) ;
SvCUR_set (pOut, l - 1) ;
if
(r -> bAppendToMainReq)
oBegin (r) ;
if
(
strstr
(r -> pConf -> sRecipe,
"LibXSLT"
))
{
#ifdef LIBXSLT
if
(r -> bDebug & dbgXSLT)
lprintf (r,
"[%d]XSLT: call libxslt\n"
, r -> nPid) ;
if
((rc = embperl_LibXSLT_Text2Text (r, r -> pConf -> pReqParameter, pOut)) != ok)
return
rc ;
#else
strcpy
(r -> errdat1,
"libxslt not supported"
) ;
return
9999 ;
#endif
}
else
if
(
strstr
(r -> pConf -> sRecipe,
"Xalan"
))
{
#ifdef XALAN
if
(r -> bDebug & dbgXSLT)
lprintf (r,
"[%d]XSLT: call xalan\n"
, r -> nPid) ;
if
((rc = embperl_Xalan_Text2Text (r, r -> pConf -> pReqParameter, pOut)) != ok)
return
rc ;
#else
strcpy
(r -> errdat1,
"xalan not supported"
) ;
return
9999 ;
#endif
}
}
#endif
if
(bOutToMem)
{
char
* pData ;
int
l ;
#ifdef EP2
if
(!bError && !r -> bEP1Compat)
{
tDomTree * pDomTree = DomTree_self (r -> xCurrDomTree) ;
Node_toString (r, pDomTree, pDomTree -> xDocument, 0) ;
}
if
(!r -> bEP1Compat)
oputs (r,
"\r\n"
) ;
#endif
l = GetContentLength (r) + 1 ;
sv_setpv (pOut,
""
) ;
SvGROW (pOut, l) ;
pData = SvPVX (pOut) ;
oCommitToMem (r, NULL, pData) ;
SvCUR_set (pOut, l - 1) ;
}
else
{
if
(r -> bAppendToMainReq)
{
tReq * l = r -> pLastReq ;
#ifdef EP2
if
(r -> bEP1Compat)
{
#endif
l -> pFirstBuf = r -> pFirstBuf ;
l -> pLastBuf = r -> pLastBuf ;
l -> pFreeBuf = r -> pFreeBuf ;
l -> pLastFreeBuf= r -> pLastFreeBuf ;
l -> nSessionMgnt= r -> nSessionMgnt ;
#ifdef EP2
}
else
{
if
(!bError && !r -> pImportStash)
{
tDomTree * pDomTree = DomTree_self (r -> xCurrDomTree) ;
if
(bXSLT)
{
int
len = GetContentLength (r) + 1 ;
char
* pData = _malloc (r, len) ;
oCommitToMem (r, NULL, pData) ;
oRollbackOutput (r, NULL) ;
l -> xCurrNode = Node_appendChild (DomTree_self (l -> xCurrDomTree),
l -> xCurrNode,
l -> nCurrRepeatLevel,
ntypCDATA,
0,
pData, len - 1, 0, 0,
"XSLT Result"
) ;
}
else
l -> xCurrNode = Node_insertAfter (pDomTree, pDomTree -> xDocument, 0, DomTree_self (l -> xCurrDomTree), l -> xCurrNode, l -> nCurrRepeatLevel) ;
}
}
#endif
}
else
{
oCommit (r, NULL) ;
#ifdef EP2
if
(!bError && !r -> bEP1Compat && !r -> pImportStash && !bXSLT)
{
tDomTree * pDomTree = DomTree_self (r -> xCurrDomTree) ;
Node_toString (r, pDomTree, pDomTree -> xDocument, 0) ;
oputs (r,
"\r\n"
) ;
}
#endif
}
}
}
else
{
oRollbackOutput (r, NULL) ;
if
(bOutToMem)
sv_setsv (pOut, &sv_undef) ;
#ifdef EP2
else
if
(!r -> bEP1Compat)
{
tDomTree * pDomTree = DomTree_self (r -> xCurrDomTree) ;
Node_toString (r, pDomTree, pDomTree -> xDocument, 0) ;
}
#endif
}
if
(!r -> bAppendToMainReq)
CloseOutput (r) ;
return
ok ;
}
static
int
ResetRequest (
register
req * r,
char
* sInputfile)
{
if
(r -> bDebug)
{
clock_t
cl =
clock
() ;
time_t
t ;
struct
tm
*
tm
;
time
(&t) ;
tm
=
localtime
(&t) ;
lprintf (r,
"[%d]PERF: input = %s\n"
, r -> nPid, sInputfile) ;
#ifdef CLOCKS_PER_SEC
lprintf (r,
"[%d]PERF: Time: %d ms "
, r -> nPid, ((cl - r -> startclock) * 1000 / CLOCKS_PER_SEC)) ;
#else
lprintf (r,
"[%d]PERF: "
, r -> nPid) ;
#endif
lprintf (r,
"Evals: %d "
, r -> numEvals) ;
if
(r -> numEvals == 0)
lprintf (r,
"No Evals to cache"
) ;
else
lprintf (r,
"Cache Hits: %d (%d%%)"
, r -> numCacheHits, r -> numCacheHits * 100 / r -> numEvals) ;
lprintf (r,
"\n"
) ;
lprintf (r,
"[%d]%sRequest finished. %s. Entry-SVs: %d -OBJs: %d Exit-SVs: %d -OBJs: %d\n"
, r -> nPid,
(r -> bSubReq?
"Sub-"
:
""
),
asctime
(
tm
), r -> stsv_count, r -> stsv_objcount, sv_count, sv_objcount) ;
}
r -> Buf.pCurrPos = NULL ;
FlushLog (r) ;
r -> Buf.nSourceline = 1 ;
r -> Buf.pSourcelinePos = NULL ;
r -> Buf.pLineNoCurrPos = NULL ;
r -> bReqRunning = 0 ;
av_clear (r -> pErrFill) ;
av_clear (r -> pErrState) ;
#ifdef APACHE
r -> pApacheReq = NULL ;
#endif
return
ok ;
}
static
int
ProcessFile (
register
req * r,
int
nFileSize)
{
int
rc ;
r -> Buf.pSourcelinePos = r -> Buf.pCurrPos = r -> Buf.pBuf ;
r -> Buf.pEndPos = r -> Buf.pBuf + nFileSize ;
#ifdef EP2
if
(!r -> bEP1Compat)
{
tConf * pConf = r -> pConf ;
tProcessor p2 = {2,
"Embperl"
, embperl_CompileProcessor, NULL, embperl_PreExecuteProcessor, embperl_ExecuteProcessor,
""
,
NULL, 0, 0, NULL, NULL } ;
tProcessor p1 = {1,
"Parser"
, embperl_ParseProcessor, NULL, NULL, NULL,
""
, NULL, 0, 0, NULL, NULL } ;
p2.pCacheKeyCV = pConf -> pCacheKeyCV ;
p2.bCacheKeyOptions = pConf -> bCacheKeyOptions ;
p2.nOutputExpiresIn = pConf -> nExpiresIn ;
p2.pOutputExpiresCV = pConf -> pExpiresCV ;
p1.pNext = &p2 ;
if
(p2.pCacheKeyCV)
SvREFCNT_inc (p2.pCacheKeyCV) ;
if
(p2.pOutputExpiresCV)
SvREFCNT_inc (p2.pOutputExpiresCV) ;
rc = embperl_CompileDocument (r, &p1) ;
if
(p2.pCacheKeyCV)
SvREFCNT_dec (p2.pCacheKeyCV) ;
if
(p2.pOutputExpiresCV)
SvREFCNT_dec (p2.pOutputExpiresCV) ;
}
else
{
clock_t
cl1 =
clock
() ;
clock_t
cl2 ;
rc = EvalMain (r) ;
cl2 =
clock
() ;
#ifdef CLOCKS_PER_SEC
if
(r -> bDebug)
{
lprintf (r,
"[%d]PERF: Run Start Time: %d ms \n"
, r -> nPid, ((cl1 - r -> startclock) * 1000 / CLOCKS_PER_SEC)) ;
lprintf (r,
"[%d]PERF: Run End Time: %d ms \n"
, r -> nPid, ((cl2 - r -> startclock) * 1000 / CLOCKS_PER_SEC)) ;
lprintf (r,
"[%d]PERF: Run Time: %d ms \n"
, r -> nPid, ((cl2 - cl1) * 1000 / CLOCKS_PER_SEC)) ;
}
#endif
}
#else /* EP2 */
rc = EvalMain (r) ;
#endif /* EP2 */
if
((r -> bOptions & optNoUncloseWarn) == 0)
{
if
(!r -> bSubReq && r -> CmdStack.pStack)
{
if
(r -> CmdStack.State.pCmd)
strncpy
(r -> errdat1, r -> CmdStack.State.pCmd -> sCmdName,
sizeof
(r -> errdat1) - 1) ;
LogError (r, rcUnclosedCmd) ;
}
if
(!r -> bSubReq && r -> HtmlStack.pStack)
{
if
(r -> HtmlStack.State.pCmd)
strncpy
(r -> errdat1, r -> HtmlStack.State.pCmd -> sCmdName,
sizeof
(r -> errdat1) - 1) ;
LogError (r, rcUnclosedHtml) ;
}
}
return
rc ;
}
int
ProcessBlock (
register
req * r,
int
nBlockStart,
int
nBlockSize,
int
nBlockNo)
{
int
rc ;
char
* p ;
int
n ;
r -> Buf.pCurrPos = r -> Buf.pBuf + nBlockStart ;
r -> Buf.pEndPos = r -> Buf.pCurrPos + nBlockSize ;
r -> Buf.nBlockNo = nBlockNo ;
if
(r -> pTokenTable &&
strcmp
((
char
*)r -> pTokenTable,
"Text"
) == 0)
{
owrite (r, r -> Buf.pCurrPos, r -> Buf.pEndPos - r -> Buf.pCurrPos) ;
return
r -> Buf.nBlockNo ;
}
rc = ok ;
p = r -> Buf.pCurrPos ;
while
(p && *p && p < r -> Buf.pEndPos && rc == ok)
{
if
((r -> bDebug & dbgMem) && (sv_count != r -> lstsv_count || sv_objcount != r -> lstsv_objcount))
{
lprintf (r,
"[%d]SVs: Entry-SVs: %d -OBJs: %d Curr-SVs: %d -OBJs: %d\n"
, r -> nPid, r -> stsv_count, r -> stsv_objcount, sv_count, sv_objcount) ;
r -> lstsv_count = sv_count ;
r -> lstsv_objcount = sv_objcount ;
}
if
(r -> CmdStack.State.bProcessCmds == cmdAll && !(r -> bOptions & optDisableHtmlScan))
{
n =
strcspn
(p,
"[<"
) ;
p += n ;
}
else
p =
strchr
(p,
'['
) ;
if
(p == NULL)
{
owrite (r, r -> Buf.pCurrPos, r -> Buf.pEndPos - r -> Buf.pCurrPos) ;
break
;
}
if
(r -> CmdStack.State.bProcessCmds == cmdAll)
owrite (r, r -> Buf.pCurrPos, p - r -> Buf.pCurrPos) ;
if
(*p ==
'\0'
)
break
;
if
(r -> bDebug & dbgSource)
{
char
* s = p ;
char
* n ;
while
(*s &&
isspace
(*s))
s++ ;
if
(*s)
{
GetLineNo (r) ;
n =
strchr
(s,
'\n'
) ;
#ifdef CLOCKS_PER_SEC
if
(r -> bDebug & dbgProfile)
if
(n)
lprintf (r,
"[%d]SRC: Line %d: Time %d ms %*.*s\n"
, r -> nPid, r -> Buf.nSourceline, ((
clock
() - r -> startclock) * 1000 / CLOCKS_PER_SEC), n-s, n-s, s) ;
else
lprintf (r,
"[%d]SRC: Line %d: Time %d ms %60.60s\n"
, r -> nPid, r -> Buf.nSourceline, ((
clock
() - r -> startclock) * 1000 / CLOCKS_PER_SEC), s) ;
else
#endif
if
(n)
lprintf (r,
"[%d]SRC: Line %d: %*.*s\n"
, r -> nPid, r -> Buf.nSourceline, n-s, n-s, s) ;
else
lprintf (r,
"[%d]SRC: Line %d: %60.60s\n"
, r -> nPid, r -> Buf.nSourceline, s) ;
}
}
r -> Buf.pCurrStart = p ;
if
(*p ==
'<'
)
{
rc = ScanHtmlTag (r, p) ;
}
else
{
if
(p[1] ==
'*'
)
break
;
rc = ScanCmdEvals (r, p) ;
}
p = r -> Buf.pCurrPos ;
}
if
(rc != ok)
{
if
(rc != rcExit)
LogError (r, rc) ;
return
0 ;
}
return
r -> Buf.nBlockNo ;
}
int
ReadInputFile (
register
req * r)
{
int
rc = ok ;
SV * pBufSV = NULL ;
req * pMain = r ;
#ifdef EP2
if
(!r -> bEP1Compat)
{
SV * * ppSV ;
ppSV = hv_fetch (r -> Buf.pFile -> pCacheHash,
"P-1----"
, 7, 0) ;
if
(ppSV && *ppSV)
{
r -> Buf.pBuf = NULL ;
r -> Buf.pFile -> nFilesize = 1 ;
return
ok ;
}
}
#endif
if
((pBufSV = r -> Buf.pFile -> pBufSV) == NULL || !SvPOK (pBufSV))
{
if
(SvROK(r -> pInData))
{
STRLEN n ;
r -> Buf.pBuf = SvPV (pBufSV = SvRV(r -> pInData), n) ;
r -> Buf.pFile -> nFilesize = n ;
}
else
{
rc = ReadHTML (r, r -> Buf.pFile -> sSourcefile, &r -> Buf.pFile -> nFilesize, &pBufSV) ;
if
(rc == ok)
r -> Buf.pBuf = SvPVX (pBufSV) ;
}
if
(rc == ok)
{
SvREFCNT_inc (pBufSV) ;
r -> Buf.pFile -> pBufSV = pBufSV ;
r -> Buf.pEndPos = r -> Buf.pBuf + r -> Buf.pFile -> nFilesize ;
if
(r -> Buf.pFile -> pNext2Free == NULL)
{
while
(pMain && pMain -> pLastReq != &InitialReq)
pMain = pMain -> pLastReq ;
if
((r -> Buf.pFile -> pNext2Free = pMain -> pFiles2Free) == NULL)
r -> Buf.pFile -> pNext2Free = r -> Buf.pFile ;
pMain -> pFiles2Free = r -> Buf.pFile ;
}
}
}
else
{
r -> Buf.pBuf = SvPVX (pBufSV) ;
r -> Buf.pFile -> nFilesize = SvCUR (pBufSV) ;
}
return
rc ;
}
int
ProcessSub (
register
req * r,
tFile * pFile,
int
nBlockStart,
int
nBlockNo)
{
int
rc ;
tSrcBuf Buf ;
char
* sEvalPackage = r -> Buf.sEvalPackage ;
STRLEN nEvalPackage = r -> Buf.nEvalPackage ;
SV * pInData = r -> pInData ;
memcpy
(&Buf, &r -> Buf,
sizeof
(Buf)) ;
if
(pFile != r -> Buf.pFile)
{
r -> Buf.pFile = pFile ;
r -> pInData = &sv_undef ;
if
((rc = ReadInputFile (r)) != ok)
{
LogError (r, rc) ;
return
rc ;
}
r -> Buf.pSourcelinePos = r -> Buf.pBuf ;
r -> Buf.nSourceline = r -> Buf.pFile -> nFirstLine ;
r -> Buf.pLineNoCurrPos = NULL ;
r -> Buf.sEvalPackage = r -> Buf.pFile -> sCurrPackage ;
r -> Buf.nEvalPackage = r -> Buf.pFile -> nCurrPackage ;
}
r -> nInsideSub++ ;
rc = ProcessBlock (r, nBlockStart, r -> Buf.pFile -> nFilesize - nBlockStart, nBlockNo) ;
r -> nInsideSub-- ;
memcpy
(&r -> Buf, &Buf,
sizeof
(Buf)) ;
r -> Buf.sEvalPackage = sEvalPackage ;
r -> Buf.nEvalPackage = nEvalPackage ;
r -> pInData = pInData ;
if
(rc != ok)
LogError (r, rc) ;
return
rc ;
}
int
ExecuteReq (
register
req * r,
SV * pReqSV)
{
int
rc = ok ;
char
olddir[PATH_MAX];
char
* sInputfile = r -> Buf.pFile -> sSourcefile ;
#ifdef WIN32
int
olddrive ;
#endif
dTHR ;
EPENTRY (ExecuteReq) ;
if
(!r -> Buf.pFile -> pExportHash)
r -> Buf.pFile -> pExportHash = newHV () ;
ENTER;
SAVETMPS ;
SetupSafeNamespace (r) ;
if
(rc == ok && !(r -> bOptions & optDisableFormData) &&
av_len (r -> pFormArray) == -1 && !r -> bSubReq &&
r -> pImportStash == NULL)
rc = GetInputData_CGIScript (r) ;
if
(rc == ok)
rc = StartOutput (r) ;
#ifdef xxxEP2
if
(rc == ok && r -> bEP1Compat)
#else
if
(rc == ok)
#endif
rc = ReadInputFile (r) ;
if
(rc == ok && r -> Buf.pBuf == NULL && r -> Buf.pFile -> nFilesize == 0)
rc = rcMissingInput ;
#ifdef APACHE
if
(rc != ok || (r -> pApacheReq && r -> pApacheReq -> header_only && (r -> bOptions & optEarlyHttpHeader)))
#else
if
(rc != ok)
#endif
{
if
(rc != ok)
LogError (r, rc);
#ifdef APACHE
r -> pApacheReq = NULL ;
#endif
r -> bReqRunning = 0 ;
FREETMPS ;
LEAVE;
return
rc ;
}
if
((r -> bOptions & optDisableChdir) == 0 && sInputfile != NULL && sInputfile !=
'\0'
&& !SvROK(r -> pInData))
{
char
dir[PATH_MAX];
#ifdef WIN32
char
drive[_MAX_DRIVE];
char
fname[_MAX_FNAME];
char
ext[_MAX_EXT];
char
* c = sInputfile ;
char
* p ;
while
(*c)
{
if
(*c ==
'/'
)
*c =
'\\'
;
c++ ;
}
olddrive = _getdrive () ;
getcwd (olddir,
sizeof
(olddir) - 1) ;
if
(sInputfile[1] ==
':'
)
{
drive[0] =
toupper
(sInputfile[0]) ;
c = sInputfile + 2 ;
}
else
{
drive[0] = olddrive + 64 ;
c = sInputfile ;
}
dir[0] = drive[0] ;
dir[1] =
':'
;
p =
strrchr
(sInputfile,
'\\'
) ;
if
(p && p - c < PATH_MAX - 4)
{
memcpy
(dir+2, c, p - c) ;
dir[2 + (p - c)] =
'\0'
;
}
else
{
dir[2] =
'.'
;
dir[3] =
'\0'
;
}
if
(_chdrive (
toupper
(drive[0]) -
'A'
+ 1) < 0)
lprintf (r,
"Cannot change to drive %c\n"
, drive[0] ) ;
if
(chdir (dir) < 0)
lprintf (r,
"Cannot change directory to %s on drive %c for file %s\n"
, dir, drive[0], sInputfile ) ;
#else
Dirname (sInputfile, dir,
sizeof
(dir) - 1) ;
getcwd (olddir,
sizeof
(olddir) - 1) ;
if
(chdir (dir) < 0)
lprintf (r,
"Cannot change directory to %s\n"
, dir ) ;
#endif
}
else
r -> bOptions |= optDisableChdir ;
r -> bReqRunning = 1 ;
if
((rc = ProcessFile (r, r -> Buf.pFile -> nFilesize)) != ok)
if
(rc == rcExit)
rc = ok ;
else
LogError (r, rc) ;
FREETMPS ;
LEAVE;
r -> bReqRunning = 0 ;
if
((rc = EndOutput (r, rc, r -> pOutData)) != ok)
LogError (r, rc) ;
if
((r -> bOptions & optDisableChdir) == 0)
{
#ifdef WIN32
_chdrive (olddrive) ;
#endif
chdir (olddir) ;
}
if
((rc = ResetRequest (r, sInputfile)) != ok)
LogError (r, rc) ;
return
ok ;
}