From Code to Community: Sponsoring The Perl and Raku Conference 2025 Learn more

/*###################################################################################
#
# Embperl - Copyright (c) 1997-2008 Gerald Richter / ecos gmbh www.ecos.de
# Embperl - Copyright (c) 2008-2015 Gerald Richter
# Embperl - Copyright (c) 2015-2023 actevy.io
#
# You may distribute under the terms of either the GNU General Public
# License or the Artistic License, as specified in the Perl README file.
# For use with Apache httpd and mod_perl, see also Apache copyright.
#
# THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
###################################################################################*/
#include "ep.h"
#include "epmacro.h"
/* ---------------------------------------------------------------------------- */
/* Commandtable... */
/* ---------------------------------------------------------------------------- */
static int CmdIf (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int CmdElse (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int CmdElsif (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int CmdEndif (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int CmdWhile (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int CmdEndwhile (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int CmdDo (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int CmdUntil (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int CmdForeach (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int CmdEndforeach (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int CmdHidden (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int CmdVar (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int CmdSub (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int CmdEndsub (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlTable (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlTableHead (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlSelect (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlEndselect (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlOption (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlEndtable (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlRow (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlEndrow (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlInput (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlTextarea (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlEndtextarea (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlBody (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlA (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlIMG (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlASRC (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlForm (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlEndform (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
static int HtmlMeta (/*i/o*/ register req * r,
/*in*/ const char * sArg) ;
struct tCmd CmdTab [] =
{
/* cmdname function push pop type scan save no disable bHtml */
{ "/dir", HtmlEndtable, 0, 1, cmdTable, 0, 0, cnDir , optDisableTableScan, 1 } ,
{ "/dl", HtmlEndtable, 0, 1, cmdTable, 0, 0, cnDl , optDisableTableScan, 1 } ,
{ "/form", HtmlEndform, 0, 0, cmdNorm, 0, 0, cnNop , 0 , 1 } ,
{ "/menu", HtmlEndtable, 0, 1, cmdTable, 0, 0, cnMenu , optDisableTableScan, 1 } ,
{ "/ol", HtmlEndtable, 0, 1, cmdTable, 0, 0, cnOl , optDisableTableScan, 1 } ,
{ "/select", HtmlEndselect, 0, 1, cmdTable, 0, 0, cnSelect , optDisableSelectScan, 1 } ,
{ "/table", HtmlEndtable, 0, 1, cmdTable, 0, 0, cnTable , optDisableTableScan, 1 } ,
{ "/textarea", HtmlEndtextarea, 0, 1, cmdTextarea, 0, 0, cnNop , optDisableInputScan, 1 } ,
{ "/tr", HtmlEndrow, 0, 1, cmdTablerow, 0, 0, cnTr , optDisableTableScan, 1 } ,
{ "/ul", HtmlEndtable, 0, 1, cmdTable, 0, 0, cnUl , optDisableTableScan, 1 } ,
{ "a", HtmlA, 0, 0, cmdNorm, 0, 0, cnNop , 0 , 1 } ,
{ "body", HtmlBody, 0, 0, cmdNorm, 1, 0, cnNop , 0 , 1 } ,
{ "dir", HtmlTable, 1, 0, cmdTable, 1, 0, cnDir , optDisableTableScan, 1 } ,
{ "dl", HtmlTable, 1, 0, cmdTable, 1, 0, cnDl , optDisableTableScan, 1 } ,
{ "do", CmdDo, 1, 0, cmdDo, 0, 0, cnNop , 0 , 0 } ,
{ "else", CmdElse, 0, 0, cmdIf, 0, 0, cnNop , 0 , 0 } ,
{ "elsif", CmdElsif, 0, 0, cmdIf, 0, 0, cnNop , 0 , 0 } ,
{ "embed", HtmlASRC, 0, 0, cmdNorm, 0, 0, cnNop , 0 , 1 } ,
{ "endforeach", CmdEndforeach, 0, 1, cmdForeach, 0, 0, cnNop , 0 , 0 } ,
{ "endif", CmdEndif, 0, 1, (enum tCmdType)(cmdIf | cmdEndif), 0, 0, cnNop , 0, 0 } ,
{ "endsub", CmdEndsub, 0, 1, cmdSub, 0, 0, cnNop , 0 , 0 } ,
{ "endwhile", CmdEndwhile, 0, 1, cmdWhile, 0, 0, cnNop , 0 , 0 } ,
{ "foreach", CmdForeach, 1, 0, cmdForeach, 0, 1, cnNop , 0 , 0 } ,
{ "form", HtmlForm, 0, 0, cmdNorm, 0, 0, cnNop , 0 , 1 } ,
{ "frame", HtmlASRC, 0, 0, cmdNorm, 0, 0, cnNop , 0 , 1 } ,
{ "hidden", CmdHidden, 0, 0, cmdNorm, 0, 0, cnNop , 0 , 0 } ,
{ "if", CmdIf, 1, 0, (enum tCmdType)(cmdIf | cmdEndif), 0, 0, cnNop , 0, 0 } ,
{ "iframe", HtmlASRC, 0, 0, cmdNorm, 0, 0, cnNop , 0 , 1 } ,
{ "img", HtmlIMG, 0, 0, cmdNorm, 0, 0, cnNop , 0 , 1 } ,
{ "input", HtmlInput, 0, 0, cmdNorm, 1, 0, cnNop , optDisableInputScan, 1 } ,
{ "layer", HtmlASRC, 0, 0, cmdNorm, 0, 0, cnNop , 0 , 1 } ,
{ "menu", HtmlTable, 1, 0, cmdTable, 1, 0, cnMenu , optDisableTableScan, 1 } ,
{ "meta", HtmlMeta, 0, 0, cmdNorm, 1, 0, cnNop , optDisableMetaScan , 1 } ,
{ "ol", HtmlTable, 1, 0, cmdTable, 1, 0, cnOl , optDisableTableScan, 1 } ,
{ "option", HtmlOption, 0, 0, cmdNorm, 1, 0, cnNop , optDisableInputScan, 1 } ,
{ "select", HtmlSelect, 1, 0, cmdTable, 1, 0, cnSelect , optDisableSelectScan, 1 } ,
{ "sub", CmdSub, 1, 0, cmdSub, 0, 0, cnNop , 0 , 0 } ,
{ "table", HtmlTable, 1, 0, cmdTable, 1, 0, cnTable , optDisableTableScan, 1 } ,
{ "textarea", HtmlTextarea, 1, 0, cmdTextarea, 1, 1, cnNop , optDisableInputScan, 1 } ,
{ "th", HtmlTableHead, 0, 0, cmdNorm, 1, 0, cnNop , optDisableTableScan, 1 } ,
{ "tr", HtmlRow, 1, 0, cmdTablerow, 1, 0, cnTr , optDisableTableScan, 1 } ,
{ "ul", HtmlTable, 1, 0, cmdTable, 1, 0, cnUl , optDisableTableScan, 1 } ,
{ "until", CmdUntil, 0, 1, cmdDo, 0, 0, cnNop , 0 , 0 } ,
{ "var", CmdVar, 0, 0, cmdNorm, 0, 0, cnNop , 0 , 0 } ,
{ "while", CmdWhile, 1, 0, cmdWhile, 0, 1, cnNop , 0 , 0 } ,
} ;
/* */
/* compare commands */
/* */
static int CmpCmd (/*in*/ const void * p1,
/*in*/ const void * p2)
{
return strcmp (*((const char * *)p1), *((const char * *)p2)) ;
}
/* */
/* Search Command in Commandtable */
/* */
int SearchCmd (/*i/o*/ register req * r,
/*in*/ const char * sCmdName,
/*in*/ int nCmdLen,
/*in*/ const char * sArg,
/*in*/ int bIgnore,
/*out*/ struct tCmd * * ppCmd)
{
struct tCmd * pCmd ;
char sCmdLwr [64] ;
char * p ;
int i ;
EPENTRY (SearchCmd) ;
i = sizeof (sCmdLwr) - 1 ;
p = sCmdLwr ;
while (nCmdLen-- > 0 && --i > 0)
if ((*p++ = tolower (*sCmdName++)) == '\0')
break ;
*p = '\0' ;
p = sCmdLwr ;
pCmd = (struct tCmd *)bsearch (&p, CmdTab, sizeof (CmdTab) / sizeof (struct tCmd), sizeof (struct tCmd), CmpCmd) ;
if (pCmd && (pCmd -> bDisableOption & r -> Component.Config.bOptions))
pCmd = NULL ; /* command is disabled */
if (pCmd && ((pCmd -> bHtml == 0) ^ (bIgnore == 0)))
pCmd = NULL ; /* command is not of right type (html <-> meta cmd) */
if (r -> Component.Config.bDebug & dbgAllCmds)
if (sArg && *sArg != '\0')
lprintf (r -> pApp, "[%d]CMD%c: Cmd = '%s' Arg = '%s'\n", r -> pThread -> nPid, (pCmd == NULL)?'-':'+', sCmdLwr, sArg) ;
else
lprintf (r -> pApp, "[%d]CMD%c: Cmd = '%s'\n", r -> pThread -> nPid, (pCmd == NULL)?'-':'+', sCmdLwr) ;
if (pCmd == NULL && bIgnore)
return rcCmdNotFound ;
if ((r -> Component.Config.bDebug & dbgCmd) && (r -> Component.Config.bDebug & dbgAllCmds) == 0)
if (sArg && *sArg != '\0')
lprintf (r -> pApp, "[%d]CMD: Cmd = '%s' Arg = '%s'\n", r -> pThread -> nPid, sCmdLwr, sArg) ;
else
lprintf (r -> pApp, "[%d]CMD: Cmd = '%s'\n", r -> pThread -> nPid, sCmdLwr) ;
if (pCmd == NULL)
{
strncpy (r -> errdat1, sCmdLwr, sizeof (r -> errdat1) - 1) ;
return rcCmdNotFound ;
}
*ppCmd = pCmd ;
return ok ;
}
/* */
/* Process a Command */
/* */
static int ProcessAllCmds (/*i/o*/ register req * r,
/*in*/ struct tCmd * pCmd,
/*in*/ const char * sArg,
/*in*/ tStackPointer *pSP)
{
int rc ;
struct tStackEntry * pStack ;
struct tStackEntry * pState = &pSP -> State ;
EPENTRY (ProcessAllCmds) ;
if (pCmd -> bPush)
{
if (pSP -> pStackFree)
{
pStack = pSP -> pStackFree ;
pSP -> pStackFree = pSP -> pStackFree -> pNext ;
}
else
{
pStack = _malloc (r, sizeof (struct tStackEntry)) ;
}
memcpy (pStack, pState, sizeof (*pStack)) ;
pStack -> pNext = pSP -> pStack ;
pSP -> pStack = pStack ;
pState -> nCmdType = pCmd -> nCmdType ;
pState -> pStart = r -> Component.pCurrPos ;
pState -> nBlockNo = r -> Buf.nBlockNo ;
if (pCmd -> bSaveArg)
pState -> sArg = _ep_strdup (r, sArg) ;
else
pState -> sArg = NULL ;
pState -> pSV = NULL ;
pState -> pSV2 = NULL ;
pState -> pBuf = NULL ;
pState -> pNext = NULL ;
pState -> pCmd = pCmd ;
}
r -> pCurrCmd = pCmd ;
rc = (*pCmd -> pProc)(r, sArg) ;
if (rc == rcEvalErr)
rc = ok ;
if (pCmd -> bPop && pState -> pStart == NULL && rc != rcExit)
{
pStack = pSP -> pStack ;
if (pStack == NULL)
return rcStackUnderflow ;
else
{
if (pState -> sArg)
_free (r, pState -> sArg) ;
if (pState -> pSV)
SvREFCNT_dec (pState -> pSV) ;
if (pState -> pSV2)
SvREFCNT_dec (pState -> pSV2) ;
memcpy (pState, pStack, sizeof (*pState)) ;
pSP -> pStack = pStack -> pNext ;
pStack -> pNext = pSP -> pStackFree ;
pSP -> pStackFree = pStack ;
}
}
return rc ;
}
int ProcessCmd (/*i/o*/ register req * r,
/*in*/ struct tCmd * pCmd,
/*in*/ const char * sArg)
{
EPENTRY (ProcessCmd) ;
if ((pCmd -> nCmdType & r -> CmdStack.State.bProcessCmds) == 0)
return ok ; /* ignore it */
if (pCmd -> bHtml)
return ProcessAllCmds (r, pCmd, sArg, &r -> HtmlStack) ;
return ProcessAllCmds (r, pCmd, sArg, &r -> CmdStack) ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* if command ... */
/* */
/* ---------------------------------------------------------------------------- */
static int CmdIf (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
int rc = ok ;
EPENTRY (CmdIf) ;
if (r -> CmdStack.State.bProcessCmds == cmdAll)
{
rc = EvalBool (r, (char *)sArg, (sArg - r -> Component.pBuf), &r -> CmdStack.State.nResult) ;
if (r -> CmdStack.State.nResult && rc == ok)
{
r -> CmdStack.State.bProcessCmds = cmdAll ;
}
else
{
r -> CmdStack.State.bProcessCmds = cmdIf ;
}
}
else
r -> CmdStack.State.nResult = -1 ;
return rc ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* elsif command ... */
/* */
/* ---------------------------------------------------------------------------- */
static int CmdElsif (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
int rc = ok ;
EPENTRY (CmdElsif) ;
if ((r -> CmdStack.State.nCmdType & cmdIf) == 0)
return rcElseWithoutIf ;
if (r -> CmdStack.State.nResult == -1)
return ok ;
if (r -> CmdStack.State.nResult == 0)
{
rc = EvalBool (r, (char *)sArg, (sArg - r -> Component.pBuf), &r -> CmdStack.State.nResult) ;
if (r -> CmdStack.State.nResult && rc == ok)
r -> CmdStack.State.bProcessCmds = cmdAll ;
else
r -> CmdStack.State.bProcessCmds = cmdIf ;
}
else
{
r -> CmdStack.State.bProcessCmds = cmdEndif ;
r -> CmdStack.State.nResult = 0 ;
}
return rc ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* else command ... */
/* */
/* ---------------------------------------------------------------------------- */
static int CmdElse (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
EPENTRY (CmdElse) ;
if ((r -> CmdStack.State.nCmdType & cmdIf) == 0)
return rcElseWithoutIf ;
if (r -> CmdStack.State.nResult == -1)
return ok ;
if (r -> CmdStack.State.nResult)
{
r -> CmdStack.State.bProcessCmds = cmdIf ;
r -> CmdStack.State.nResult = 0 ;
}
else
{
r -> CmdStack.State.bProcessCmds = cmdAll ;
r -> CmdStack.State.nResult = 1 ;
}
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* endif command ... */
/* */
/* ---------------------------------------------------------------------------- */
static int CmdEndif (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
EPENTRY (CmdEndif) ;
r -> CmdStack.State.pStart = NULL ;
if ((r -> CmdStack.State.nCmdType & cmdIf) == 0)
return rcEndifWithoutIf ;
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* while command ... */
/* */
/* ---------------------------------------------------------------------------- */
static int CmdWhile (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
int rc ;
EPENTRY (CmdWhile) ;
if (r -> CmdStack.State.bProcessCmds == cmdWhile)
return ok ;
rc = EvalBool (r, (char *)sArg, (r -> CmdStack.State.pStart - r -> Component.pBuf), &r -> CmdStack.State.nResult) ;
if (r -> CmdStack.State.nResult && rc == ok)
r -> CmdStack.State.bProcessCmds = cmdAll ;
else
r -> CmdStack.State.bProcessCmds = cmdWhile ;
return rc ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* endwhile command ... */
/* */
/* ---------------------------------------------------------------------------- */
static int CmdEndwhile (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
int rc = ok ;
EPENTRY (CmdEndwhile) ;
if (r -> CmdStack.State.nCmdType != cmdWhile)
return rcEndwhileWithoutWhile ;
if (r -> CmdStack.State.nResult)
{
rc = EvalBool (r, r -> CmdStack.State.sArg, (r -> CmdStack.State.pStart - r -> Component.pBuf), &r -> CmdStack.State.nResult) ;
if (r -> CmdStack.State.nResult && rc == ok)
{
r -> Component.pCurrPos = r -> CmdStack.State.pStart ;
r -> Buf.nBlockNo = r -> CmdStack.State.nBlockNo ;
return rc ;
}
}
r -> CmdStack.State.pStart = NULL ;
return rc ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* do command ... */
/* */
/* ---------------------------------------------------------------------------- */
static int CmdDo (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
EPENTRY (CmdDo) ;
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* until command ... */
/* */
/* ---------------------------------------------------------------------------- */
static int CmdUntil (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
int rc = ok ;
EPENTRY (CmdUntil) ;
if (r -> CmdStack.State.nCmdType != cmdDo)
return rcUntilWithoutDo ;
rc = EvalBool (r, (char *)sArg, (r -> CmdStack.State.pStart - r -> Component.pBuf), &r -> CmdStack.State.nResult) ;
if (!r -> CmdStack.State.nResult && rc == ok && !r -> Component.pImportStash)
{
r -> Component.pCurrPos = r -> CmdStack.State.pStart ;
r -> Buf.nBlockNo = r -> CmdStack.State.nBlockNo ;
return rc ;
}
r -> CmdStack.State.pStart = NULL ;
return rc ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* foreach command ... */
/* */
/* ---------------------------------------------------------------------------- */
static int CmdForeach (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
int rc ;
char * sArgs ;
char * sVarName ;
char sVar[512] ;
SV * * ppSV ;
SV * pRV ;
int nMax ;
int n ;
int c ;
EPENTRY (CmdForeach) ;
if (r -> CmdStack.State.bProcessCmds == cmdForeach)
return ok ;
sArgs = r -> CmdStack.State.sArg ;
while (isspace (*sArgs))
sArgs++ ;
if (*sArgs != '\0')
{
n = strcspn (sArgs, ", \t\n(") ;
sVarName = sArgs + n ;
if (*sVarName != '\0')
{
if (*sArgs == '$')
sArgs++ ;
c = *sVarName ;
*sVarName = '\0' ;
if (!strstr (sArgs, "::"))
{
strncpy (sVar, r -> Component.sEvalPackage, sizeof (sVar) - 5) ;
sVar[r -> Component.nEvalPackage] = ':' ;
sVar[r -> Component.nEvalPackage+1] = ':' ;
sVar[sizeof(sVar) - 1] = '\0' ;
nMax = sizeof(sVar) - r -> Component.nEvalPackage - 3 ;
strncpy (sVar + r -> Component.nEvalPackage + 2, sArgs, nMax) ;
if ((r -> CmdStack.State.pSV = perl_get_sv (sVar, TRUE)) == NULL)
return rcPerlVarError ;
}
else
if ((r -> CmdStack.State.pSV = perl_get_sv (sArgs, TRUE)) == NULL)
return rcPerlVarError ;
*sVarName = c ;
SvREFCNT_inc (r -> CmdStack.State.pSV) ;
if (*sVarName != '(')
sVarName++ ;
if ((rc = EvalTransFlags (r, sVarName, (r -> CmdStack.State.pStart - r -> Component.pBuf), G_ARRAY, &pRV)) != ok)
return rc ;
if (r -> Component.pImportStash)
return ok ;
if (pRV == NULL)
return rcMissingArgs ;
if (!SvROK (pRV))
{
SvREFCNT_dec (pRV) ;
return rcNotAnArray ;
}
r -> CmdStack.State.pSV2 = SvRV (pRV) ;
SvREFCNT_inc (r -> CmdStack.State.pSV2) ;
SvREFCNT_dec (pRV) ;
if (SvTYPE (r -> CmdStack.State.pSV2) != SVt_PVAV)
return rcNotAnArray ;
}
}
if (r -> CmdStack.State.pSV == NULL || r -> CmdStack.State.pSV2 == NULL)
return rcMissingArgs ;
r -> CmdStack.State.nResult = 0 ; /* array index */
ppSV = av_fetch ((AV *)r -> CmdStack.State.pSV2, r -> CmdStack.State.nResult, 0) ;
if (ppSV != NULL && *ppSV != NULL)
{
r -> CmdStack.State.bProcessCmds = cmdAll ;
sv_setsv (r -> CmdStack.State.pSV, *ppSV) ;
r -> CmdStack.State.nResult++ ;
}
else
r -> CmdStack.State.bProcessCmds = cmdForeach ;
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* endforeach command ... */
/* */
/* ---------------------------------------------------------------------------- */
static int CmdEndforeach (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
SV ** ppSV ;
EPENTRY (CmdEndforeach) ;
if (r -> CmdStack.State.nCmdType != cmdForeach)
return rcEndforeachWithoutForeach ;
if (r -> CmdStack.State.pSV == NULL)
{
r -> CmdStack.State.pStart = NULL ;
return ok ;
}
ppSV = av_fetch ((AV *)r -> CmdStack.State.pSV2, r -> CmdStack.State.nResult, 0) ;
if (ppSV != NULL && *ppSV != NULL)
{
sv_setsv (r -> CmdStack.State.pSV, *ppSV) ;
r -> CmdStack.State.nResult++ ;
r -> Component.pCurrPos = r -> CmdStack.State.pStart ;
r -> Buf.nBlockNo = r -> CmdStack.State.nBlockNo ;
}
else
r -> CmdStack.State.pStart = NULL ;
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* hidden command ... */
/* */
/* ---------------------------------------------------------------------------- */
static int CmdHidden (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
char * pKey ;
SV * psv ;
SV * * ppsv ;
HV * pAddHash = r -> pThread -> pFormHash ;
HV * pSubHash = r -> pThread -> pInputHash ;
AV * pSort = NULL ;
HE * pEntry ;
I32 l ;
char * sArgs ;
char * sVarName ;
char sVar[512] ;
int nMax ;
STRLEN nKey ;
EPENTRY (CmdHidden) ;
sArgs = _ep_strdup (r, sArg) ;
if (sArgs && *sArgs != '\0')
{
strncpy (sVar, r -> Component.sEvalPackage, sizeof (sVar) - 5) ;
sVar[r -> Component.nEvalPackage] = ':' ;
sVar[r -> Component.nEvalPackage+1] = ':' ;
sVar[sizeof(sVar) - 1] = '\0' ;
nMax = sizeof(sVar) - r -> Component.nEvalPackage - 3 ;
if ((sVarName = strtok (sArgs, ", \t\n")))
{
if (*sVarName == '%')
sVarName++ ;
strncpy (sVar + r -> Component.nEvalPackage + 2, sVarName, nMax) ;
if ((pAddHash = perl_get_hv ((char *)sVar, FALSE)) == NULL)
{
strncpy (r -> errdat1, sVar, sizeof (r -> errdat1) - 1) ;
_free (r, sArgs) ;
return rcHashError ;
}
if ((sVarName = strtok (NULL, ", \t\n")))
{
if (*sVarName == '%')
sVarName++ ;
strncpy (sVar + r -> Component.nEvalPackage + 2, sVarName, nMax) ;
if ((pSubHash = perl_get_hv ((char *)sVar, FALSE)) == NULL)
{
strncpy (r -> errdat1, sVar, sizeof (r -> errdat1) - 1) ;
_free (r, sArgs) ;
return rcHashError ;
}
if ((sVarName = strtok (NULL, ", \t\n")))
{
if (*sVarName == '@')
sVarName++ ;
strncpy (sVar + r -> Component.nEvalPackage + 2, sVarName, nMax) ;
if ((pSort = perl_get_av ((char *)sVar, FALSE)) == NULL)
{
strncpy (r -> errdat1, sVar, sizeof (r -> errdat1) - 1) ;
_free (r, sArgs) ;
return rcArrayError ;
}
}
}
}
}
else
pSort = r -> pThread -> pFormArray ;
oputc (r, '\n') ;
if (pSort)
{
int n = AvFILL (pSort) + 1 ;
int i ;
for (i = 0; i < n; i++)
{
ppsv = av_fetch (pSort, i, 0) ;
if (ppsv && (pKey = SvPV(*ppsv, nKey)) && !hv_exists (pSubHash, pKey, nKey))
{
ppsv = hv_fetch (pAddHash, pKey, nKey, 0) ;
if (ppsv && (!(r -> Component.Config.bOptions & optNoHiddenEmptyValue) || *SvPV (*ppsv, na)))
{
oputs (r, "<input type=\"hidden\" name=\"") ;
OutputToHtml (r, pKey) ;
oputs (r, "\" value=\"") ;
OutputToHtml (r, SvPV (*ppsv, na)) ;
oputs (r, "\">\n") ;
}
}
}
}
else
{
hv_iterinit (pAddHash) ;
while ((pEntry = hv_iternext (pAddHash)))
{
pKey = hv_iterkey (pEntry, &l) ;
if (!hv_exists (pSubHash, pKey, strlen (pKey)))
{
psv = hv_iterval (pAddHash, pEntry) ;
if (!(r -> Component.Config.bOptions & optNoHiddenEmptyValue) || *SvPV (psv, na))
{
oputs (r, "<input type=\"hidden\" name=\"") ;
OutputToHtml (r, pKey) ;
oputs (r, "\" value=\"") ;
OutputToHtml (r, SvPV (psv, na)) ;
oputs (r, "\">\n") ;
}
}
}
}
if (sArgs)
_free (r, sArgs) ;
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* var command ... */
/* */
/* ---------------------------------------------------------------------------- */
static int CmdVar (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
int rc ;
SV ** ppSV ;
int nFilepos = (sArg - r -> Component.pBuf) ;
SV * pSV ;
dTHR ;
EPENTRY (CmdVar) ;
r -> Component.bStrict = HINT_STRICT_REFS | HINT_STRICT_SUBS | HINT_STRICT_VARS ;
/* Already compiled ? */
ppSV = hv_fetch(r -> Buf.pFile -> pCacheHash, (char *)&nFilepos, sizeof (nFilepos), 1) ;
if (ppSV == NULL)
{
strcpy (r -> errdat1, "CacheHash") ;
return rcHashError ;
}
if (SvTRUE(*ppSV))
return ok ;
sv_setiv (*ppSV, 1) ;
tainted = 0 ;
pSV = newSVpvf("package %s ; \n#line %d %s\n use vars qw(%s); map { $%s::CLEANUP{substr ($_, 1)} = 1 } qw(%s) ;\n",
r -> Component.sEvalPackage, r -> Component.nSourceline, r -> Component.sSourcefile, sArg,
r -> Component.sEvalPackage, sArg) ;
newSVpvf2(pSV) ;
rc = EvalDirect (r, pSV, 0, NULL) ;
SvREFCNT_dec(pSV);
return rc ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* sub command ... */
/* */
/* ---------------------------------------------------------------------------- */
static int CmdSub (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
int nSubPos = r -> Component.pCurrPos - r -> Component.pBuf ;
int nFilepos = (sArg - r -> Component.pBuf) ;
char sSubCode [128] ;
EPENTRY (CmdSub) ;
/* remember the start of the sub */
SetSubTextPos (r, sArg, nSubPos) ;
/* skip everything until endsub */
r -> CmdStack.State.bProcessCmds = cmdSub ;
/* compile perl sub */
/* sprintf (sSubCode, "unshift @_, HTML::Embperl::CurrReq (0) ; HTML::Embperl::ProcessSub (%d, %d, %d)", (int)r -> Buf.pFile, nSubPos, r -> Buf.nBlockNo) ; */
sprintf (sSubCode, " HTML::Embperl::ProcessSub (%ld, %d, %d)", (IV)r -> Buf.pFile, nSubPos, r -> Buf.nBlockNo) ;
while (isspace(*sArg))
sArg++ ;
return EvalSub (r, sSubCode, nFilepos, sArg) ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* endsub command ... */
/* */
/* ---------------------------------------------------------------------------- */
static int CmdEndsub (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
EPENTRY (CmdEndsub) ;
if (r -> CmdStack.State.nCmdType != cmdSub)
return rcExit ;
r -> CmdStack.State.bProcessCmds = cmdAll ;
r -> CmdStack.State.pStart = NULL ;
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* meta tag ... */
/* */
/* set http headers on meta http-equiv */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlMeta (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
char * pType ;
char * pContent ;
int tlen ;
int clen ;
EPENTRY (HtmlMeta) ;
pType = (char *)GetHtmlArg (sArg, "HTTP-EQUIV", &tlen) ;
if (tlen == 0)
return ok ; /* no http-equiv */
pContent = (char *)GetHtmlArg (sArg, "CONTENT", &clen) ;
if (clen == 0)
return ok ; /* missing content for http-equiv */
/*tsav = pType[tlen] ;
pType[tlen] = '\0' ;
csav = pContent[clen] ;
pContent[clen] = '\0' ;*/
hv_store (r -> pThread -> pHeaderHash, pType, tlen, newSVpv (pContent, clen), 0) ;
/*pType[tlen] = tsav ;
pContent[clen] = csav ;*/
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* body tag ... */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlBody (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
EPENTRY (HtmlBody) ;
if ((r -> Component.Config.bDebug & dbgLogLink) == 0)
return ok ;
oputs (r, r -> Buf.pCurrTag) ;
if (*sArg != '\0')
{
oputc (r, ' ') ;
oputs (r, sArg) ;
}
oputc (r, '>') ;
r -> Component.pCurrPos = NULL ;
if (r -> Component.Config.bDebug & dbgLogLink)
{
char pid [30] ;
char fp [30] ;
if (!r -> pConf -> sVirtLogURI)
{
LogError (r, rcVirtLogNotSet) ;
return ok ;
}
sprintf (pid, "%d", r -> pThread -> nPid) ;
sprintf (fp, "%ld", r -> nLogFileStartPos) ;
oputs (r, "<A HREF=\"") ;
oputs (r, r -> pConf -> sVirtLogURI) ;
oputs (r, "?") ;
oputs (r, fp) ;
oputs (r, "&") ;
oputs (r, pid) ;
oputs (r, "\">Logfile</A> / ") ;
oputs (r, "<A HREF=\"") ;
oputs (r, r -> pConf -> sVirtLogURI) ;
oputs (r, "?") ;
oputs (r, fp) ;
oputs (r, "&") ;
oputs (r, pid) ;
oputs (r, "&SRC:") ;
oputs (r, "\">Source only</A> / ") ;
oputs (r, "<A HREF=\"") ;
oputs (r, r -> pConf -> sVirtLogURI) ;
oputs (r, "?") ;
oputs (r, fp) ;
oputs (r, "&") ;
oputs (r, pid) ;
oputs (r, "&EVAL") ;
oputs (r, "\">Eval only</A>\n") ;
}
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* URLEscape ... */
/* */
/* ---------------------------------------------------------------------------- */
static int URLEscape (/*i/o*/ register req * r,
/*in*/ const char * sArg,
/*in*/ const char * sAttrName,
/*in*/ int bAppendSessionID)
{
int rc ;
char * pArgBuf = NULL ;
char * pFreeBuf = NULL ;
char * pAttr ;
int alen ;
EPENTRY (URLEscape) ;
oputs (r, r -> Buf.pCurrTag) ;
oputc (r, ' ') ;
if (*sArg != '\0')
{
pAttr = (char *)GetHtmlArg (sArg, sAttrName, &alen) ;
if (alen > 0)
{
char c = *pAttr ;
/* check part before ATTR */
*pAttr = '\0' ;
if ((rc = ScanCmdEvalsInString (r, (char *)sArg, &pArgBuf, nInitialScanOutputSize, &pFreeBuf)) != ok)
{
*pAttr = c ;
if (pFreeBuf)
_free (r, pFreeBuf) ;
return rc ;
}
oputs (r, pArgBuf) ;
*pAttr = c ;
if (pFreeBuf)
_free (r, pFreeBuf) ;
pFreeBuf = NULL ;
/* check ATTR part which should be URL escaped */
c = pAttr[alen] ;
pAttr[alen] = '\0' ;
if (r -> Component.Config.nEscMode & escUrl)
r -> Component.pCurrEscape = Char2Url ;
r -> Component.bEscInUrl = TRUE ;
if ((rc = ScanCmdEvalsInString (r, (char *)pAttr, &pArgBuf, nInitialScanOutputSize, &pFreeBuf)) != ok)
{
pAttr[alen] = c ;
r -> Component.bEscInUrl = FALSE ;
NewEscMode (r, NULL) ;
if (pFreeBuf)
_free (r, pFreeBuf) ;
return rc ;
}
oputs (r, pArgBuf) ;
if (bAppendSessionID && r -> sSessionID)
{
if (strchr(pArgBuf, '?'))
{
oputc(r, '&') ;
}
else
{
oputc(r, '?') ;
}
oputs (r, r -> sSessionID) ;
}
r -> Component.bEscInUrl = FALSE ;
NewEscMode (r, NULL) ;
if (pFreeBuf)
_free (r, pFreeBuf) ;
pFreeBuf = NULL ;
pAttr[alen] = c ;
/* check part after ATTR */
if ((rc = ScanCmdEvalsInString (r, (char *)pAttr + alen, &pArgBuf, nInitialScanOutputSize, &pFreeBuf)) != ok)
{
if (pFreeBuf)
_free (r, pFreeBuf) ;
return rc ;
}
oputs (r, pArgBuf) ;
if (pFreeBuf)
_free (r, pFreeBuf) ;
pFreeBuf = NULL ;
}
else
{
if ((rc = ScanCmdEvalsInString (r, (char *)sArg, &pArgBuf, nInitialScanOutputSize, &pFreeBuf)) != ok)
{
if (pFreeBuf)
_free (r, pFreeBuf) ;
return rc ;
}
oputs (r, pArgBuf) ;
if (pFreeBuf)
_free (r, pFreeBuf) ;
pFreeBuf = NULL ;
}
}
else
{
oputs (r, sArg) ;
}
oputc (r, '>') ;
r -> Component.pCurrPos = NULL ;
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* A tag ... */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlA (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
EPENTRY (HtmlA) ;
return URLEscape (r, sArg, "HREF", 1) ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* IMG tag ... */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlIMG (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
EPENTRY (HtmlIMG) ;
return URLEscape (r, sArg, "SRC", 0) ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* tag with SRC attribute... */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlASRC (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
EPENTRY (HtmlASRC) ;
return URLEscape (r, sArg, "SRC", 1) ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* Form tag ... */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlForm (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
EPENTRY (HtmlForm) ;
return URLEscape (r, sArg, "ACTION", 0) ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* /Form tag ... */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlEndform (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
char * sid = r -> sSessionID ;
EPENTRY (HtmlFormEnd) ;
if (sid)
{
char * val = strchr (sid, '=') ;
if (val)
{
oputs(r, "<input type=\"hidden\" name=\"") ;
owrite(r, sid, val - sid) ;
val++ ;
oputs(r, "\" value=\"") ;
oputs (r, val) ;
oputs(r, "\">") ;
}
}
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* table tag ... */
/* and various list tags ... (dir, menu, ol, ul) */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlTable (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
tTableStackEntry * pStack ;
EPENTRY (HtmlTable) ;
oputs (r, r -> Buf.pCurrTag) ;
if (*sArg != '\0')
{
oputc (r, ' ') ;
oputs (r, sArg) ;
}
oputc (r, '>') ;
pStack = r -> TableStack.pStackFree ;
if (pStack)
r -> TableStack.pStackFree = pStack -> pNext ;
else
pStack = _malloc (r, sizeof (struct tTableStackEntry)) ;
memcpy (pStack, &r -> TableStack.State, sizeof (*pStack)) ;
pStack -> pNext = r -> TableStack.pStack ;
r -> TableStack.pStack = pStack ;
memset (&r -> TableStack.State, 0, sizeof (r -> TableStack.State)) ;
r -> TableStack.State.nResult = 1 ;
r -> TableStack.State.nTabMode = r -> nTabMode ;
r -> TableStack.State.nMaxRow = r -> nTabMaxRow ;
r -> TableStack.State.nMaxCol = r -> nTabMaxCol ;
if ((r -> TableStack.State.nTabMode & epTabRow) == epTabRowDef)
r -> HtmlStack.State.pBuf = oBegin (r) ;
r -> Component.pCurrPos = NULL ;
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* table tag ... (and end of list) */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlEndtable (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
tTableStackEntry * pStack ;
EPENTRY (HtmlEndtable) ;
if (r -> HtmlStack.State.nCmdType != cmdTable || r -> HtmlStack.State.pCmd -> nCmdNo != r -> pCurrCmd -> nCmdNo)
{
strncpy (r -> errdat1, r -> Buf.pCurrTag + 1, sizeof (r -> errdat1) - 1) ;
if (r -> HtmlStack.State.pCmd)
strcpy (r -> errdat2, r -> HtmlStack.State.pCmd -> sCmdName) ;
else
strcpy (r -> errdat2, "NO TAG") ;
return rcEndtableWithoutTable ;
}
if (r -> Component.Config.bDebug & dbgTab)
lprintf (r -> pApp, "[%d]TAB: r -> nTabMode=%d nResult=%d nRow=%d Used=%d nCol=%d Used=%d nCnt=%d Used=%d \n",
r -> pThread -> nPid, r -> TableStack.State.nTabMode, r -> TableStack.State.nResult, r -> TableStack.State.nRow, r -> TableStack.State.nRowUsed, r -> TableStack.State.nCol, r -> TableStack.State.nColUsed, r -> TableStack.State.nCount, r -> TableStack.State.nCountUsed) ;
if ((r -> TableStack.State.nTabMode & epTabRow) == epTabRowDef)
if (r -> TableStack.State.nResult || r -> TableStack.State.nCol > 0)
oCommit (r, r -> HtmlStack.State.pBuf) ;
else
oRollback (r, r -> HtmlStack.State.pBuf) ;
r -> TableStack.State.nRow++ ;
if (((r -> TableStack.State.nTabMode & epTabRow) == epTabRowMax ||
((r -> TableStack.State.nResult || r -> TableStack.State.nCol > 0) && (r -> TableStack.State.nRowUsed || r -> TableStack.State.nCountUsed) )) &&
r -> TableStack.State.nRow < r -> TableStack.State.nMaxRow)
{
r -> Component.pCurrPos = r -> HtmlStack.State.pStart ;
r -> Buf.nBlockNo = r -> HtmlStack.State.nBlockNo ;
if ((r -> TableStack.State.nTabMode & epTabRow) == epTabRowDef)
r -> HtmlStack.State.pBuf = oBegin (r) ;
r -> TableStack.State.nResult = 1 ;
return ok ;
}
r -> HtmlStack.State.pStart = NULL ;
pStack = r -> TableStack.pStack ;
if (pStack == NULL)
return rcStackUnderflow ;
else
{
memcpy (&r -> TableStack.State, pStack, sizeof (r -> TableStack.State)) ;
r -> TableStack.pStack = pStack -> pNext ;
pStack -> pNext = r -> TableStack.pStackFree ;
r -> TableStack.pStackFree = pStack ;
}
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* tr tag ... */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlRow (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
EPENTRY (HtmlRow) ;
if (r -> TableStack.pStack == NULL)
return rcTablerowOutsideOfTable ;
oputs (r, r -> Buf.pCurrTag) ;
if (*sArg != '\0')
{
oputc (r, ' ') ;
oputs (r, sArg) ;
}
oputc (r, '>') ;
/* r -> TableStack.State.nResult = 1 ; */
r -> TableStack.State.nCol = 0 ;
r -> TableStack.State.nColUsed = 0 ;
r -> TableStack.State.bHead = r -> TableStack.State.bRowHead = 0 ;
if ((r -> TableStack.State.nTabMode & epTabCol) == epTabColDef)
r -> HtmlStack.State.pBuf = oBegin (r) ;
r -> Component.pCurrPos = NULL ;
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* /tr tag ... */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlEndrow (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
EPENTRY (HtmlEndrow) ;
if (r -> HtmlStack.State.nCmdType != cmdTablerow)
return rcEndtableWithoutTablerow ;
if (r -> Component.Config.bDebug & dbgTab)
lprintf (r -> pApp, "[%d]TAB: r -> nTabMode=%d nResult=%d nRow=%d Used=%d nCol=%d Used=%d nCnt=%d Used=%d \n",
r -> pThread -> nPid, r -> TableStack.State.nTabMode, r -> TableStack.State.nResult, r -> TableStack.State.nRow, r -> TableStack.State.nRowUsed, r -> TableStack.State.nCol, r -> TableStack.State.nColUsed, r -> TableStack.State.nCount, r -> TableStack.State.nCountUsed) ;
if ((r -> TableStack.State.nTabMode & epTabCol) == epTabColDef)
if (r -> TableStack.State.nResult || (!r -> TableStack.State.nColUsed && !r -> TableStack.State.nCountUsed && !r -> TableStack.State.nRowUsed))
oCommit (r, r -> HtmlStack.State.pBuf) ;
else
oRollback (r, r -> HtmlStack.State.pBuf), r -> TableStack.State.nCol-- ;
if (r -> TableStack.State.bRowHead)
{
if (r -> HtmlStack.pStack == NULL)
return rcTablerowOutsideOfTable ;
r -> HtmlStack.pStack -> pStart = r -> Component.pCurrPos ;
r -> HtmlStack.pStack -> nBlockNo = r -> Buf.nBlockNo ;
}
r -> TableStack.State.nCount++ ;
r -> TableStack.State.nCol++ ;
if (((r -> TableStack.State.nTabMode & epTabCol) == epTabColMax ||
(r -> TableStack.State.nResult && (r -> TableStack.State.nColUsed || r -> TableStack.State.nCountUsed)))
&& r -> TableStack.State.nCol < r -> TableStack.State.nMaxCol)
{
r -> Component.pCurrPos = r -> HtmlStack.State.pStart ;
r -> Buf.nBlockNo = r -> HtmlStack.State.nBlockNo ;
if ((r -> TableStack.State.nTabMode & epTabCol) == epTabColDef)
r -> HtmlStack.State.pBuf = oBegin (r) ;
}
else
{
r -> HtmlStack.State.pStart = NULL ;
if (r -> TableStack.State.bHead || r -> TableStack.State.nCol > 0)
{
r -> TableStack.State.nResult = 1 ;
}
}
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* table head tag ... */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlTableHead (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
EPENTRY (HtmlTableHead) ;
if (r -> TableStack.State.nCol == 0)
r -> TableStack.State.bHead = r -> TableStack.State.bRowHead = 1 ;
else
r -> TableStack.State.bRowHead = 0 ;
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* Split values in from %fdat */
/* */
/* ---------------------------------------------------------------------------- */
SV * SplitFdat (/*i/o*/ register req * r,
/*in*/ SV ** ppSVfdat,
/*out*/ SV ** ppSVerg,
/*in*/ char * pName,
/*in*/ STRLEN nlen)
{
STRLEN dlen ;
char * pData ;
char * s ;
char * p ;
if (ppSVerg && *ppSVerg && SvTYPE (*ppSVerg))
{
return *ppSVerg ;
}
pData = SvPV (*ppSVfdat, dlen) ;
s = pData ;
if ((p = strchr (s, r -> pConf -> cMultFieldSep)))
{ /* Multiple values -> put them into a hash */
HV * pHV = newHV () ;
int l ;
while (p)
{
hv_store (pHV, s, p - s, &sv_undef, 0) ;
s = p + 1 ;
p = strchr (s, r -> pConf -> cMultFieldSep) ;
}
l = dlen - (s - pData) ;
if (l > 0)
hv_store (pHV, s, l, &sv_undef, 0) ;
hv_store (r -> pThread -> pFormSplitHash, (char *)pName, nlen, (SV *)pHV, 0) ;
if (r -> Component.Config.bDebug & dbgInput)
lprintf (r -> pApp, "[%d]INPU: <mult values>\n", r -> pThread -> nPid) ;
return (SV *)pHV;
}
else
{
SvREFCNT_inc (*ppSVfdat) ;
hv_store (r -> pThread -> pFormSplitHash, (char *)pName, nlen, *ppSVfdat, 0) ;
if (r -> Component.Config.bDebug & dbgInput)
lprintf (r -> pApp, "[%d]INPU: value = %s\n", r -> pThread -> nPid, SvPV(*ppSVfdat, na)) ;
return *ppSVfdat ;
}
}
/* ---------------------------------------------------------------------------- */
/* */
/* select tag ... */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlSelect (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
const char * pName ;
int nlen ;
SV * * ppSV ;
EPENTRY (HtmlSelect) ;
pName = GetHtmlArg (sArg, "NAME", &nlen) ;
if (nlen == 0)
{
if (r -> Component.Config.bDebug & dbgInput)
lprintf (r -> pApp, "[%d]INPU: Select has no name\n", r -> pThread -> nPid) ;
}
else
{
r -> HtmlStack.State.sArg = _ep_strndup (r, pName, nlen) ;
ppSV = hv_fetch(r -> pThread -> pFormHash, (char *)pName, nlen, 0) ;
if (ppSV == NULL)
{
if (r -> Component.Config.bDebug & dbgInput)
lprintf (r -> pApp, "[%d]INPU: Select %s: no data available in form data\n", r -> pThread -> nPid, r -> HtmlStack.State.sArg) ;
}
else
{
SV * * ppSVerg = hv_fetch(r -> pThread -> pFormSplitHash, (char *)pName, nlen, 0) ;
r -> HtmlStack.State.pSV = SplitFdat (r, ppSV, ppSVerg, (char *)pName, nlen) ;
SvREFCNT_inc (r -> HtmlStack.State.pSV) ;
if (r -> Component.Config.bDebug & dbgInput)
lprintf (r -> pApp, "[%d]INPU: Select %s = %s\n", r -> pThread -> nPid, r -> HtmlStack.State.sArg, SvPV(r -> HtmlStack.State.pSV, na)) ;
}
}
return HtmlTable (r, sArg) ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* option tag ... */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlOption (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
const char * pVal ;
const char * pSelected ;
STRLEN vlen ;
int slen ;
char * pName ;
char * pData ;
STRLEN dlen ;
int bSel ;
SV * pSV ;
EPENTRY (HtmlOption) ;
pName = r -> HtmlStack.State.sArg?r -> HtmlStack.State.sArg:"" ;
if (r -> HtmlStack.State.pSV == NULL)
{
/*if (bDebug & dbgInput)
lprintf (r -> pApp, "[%d]INPU: <Select>/<Option> no data available\n", r -> pThread -> nPid) ; */
return ok ; /* no name or no data for select */
}
pVal = GetHtmlArg (sArg, "VALUE", &slen) ;
vlen = slen ; /* first use an int to avoid problems on 64Bit Systems! */
if (vlen == 0)
{
if (r -> Component.Config.bDebug & dbgInput)
lprintf (r -> pApp, "[%d]INPU: <Option> for Select %s has no value\n", r -> pThread -> nPid, pName) ;
return ok ; /* has no value */
}
pSV = newSVpv ((char *)pVal, vlen) ;
TransHtmlSV (r, pSV) ;
pVal = SvPV (pSV, vlen) ;
pSelected = GetHtmlArg (sArg, "SELECTED", &slen) ;
bSel = 0 ;
if (SvTYPE (r -> HtmlStack.State.pSV) == SVt_PVHV)
{ /* -> Hash -> check if key exists */
if (hv_exists ((HV *)r -> HtmlStack.State.pSV, (char *)pVal, vlen))
bSel = 1 ;
}
else
{
pData = SvPV (r -> HtmlStack.State.pSV, dlen) ;
if (dlen == vlen && strncmp (pVal, pData, dlen) == 0)
bSel = 1 ;
}
if (r -> Component.Config.bDebug & dbgInput)
lprintf (r -> pApp, "[%d]INPU: <Option> %s is now%s selected\n", r -> pThread -> nPid, pName, (bSel?"":" not")) ;
if (bSel)
{ /* -> selected */
if (hv_store (r -> pThread -> pInputHash, pName, strlen (pName), pSV, 0) == NULL)
{
strcpy (r -> errdat1, "InputHash in HtmlOption") ;
return rcHashError ;
}
if (pSelected)
return ok ;
else
{
oputs (r, r -> Buf.pCurrTag) ;
if (*sArg != '\0')
{
oputc (r, ' ') ;
oputs (r, sArg) ;
}
oputs (r, " selected>") ;
r -> Component.pCurrPos = NULL ; /* nothing more left of html tag */
return ok ;
}
}
else
{
SvREFCNT_dec (pSV) ;
if (pSelected == NULL)
return ok ;
else
{
oputs (r, r -> Buf.pCurrTag) ;
oputc (r, ' ') ;
owrite (r, sArg, pSelected - sArg) ;
oputs (r, pSelected + 8) ;
oputc (r, '>') ;
r -> Component.pCurrPos = NULL ; /* nothing more left of html tag */
return ok ;
}
}
}
/* ---------------------------------------------------------------------------- */
/* */
/* /select tag ... */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlEndselect (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
if (r -> Component.Config.bOptions & optAllFormData)
{
char * pName ;
int l ;
EPENTRY (HtmlEndselect) ;
pName = r -> HtmlStack.State.sArg?r -> HtmlStack.State.sArg:"" ;
l = strlen (pName) ;
if (!hv_exists (r -> pThread -> pInputHash, pName, l))
if (hv_store (r -> pThread -> pInputHash, pName, l, &sv_undef, 0) == NULL)
{
strcpy (r -> errdat1, "InputHash in HtmlEndselect") ;
return rcHashError ;
}
}
return HtmlEndtable (r, sArg) ;
}
/* ---------------------------------------------------------------------------- */
/* */
/* input tag ... */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlInput (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
const char * pName ;
const char * pVal ;
const char * pData ;
const char * pType ;
const char * pCheck ;
int nlen ;
int vlen ;
STRLEN dlen ;
int tlen ;
int clen ;
SV * pSV ;
SV ** ppSV ;
char sName [256] ;
int bCheck ;
int bEqual = 0 ;
EPENTRY (HtmlInput) ;
pName = GetHtmlArg (sArg, "NAME", &nlen) ;
if (nlen == 0)
{
if (r -> Component.Config.bDebug & dbgInput)
lprintf (r -> pApp, "[%d]INPU: has no name\n", r -> pThread -> nPid) ;
return ok ; /* no Name */
}
if (nlen >= sizeof (sName))
nlen = sizeof (sName) - 1 ;
strncpy (sName, pName, nlen) ;
sName [nlen] = '\0' ;
pType = GetHtmlArg (sArg, "TYPE", &tlen) ;
if (tlen > 0 && (strnicmp (pType, "RADIO", 5) == 0 || strnicmp (pType, "CHECKBOX", 8) == 0))
bCheck = 1 ;
else
bCheck = 0 ;
pVal = GetHtmlArg (sArg, "VALUE", &vlen) ;
/*if ((pVal && vlen != 0) && bCheck == 0) */
if (pVal && bCheck == 0)
{
pSV = newSVpv ((char *)pVal, vlen) ;
TransHtmlSV (r, pSV) ;
if (r -> Component.Config.bDebug & dbgInput)
lprintf (r -> pApp, "[%d]INPU: %s already has a value = %s\n", r -> pThread -> nPid, sName, SvPV (pSV, na)) ;
if (hv_store (r -> pThread -> pInputHash, sName, strlen (sName), pSV, 0) == NULL)
{
strcpy (r -> errdat1, "InputHash in HtmlInput") ;
return rcHashError ;
}
return ok ; /* has already a value */
}
ppSV = hv_fetch(r -> pThread -> pFormHash, (char *)pName, nlen, 0) ;
if (ppSV == NULL)
{
if (r -> Component.Config.bOptions & optUndefToEmptyValue)
{
pData = "" ;
dlen = 0 ;
}
else
{
if (r -> Component.Config.bDebug & dbgInput)
lprintf (r -> pApp, "[%d]INPU: %s: no data available in form data\n", r -> pThread -> nPid, sName) ;
if (vlen != 0)
{
pSV = newSVpv ((char *)pVal, vlen) ;
if (hv_store (r -> pThread -> pInputHash, sName, strlen (sName), pSV, 0) == NULL)
{
strcpy (r -> errdat1, "InputHash in HtmlInput") ;
return rcHashError ;
}
}
return ok ; /* no data available */
}
}
else
pData = SvPV (*ppSV, dlen) ;
if (bCheck)
{ /* check box */
bEqual = 0 ;
if (vlen > 0 && ppSV)
{
SV * pSV ;
SV * pSVVal ;
char * pTVal ;
STRLEN vtlen ;
SV * * ppSVerg = hv_fetch(r -> pThread -> pFormSplitHash, (char *)pName, nlen, 0) ;
pSV = SplitFdat (r, ppSV, ppSVerg, (char *)pName, nlen) ;
pSVVal = newSVpv ((char *)pVal, vlen) ;
TransHtmlSV (r, pSVVal) ;
pTVal = SvPV (pSVVal, vtlen) ;
if (SvTYPE (pSV) == SVt_PVHV)
{ /* -> Hash -> check if key exists */
if (hv_exists ((HV *)pSV, (char *)pTVal, vtlen))
bEqual = 1 ;
}
else
{
pData = SvPV (pSV, dlen) ;
if (dlen == vtlen && strncmp (pTVal, pData, dlen) == 0)
bEqual = 1 ;
}
SvREFCNT_dec (pSVVal) ;
}
pCheck = GetHtmlArg (sArg, "checked", &clen) ;
if (pCheck)
{
if (!bEqual)
{ /* Remove "checked" */
oputs (r, "<input ") ;
owrite (r, sArg, pCheck - sArg) ;
oputs (r, pCheck + 7) ; /* write rest of html tag */
oputc (r, '>') ;
r -> Component.pCurrPos = NULL ; /* nothing more left of html tag */
}
}
else
{
if (bEqual)
{ /* Insert "checked" */
oputs (r, "<input ") ;
oputs (r, sArg) ;
oputs (r, " checked>") ;
r -> Component.pCurrPos = NULL ; /* nothing more left of html tag */
}
}
}
else
{ /* text field */
if (pVal)
{
oputs (r, "<input ") ;
owrite (r, sArg, pVal - sArg) ;
oputs (r, " value=\"") ;
OutputToHtml (r, pData) ;
oputs (r, "\" ") ;
while (*pVal && !isspace(*pVal))
pVal++ ;
oputs (r, pVal) ; /* write rest of html tag */
oputc (r, '>') ;
r -> Component.pCurrPos = NULL ; /* nothing more left of html tag */
}
else
{
oputs (r, "<input ") ;
oputs (r, sArg) ;
oputs (r, " value=\"") ;
OutputToHtml (r, pData) ;
oputs (r, "\">") ;
r -> Component.pCurrPos = NULL ; /* nothing more left of html tag */
}
}
if (r -> Component.Config.bDebug & dbgInput)
{
lprintf (r -> pApp, "[%d]INPU: %s=%s %s\n", r -> pThread -> nPid, sName, pData, bCheck?(bEqual?"CHECKED":"NOT CHECKED"):"") ;
}
pSV = newSVpv ((char *)pData, dlen) ;
if (hv_store (r -> pThread -> pInputHash, sName, strlen (sName), pSV, 0) == NULL)
{
strcpy (r -> errdat1, "InputHash in HtmlInput") ;
return rcHashError ;
}
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* textarea tag ... */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlTextarea (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
EPENTRY (HtmlTextarea) ;
return ok ;
}
/* ---------------------------------------------------------------------------- */
/* /textarea tag ... */
/* */
/* ---------------------------------------------------------------------------- */
static int HtmlEndtextarea (/*i/o*/ register req * r,
/*in*/ const char * sArg)
{
const char * pName ;
const char * pVal ;
const char * pEnd ;
const char * pData ;
int nlen ;
int vlen ;
STRLEN dlen ;
SV * pSV ;
SV ** ppSV ;
char sName [256] ;
EPENTRY (HtmlEndtextarea) ;
pVal = r -> HtmlStack.State.pStart ;
r -> HtmlStack.State.pStart = NULL ;
if (r -> HtmlStack.State.nCmdType != cmdTextarea)
return rcEndtextareaWithoutTextarea ;
pName = GetHtmlArg (r -> HtmlStack.State.sArg, "NAME", &nlen) ;
if (nlen == 0)
{
if (r -> Component.Config.bDebug & dbgInput)
lprintf (r -> pApp, "[%d]TEXT: has no name\n", r -> pThread -> nPid) ;
return ok ; /* no Name */
}
if (nlen >= sizeof (sName))
nlen = sizeof (sName) - 1 ;
strncpy (sName, pName, nlen) ;
sName [nlen] = '\0' ;
pEnd = r -> Buf.pCurrTag - 1 ;
while (pVal <= pEnd && isspace (*pVal))
pVal++ ;
while (pVal <= pEnd && isspace (*pEnd))
pEnd-- ;
vlen = pEnd - pVal + 1 ;
if (vlen != 0)
{
pSV = newSVpv ((char *)pVal, vlen) ;
TransHtmlSV (r, pSV) ;
if (r -> Component.Config.bDebug & dbgInput)
lprintf (r -> pApp, "[%d]TEXT: %s already has a value = %s\n", r -> pThread -> nPid, sName, SvPV (pSV, na)) ;
if (hv_store (r -> pThread -> pInputHash, sName, strlen (sName), pSV, 0) == NULL)
{
strcpy (r -> errdat1, "InputHash in HtmlEndtextarea") ;
return rcHashError ;
}
return ok ; /* has already a value */
}
ppSV = hv_fetch(r -> pThread -> pFormHash, (char *)pName, nlen, 0) ;
if (ppSV == NULL)
{
if (r -> Component.Config.bDebug & dbgInput)
lprintf (r -> pApp, "[%d]TEXT: %s: no data available in form data\n", r -> pThread -> nPid, sName) ;
return ok ; /* no data available */
}
pData = SvPV (*ppSV, dlen) ;
if (pVal)
{
OutputToHtml (r, pData) ;
}
if (r -> Component.Config.bDebug & dbgInput)
{
lprintf (r -> pApp, "[%d]TEXT: %s=%s\n", r -> pThread -> nPid, sName, pData) ;
}
pSV = newSVpv ((char *)pData, dlen) ;
if (hv_store (r -> pThread -> pInputHash, sName, strlen (sName), pSV, 0) == NULL)
{
strcpy (r -> errdat1, "InputHash in HtmlEndtextarea") ;
return rcHashError ;
}
return ok ;
}