Sponsoring The Perl Toolchain Summit 2025: Help make this important event another success 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"
#include "ep_xs_typedefs.h"
#include "ep_xs_sv_convert.h"
/* ------------------------------------------------------------------------ */
/* */
/* Provider_New */
/* */
/*!
* \_en
* Creates a provider.
*
* @note This function should not be called directly, but from another
* ProviderXXX_New function
*
* @param r Embperl request record
* @param nSize Size of provider struct
* @param pItem CacheItem which holds the output of the provider
* @param pProviderClass Provider class record
* source Sourcetext provider
* @param pParam Parameter Hash
* @return error code
* \endif
*
* \_de
* Erzeugt einen neuen Provider.
*
* @note Diese Funktion sollte nicht direkt aufgerufen werden, sondern
* von einer anderen ProviderXXX_New Funktion aus
*
* @param r Embperl request record
* @param nSize Größer der provider struct
* @param pItem CacheItem welches die Ausgabe des Providers
* speichert
* @param pProviderClass Provider class record
* @param pParam Parameter Hash
* source Quellentext provider
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
int Provider_New (/*in*/ req * r,
/*in*/ size_t nSize,
/*in*/ tCacheItem * pItem,
/*in*/ tProviderClass * pProviderClass,
/*in*/ HV * pParam)
{
epTHX_
tProvider * pNew = (tProvider *)cache_malloc (r, nSize) ;
if (!pNew)
return rcOutOfMemory ;
memset (pNew, 0, nSize) ;
pNew -> pCache = pItem ;
pNew -> pProviderClass = pProviderClass ;
pNew -> sOutputType = pProviderClass -> sOutputType ;
pItem -> pProvider = (tProvider *)pNew ;
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* Provider_AddDependOne */
/* */
/*!
* \_en
* Adds another dependency provider to a new provider. If only a string
* is given for the dependend provider the fMatch functions of the
* provider classes are called until a provider class is found.
*
* @note This function should not be called directly, but from another
* ProviderXXX_New function
*
* @param r Embperl request record
* @param nSize Size of provider struct
* @param sSourceName Name of the element in pParam that holds the source
* @param pItem CacheItem which holds the output of the provider
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* @param pParam All Parameters
* @param nParamIndex If pParam is an AV, this parameter gives the index into the Array
* @return error code
* \endif
*
* \_de
* Fügt einen neuen Abhänigkeit für einen neuen Provider.
* Wird nur eine Zeichenkette als Abhänigkeit übergeben, werden der Reihe
* nach die fMatch Funktionen der Providerklassen aufgerufen, bis eine
* passende Klasse gefunden wurde.
*
* @note Diese Funktion sollte nicht direkt aufgerufen werden, sondern
* von einer anderen ProviderXXX_New Funktion aus
*
* @param r Embperl request record
* @param nSize Größer der provider struct
* @param sSourceName Name des Elements in pParam welches die Quelle enthält
* @param pItem CacheItem welches die Ausgabe des Providers
* speichert
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash dieses Providers
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
int Provider_AddDependOne (/*in*/ req * r,
/*in*/ tProvider * pProvider,
/*in*/ const char * sSourceName,
/*in*/ tCacheItem * pItem,
/*in*/ tProviderClass * pProviderClass,
/*in*/ HV * pProviderParam,
/*in*/ SV * pParam,
/*in*/ IV nParamIndex)
{
epTHX_
int rc ;
SV * pSourceParam ;
tCacheItem * pSubCache ;
pSourceParam = GetHashValueSV (r, pProviderParam, sSourceName) ;
if (pSourceParam)
{
if ((rc = Cache_New (r, pSourceParam, -1, 0, &pSubCache)) != ok)
{
strcpy (r -> errdat2, sSourceName) ;
return rc ;
}
}
else if (pParam)
{
if ((rc = Cache_New (r, pParam, nParamIndex, 0, &pSubCache)) != ok)
{
strcpy (r -> errdat2, sSourceName) ;
return rc ;
}
}
else
{
strncpy (r -> errdat1, sSourceName, sizeof (r -> errdat1) - 1) ;
strncpy (r -> errdat2, pItem -> sKey, sizeof (r -> errdat2) - 1) ;
return rcMissingParam ;
}
if ((rc = Cache_AddDependency (r, pItem, pSubCache)) != ok)
return rc ;
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* Provider_NewDependOne */
/* */
/*!
* \_en
* Creates a provider which depends on another provider. If only a string
* is given for the dependend provider the fMatch functions of the
* provider classes are called until a provider class is found.
*
* @note This function should not be called directly, but from another
* ProviderXXX_New function
*
* @param r Embperl request record
* @param nSize Size of provider struct
* @param sSourceName Name of the element in pParam that holds the source
* @param pItem CacheItem which holds the output of the provider
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* @param pParam All Parameters
* @param nParamIndex If pParam is a AV, this parameter gives the index into the Array
* @return error code
* \endif
*
* \_de
* Erzeugt einen neuen Provider der von einem anderem Provider abhängt.
* Wird nur eine Zeichenkette als Abhänigkeit übergeben, werden der Reihe
* nach die fMatch Funktionen der Providerklassen aufgerufen, bis eine
* passende Klasse gefunden wurde.
*
* @note Diese Funktion sollte nicht direkt aufgerufen werden, sondern
* von einer anderen ProviderXXX_New Funktion aus
*
* @param r Embperl request record
* @param nSize Größer der provider struct
* @param sSourceName Name des Elements in pParam welches die Quelle enthält
* @param pItem CacheItem welches die Ausgabe des Providers
* speichert
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash dieses Providers
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
int Provider_NewDependOne (/*in*/ req * r,
/*in*/ size_t nSize,
/*in*/ const char * sSourceName,
/*in*/ tCacheItem * pItem,
/*in*/ tProviderClass * pProviderClass,
/*in*/ HV * pProviderParam,
/*in*/ SV * pParam,
/*in*/ IV nParamIndex)
{
int rc ;
if ((rc = Provider_New (r, nSize, pItem, pProviderClass, pProviderParam)) != ok)
return rc ;
if ((rc = Provider_AddDependOne (r, pItem -> pProvider, sSourceName, pItem, pProviderClass, pProviderParam, pParam, nParamIndex)) != ok)
return rc ;
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/*! Provider that reads input from file */
/* */
typedef struct tProviderFile
{
tProvider Provider ;
const char * sFilename ; /**< Filename */
} tProviderFile ;
/* ------------------------------------------------------------------------ */
/* */
/* ProviderFile_New */
/* */
/*!
* \_en
* Creates a new file provider and fills it with data from the hash pParam
* The resulting provider is put into the cache structure
*
* @param r Embperl request record
* @param pItem CacheItem which holds the output of the provider
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* filename filename
* @param pParam All Parameters
* @param nParamIndex If pParam is an AV, this parameter gives the index into the Array
* @return error code
* \endif
*
* \_de
* Erzeugt einen neue Provider der daten aus Dateien ließt. Der ein Zeiger
* auf den resultierenden Provider wird in die Cachestrutr eingefügt
*
* @param r Embperl request record
* @param pItem CacheItem welches die Ausgabe des Providers
* speichert
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash dieses Providers
* filename Dateiname
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderFile_New (/*in*/ req * r,
/*in*/ tCacheItem * pItem,
/*in*/ tProviderClass * pProviderClass,
/*in*/ HV * pProviderParam,
/*in*/ SV * pParam,
/*in*/ IV nParamIndex)
{
epTHX_
int rc ;
tProviderFile * pNew ;
char * sFilename ;
if ((rc = Provider_New (r, sizeof(tProviderFile), pItem, pProviderClass, pProviderParam)) != ok)
return rc ;
pNew = (tProviderFile *)pItem -> pProvider ;
sFilename = GetHashValueStr (aTHX_ pProviderParam, "filename", r -> Component.Param.sInputfile) ;
pNew -> sFilename = embperl_PathSearch(r, NULL, sFilename, -1) ;
if (!pNew -> sFilename)
{
strncpy (r -> errdat1, sFilename, sizeof (r -> errdat1) - 1) ;
strncpy (r -> errdat2, embperl_PathStr(r, sFilename), sizeof (r -> errdat2) - 1) ;
return rcNotFound ;
}
pItem -> sExpiresFilename = strdup (pNew -> sFilename) ;
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderFile_AppendKey */
/* */
/*!
* \_en
* Append it's key to the keystring. If it depends on anything it must
* call Cache_AppendKey for any dependency.
* The file provider appends the filename
*
* @param r Embperl request record
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* filename filename
* @param pParam All Parameters
* @param nParamIndex If pParam is an AV, this parameter gives the index into the Array
* @param pKey Key to which string should be appended
* @return error code
* \endif
*
* \_de
* Hängt ein eigenen Schlüssel an den Schlüsselstring an. Wenn irgednwelche
* Abhänigkeiten bestehen, muß Cache_AppendKey für alle Abhänigkeiten aufgerufen
* werden.
* Der File Provider hängt den Dateinamen an.
*
* @param r Embperl request record
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash dieses Providers
* filename Dateiname
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @param pKey Schlüssel zu welchem hinzugefügt wird
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderFile_AppendKey (/*in*/ req * r,
/*in*/ tProviderClass * pProviderClass,
/*in*/ HV * pProviderParam,
/*in*/ SV * pParam,
/*in*/ IV nParamIndex,
/*i/o*/ SV * pKey)
{
epTHX_
const char * sFilename ;
const char * sAbsFilename ;
sFilename = GetHashValueStr (aTHX_ pProviderParam, "filename", r -> Component.Param.sInputfile) ;
sAbsFilename = embperl_PathSearch(r, r -> pPool, (char *)sFilename, -1) ;
if (!sAbsFilename)
{
strncpy (r -> errdat1, sFilename, sizeof (r -> errdat1) - 1) ;
strncpy (r -> errdat2, embperl_PathStr(r, sFilename), sizeof (r -> errdat2) - 1) ;
return rcNotFound ;
}
sv_catpvf (pKey, "*file:%s", sAbsFilename) ;
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderFile_GetContentSV */
/* */
/*!
* \_en
* Get the whole content from the provider.
* The file provider reads the whole file into memory
*
* @param r Embperl request record
* @param pProvider The provider record
* @param pData Returns the content
* @param bUseCache Set if the content should not recomputed
* @return error code
* \endif
*
* \_de
* Holt den gesamt Inhalt vom Provider.
* Der File Provider ließt die komplette Datei.
*
* @param r Embperl request record
* @param pProvider The provider record
* @param pData Liefert den Inhalt
* @param bUseCache Gesetzt wenn der Inhalt nicht neu berechnet werden soll
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderFile_GetContentSV (/*in*/ req * r,
/*in*/ tProvider * pProvider,
/*in*/ SV * * pData,
/*in*/ bool bUseCache)
{
epTHX_
size_t nSize = pProvider -> pCache -> FileStat.st_size ;
int rc = ok ;
r -> Component.sSourcefile = (char *)((tProviderFile *)pProvider) -> sFilename ;
embperl_SetCWDToFile (r, r -> Component.sSourcefile) ;
if (!bUseCache)
{
rc = ReadHTML(r, (char *)((tProviderFile *)pProvider) -> sFilename, &nSize, pData) ;
if (rc == ok)
{
SvREFCNT_inc (*pData) ;
r -> Component.pBuf = SvPVX (*pData) ;
r -> Component.pEndPos = r -> Component.pBuf + nSize ;
r -> Component.pCurrPos = r -> Component.pBuf ;
}
}
return rc ;
}
/* ------------------------------------------------------------------------ */
tProviderClass ProviderClassFile =
{
"text/*",
&ProviderFile_New,
&ProviderFile_AppendKey,
NULL,
&ProviderFile_GetContentSV,
NULL,
NULL,
NULL,
} ;
/* ------------------------------------------------------------------------ */
/* */
/*! Provider that reads input from memory */
/* */
typedef struct tProviderMem
{
tProvider Provider ;
SV * pSource ; /**< Source */
const char * sName ; /**< Name of memory provider */
time_t nLastModified ; /**< Last modified */
time_t nLastModifiedWhileGet ; /**< Last modified during last get */
} tProviderMem ;
/* ------------------------------------------------------------------------ */
/* */
/* ProviderMem_New */
/* */
/*!
* \_en
* Creates a new file provider and fills it with data from the hash pParam
* The resulting provider is put into the cache structure
*
* @param r Embperl request record
* @param pItem CacheItem which holds the output of the provider
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* name name (used to compare mtime)
* source source text
* mtime last modification time
* @param pParam All Parameters
* @param nParamIndex If pParam is an AV, this parameter gives the index into the Array
* @return error code
* \endif
*
* \_de
* Erzeugt einen neue Provider der daten aus Dateien ließt. Der ein Zeiger
* auf den resultierenden Provider wird in die Cachestrutr eingefügt
*
* @param r Embperl request record
* @param pItem CacheItem welches die Ausgabe des Providers
* speichert
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash dieses Providers
* name Name (wird benutzt um mtime zu vergelichen)
* source Quellentext
* mtime Zeitpunkt der letzten Änderung
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderMem_New (/*in*/ req * r,
/*in*/ tCacheItem * pItem,
/*in*/ tProviderClass * pProviderClass,
/*in*/ HV * pProviderParam,
/*in*/ SV * pParam,
/*in*/ IV nParamIndex)
{
epTHX_
int rc ;
tProviderMem * pNew ;
if ((rc = Provider_New (r, sizeof(tProviderMem), pItem, pProviderClass, pProviderParam)) != ok)
return rc ;
pNew = (tProviderMem *)pItem -> pProvider ;
pNew -> sName = GetHashValueStrDupA (aTHX_ pProviderParam, "name", r -> Component.Param.sInputfile) ;
/*
pNew -> nLastModified = GetHashValueUInt (pParam, "mtime", 0) ;
pSrc = GetHashValueSV (r, pParam, "source") ;
if (!pSrc)
pNew -> pSource = NULL ;
else if (SvROK(pSrc))
pNew -> pSource = SvREFCNT_inc (SvRV(pSrc)) ;
else
pNew -> pSource = SvREFCNT_inc (pSrc) ;
*/
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderMem_AppendKey */
/* */
/*!
* \_en
* Append it's key to the keystring. If it depends on anything it must
* call Cache_AppendKey for any dependency.
* The file provider appends the filename
*
* @param r Embperl request record
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* name name (used to compare mtime)
* source source text
* mtime last modification time
* @param pParam All Parameters
* @param nParamIndex If pParam is an AV, this parameter gives the index into the Array
* @param pKey Key to which string should be appended
* @return error code
* \endif
*
* \_de
* Hängt ein eigenen Schlüssel an den Schlüsselstring an. Wenn irgednwelche
* Abhänigkeiten bestehen, muß Cache_AppendKey für alle Abhänigkeiten aufgerufen
* werden.
* Der File Provider hängt den Dateinamen an.
*
* @param r Embperl request record
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash dieses Providers
* name Name (wird benutzt um mtime zu vergelichen)
* source Quellentext
* mtime Zeitpunkt der letzten Änderung
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @param pKey Schlüssel zu welchem hinzugefügt wird
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderMem_AppendKey (/*in*/ req * r,
/*in*/ tProviderClass * pProviderClass,
/*in*/ HV * pProviderParam,
/*in*/ SV * pParam,
/*in*/ IV nParamIndex,
/*i/o*/ SV * pKey)
{
epTHX_
const char * sName = GetHashValueStr (aTHX_ pProviderParam, "name", r -> Component.Param.sInputfile) ;
sv_catpvf (pKey, "*memory:%s", sName) ;
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderMem_UpdateParam */
/* */
/*!
* \_en
* Update the parameter of the provider
*
* @param r Embperl request record
* @param pProvider Provider record
* @param pParam Parameter Hash
* name name
* @param pKey Key to which string should be appended
* @return error code
* \endif
*
* \_de
* Aktualisiert die Parameter des Providers
*
* @param r Embperl request record
* @param pProvider Provider record
* @param pParam Parameter Hash
* name name
* @param pKey Schlüssel zu welchem hinzugefügt wird
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderMem_UpdateParam(/*in*/ req * r,
/*in*/ tProvider * pProvider,
/*in*/ HV * pParam)
{
epTHX_
SV * pSrc ;
if (((tProviderMem *)pProvider) -> pSource)
SvREFCNT_dec (((tProviderMem *)pProvider) -> pSource) ;
((tProviderMem *)pProvider) -> nLastModified = GetHashValueUInt (r, pParam, "mtime", r -> Component.Param.nMtime) ;
pSrc = GetHashValueSV (r, pParam, "source") ;
if (!pSrc)
((tProviderMem *)pProvider) -> pSource = SvROK(r -> Component.Param.pInput)?SvREFCNT_inc (SvRV(r -> Component.Param.pInput)):NULL ;
else if (SvROK(pSrc))
((tProviderMem *)pProvider) -> pSource = SvREFCNT_inc (SvRV(pSrc)) ;
else
((tProviderMem *)pProvider) -> pSource = SvREFCNT_inc (pSrc) ;
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderMem_GetContentSV */
/* */
/*!
* \_en
* Get the whole content from the provider.
* The file provider reads the whole file into memory
*
* @param r Embperl request record
* @param pProvider The provider record
* @param pData Returns the content
* @param bUseCache Set if the content should not recomputed
* @return error code
* \endif
*
* \_de
* Holt den gesamt Inhalt vom Provider.
* Der File Provider ließt die komplette Datei.
*
* @param r Embperl request record
* @param pProvider The provider record
* @param pData Liefert den Inhalt
* @param bUseCache Gesetzt wenn der Inhalt nicht neu berechnet werden soll
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderMem_GetContentSV (/*in*/ req * r,
/*in*/ tProvider * pProvider,
/*in*/ SV * * pData,
/*in*/ bool bUseCache)
{
epTHX_
r -> Component.sSourcefile = ep_pstrcat(r -> pPool, "MEM:", (char *)((tProviderMem *)pProvider) -> sName, NULL) ;
if (!bUseCache)
{
((tProviderMem *)pProvider) -> nLastModifiedWhileGet = ((tProviderMem *)pProvider) -> nLastModified ;
if ((*pData = SvREFCNT_inc(((tProviderMem *)pProvider) -> pSource)))
{
SvREFCNT_inc (*pData) ;
if (SvPOK(*pData))
{
r -> Component.pBuf = SvPVX (*pData) ;
r -> Component.pEndPos = r -> Component.pBuf + SvCUR(*pData) ;
r -> Component.pCurrPos = r -> Component.pBuf ;
}
else
{
r -> Component.pBuf = "" ;
r -> Component.pEndPos = r -> Component.pBuf ;
r -> Component.pCurrPos = r -> Component.pBuf ;
}
}
}
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderMem_FreeContent */
/* */
/*!
* \_en
* Free the cached data
*
* @param r Embperl request record
* @param pProvider The provider record
* @return error code
* \endif
*
* \_de
* Gibt die gecachten Daten frei
*
* @param r Embperl request record
* @param pProvider The provider record
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
int ProviderMem_FreeContent(/*in*/ req * r,
/*in*/ tCacheItem * pItem)
{
epTHX_
tProviderMem * pProvider = (tProviderMem *)(pItem -> pProvider) ;
if (pItem -> pSVData && pProvider -> pSource)
{
SvREFCNT_dec (pProvider -> pSource) ;
pProvider -> pSource = NULL ;
}
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderMem_IsExpired */
/* */
/*!
* \_en
* Check if content of provider is expired
*
* @param r Embperl request record
* @param pProvider Provider
* @return TRUE if expired
* \endif
*
* \_de
* Prüft ob der Inhalt des Providers noch gültig ist.
*
* @param r Embperl request record
* @param pProvider Provider
* @return WAHR wenn abgelaufen
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderMem_IsExpired (/*in*/ req * r,
/*in*/ tProvider * pProvider)
{
return ((tProviderMem *)pProvider) -> nLastModified == 0 || ((tProviderMem *)pProvider) -> nLastModified != ((tProviderMem *)pProvider) -> nLastModifiedWhileGet ;
}
/* ------------------------------------------------------------------------ */
tProviderClass ProviderClassMem =
{
"text/*",
&ProviderMem_New,
&ProviderMem_AppendKey,
&ProviderMem_UpdateParam,
&ProviderMem_GetContentSV,
NULL,
NULL,
&ProviderMem_FreeContent,
&ProviderMem_IsExpired,
} ;
/* ------------------------------------------------------------------------ */
/* */
/*! Provider for Embperl parser */
/* */
typedef struct tProviderEpParse
{
tProvider Provider ;
tTokenTable * pTokenTable ;
} tProviderEpParse ;
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpParse_New */
/* */
/*!
* \_en
* Creates a new Embperl parser provider and fills it with data from the
* hash pParam. The resulting provider is put into the cache structure
*
* @param r Embperl request record
* @param pItem CacheItem which holds the output of the provider
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* @param pParam All Parameters
* @param nParamIndex If pParam is an AV, this parameter gives the index into the Array
* @return error code
* \endif
*
* \_de
* Erzeugt einen neue Provider für den Embperl Parser. Der ein Zeiger
* auf den resultierenden Provider wird in die Cachestrutr eingefügt
*
* @param r Embperl request record
* @param pItem CacheItem welches die Ausgabe des Providers
* speichert
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash dieses Providers
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderEpParse_New (/*in*/ req * r,
/*in*/ tCacheItem * pItem,
/*in*/ tProviderClass * pProviderClass,
/*in*/ HV * pProviderParam,
/*in*/ SV * pParam,
/*in*/ IV nParamIndex)
{
epTHX_
dSP ;
int rc ;
int num ;
SV * pSyntaxSV ;
SV * pSyntaxRV = NULL ;
SV * pSyntaxPV ;
tTokenTable * pSyntax ;
const char * sSyntax = GetHashValueStr (aTHX_ pProviderParam, "syntax", r -> Component.Config.sSyntax) ;
if ((rc = Provider_NewDependOne (r, sizeof(tProviderEpParse), "source", pItem, pProviderClass, pProviderParam, pParam, nParamIndex)) != ok)
return rc ;
pSyntaxPV = sv_2mortal(newSVpv ((char *)sSyntax, 0)) ;
SPAGAIN ;
PUSHMARK(sp);
XPUSHs(pSyntaxPV);
PUTBACK;
num = perl_call_pv ("Embperl::Syntax::GetSyntax", G_SCALAR /*| G_EVAL*/) ;
tainted = 0 ;
SPAGAIN;
if (num == 1)
pSyntaxRV = POPs ;
PUTBACK;
if (num != 1 || !SvROK (pSyntaxRV) || !(pSyntaxSV = SvRV(pSyntaxRV)) || SvTYPE((SV *)pSyntaxSV) != SVt_PVHV)
{
strncpy (r -> errdat1, sSyntax, sizeof (r -> errdat1) - 1) ;
return rcUnknownSyntax ;
}
pSyntax = epxs_sv2_Embperl__Syntax(pSyntaxRV) ;
((tProviderEpParse *)pItem -> pProvider) -> pTokenTable = pSyntax ;
pItem -> bCache = FALSE ; /* do not cache, because it's cached by the compiler */
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpParse_AppendKey */
/* */
/*!
* \_en
* Append it's key to the keystring. If it depends on anything it must
* call Cache_AppendKey for any dependency.
*
* @param r Embperl request record
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* syntax Syntax
* @param pParam All Parameters
* @param nParamIndex If pParam is an AV, this parameter gives the index into the Array
* @param pKey Key to which string should be appended
* @return error code
* \endif
*
* \_de
* Hängt ein eigenen Schlüssel an den Schlüsselstring an. Wenn irgednwelche
* Abhänigkeiten bestehen, muß Cache_AppendKey für alle Abhänigkeiten aufgerufen
* werden.
*
* @param r Embperl request record
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash dieses Providers
* syntax Syntax
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @param pKey Schlüssel zu welchem hinzugefügt wird
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderEpParse_AppendKey (/*in*/ req * r,
/*in*/ tProviderClass * pProviderClass,
/*in*/ HV * pProviderParam,
/*in*/ SV * pParam,
/*in*/ IV nParamIndex,
/*i/o*/ SV * pKey)
{
epTHX_
int rc ;
const char * sSyntax = GetHashValueStr (aTHX_ pProviderParam, "syntax", r -> Component.Config.sSyntax) ;
if ((rc = Cache_AppendKey (r, pProviderParam, "source", pParam, nParamIndex, pKey)) != ok)
return rc;
sv_catpvf (pKey, "*epparse:%s", sSyntax) ;
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpParse_GetContentIndex */
/* */
/*!
* \_en
* Get the whole content from the provider.
* The Embperl parser provider parsers the source and generates a DomTree
*
* @param r Embperl request record
* @param pProvider The provider record
* @param pData Returns the content
* @param bUseCache Set if the content should not recomputed
* @return error code
* \endif
*
* \_de
* Holt den gesamt Inhalt vom Provider.
* Der Embperl Parser Provider parsest die Quelle und erzeugt einen DomTree
*
* @param r Embperl request record
* @param pProvider The provider record
* @param pData Liefert den Inhalt
* @param bUseCache Gesetzt wenn der Inhalt nicht neu berechnet werden soll
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderEpParse_GetContentIndex (/*in*/ req * r,
/*in*/ tProvider * pProvider,
/*in*/ tIndex * pData,
/*in*/ bool bUseCache)
{
epTHX_
int rc ;
char * p ;
STRLEN len ;
SV * pSource ;
tCacheItem * pFileCache = Cache_GetDependency(r, pProvider -> pCache, 0) ;
if ((rc = Cache_GetContentSV (r, pFileCache, &pSource, bUseCache)) != ok)
return rc ;
r -> Component.pTokenTable = ((tProviderEpParse *)pProvider) -> pTokenTable ;
if (!bUseCache)
{
p = SvPV (pSource, len) ;
if ((rc = embperl_Parse (r, p, len, pData)) != ok)
return rc ;
}
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpParse_FreeContent */
/* */
/*!
* \_en
* Free the cached data
*
* @param r Embperl request record
* @param pProvider The provider record
* @return error code
* \endif
*
* \_de
* Gibt die gecachten Daten frei
*
* @param r Embperl request record
* @param pProvider The provider record
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
int ProviderEpParse_FreeContent(/*in*/ req * r,
/*in*/ tCacheItem * pItem)
{
/*
Do not delete, because it's same dom tree as compiler
if (pItem -> xData)
return DomTree_delete (r -> pApp, DomTree_self(pItem -> xData)) ;
*/
return ok ;
}
/* ------------------------------------------------------------------------ */
tProviderClass ProviderClassEpParse =
{
"X-Embperl/DomTree",
&ProviderEpParse_New,
&ProviderEpParse_AppendKey,
NULL,
NULL,
NULL,
&ProviderEpParse_GetContentIndex,
&ProviderEpParse_FreeContent,
NULL,
} ;
/* ------------------------------------------------------------------------ */
/* */
/*! Provider for Embperl compiler */
/* */
typedef struct tProviderEpCompile
{
tProvider Provider ;
SV * pSVData ;
char * sPackage ;
char * sMainSub ;
} tProviderEpCompile ;
static int nPackageCount = 1 ;
static perl_mutex PackageCountMutex ;
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpCompile_New */
/* */
/*!
* \_en
* Creates a new Embperl compile provider and fills it with data from the
* hash pParam. The resulting provider is put into the cache structure
*
* @param r Embperl request record
* @param pItem CacheItem which holds the output of the provider
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* package Packagename
* @param pParam All Parameters
* @param nParamIndex If pParam is an AV, this parameter gives the index into the Array
* @return error code
* \endif
*
* \_de
* Erzeugt einen neue Provider für den Embperl Compiler. Der ein Zeiger
* auf den resultierenden Provider wird in die Cachestrutr eingefügt
*
* @param r Embperl request record
* @param pItem CacheItem welches die Ausgabe des Providers
* speichert
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash dieses Providers
* package Packagename
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderEpCompile_New (/*in*/ req * r,
/*in*/ tCacheItem * pItem,
/*in*/ tProviderClass * pProviderClass,
/*in*/ HV * pProviderParam,
/*in*/ SV * pParam,
/*in*/ IV nParamIndex)
{
epTHX_
int rc ;
char * sPackage ;
char * sMainSub ;
if ((rc = Provider_NewDependOne (r, sizeof(tProviderEpCompile), "source", pItem, pProviderClass, pProviderParam, pParam, nParamIndex)) != ok)
return rc ;
/*if (r -> Config.bDebug)
lprintf (r -> pApp, "[%d]ep_acquire_mutex(PackageCountMutex)\n", r -> pThread -> nPid) ; */
if ((sPackage = GetHashValueStrDupA (aTHX_ pProviderParam, "package", r -> Component.Config.sPackage)))
{
int n ;
ep_acquire_mutex(PackageCountMutex) ;
n = nPackageCount++ ;
ep_release_mutex(PackageCountMutex) ;
((tProviderEpCompile *)(pItem -> pProvider)) -> sPackage = sPackage ;
sMainSub = ((tProviderEpCompile *)(pItem -> pProvider)) -> sMainSub = malloc (40) ;
sprintf (sMainSub, "_ep_main%d", n) ;
}
else
{
int n ;
ep_acquire_mutex(PackageCountMutex) ;
n = nPackageCount++ ;
ep_release_mutex(PackageCountMutex) ;
sPackage = ((tProviderEpCompile *)(pItem -> pProvider)) -> sPackage = malloc (sizeof (EMBPERL_PACKAGE_STR) + 32) ;
sprintf (sPackage, EMBPERL_PACKAGE_STR"::__%d", n) ;
sMainSub = ((tProviderEpCompile *)(pItem -> pProvider)) -> sMainSub = malloc (40) ;
sprintf (sMainSub, "_ep_main%d", n) ;
}
/*if (r -> Config.bDebug)
lprintf (r -> pApp, "[%d]ep_release_mutex(PackageCountMutex)\n", r -> pThread -> nPid) ; */
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpCompile_AppendKey */
/* */
/*!
* \_en
* Append it's key to the keystring. If it depends on anything it must
* call Cache_AppendKey for any dependency.
*
* @param r Embperl request record
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* package Packagename
* @param pParam All Parameters
* @param nParamIndex If pParam is an AV, this parameter gives the index into the Array
* @param pKey Key to which string should be appended
* @return error code
* \endif
*
* \_de
* Hängt ein eigenen Schlüssel an den Schlüsselstring an. Wenn irgednwelche
* Abhänigkeiten bestehen, muß Cache_AppendKey für alle Abhänigkeiten aufgerufen
* werden.
*
* @param r Embperl request record
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash dieses Providers
* package Packagename
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @param pKey Schlüssel zu welchem hinzugefügt wird
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderEpCompile_AppendKey (/*in*/ req * r,
/*in*/ tProviderClass * pProviderClass,
/*in*/ HV * pProviderParam,
/*in*/ SV * pParam,
/*in*/ IV nParamIndex,
/*i/o*/ SV * pKey)
{
epTHX_
int rc ;
if ((rc = Cache_AppendKey (r, pProviderParam, "source", pParam, nParamIndex, pKey)) != ok)
return rc;
sv_catpvf (pKey, "*epcompile:%s", GetHashValueStr (aTHX_ pProviderParam, "package", r -> Component.Config.sPackage?r -> Component.Config.sPackage:"")) ;
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpCompile_GetContentIndex */
/* */
/*!
* \_en
* Get the whole content from the provider.
* The Embperl compile provider compiles the source DomTRee and generates
* a Perl program and a compiled DomTRee
*
* @param r Embperl request record
* @param pProvider The provider record
* @param pData Returns the content
* @param bUseCache Set if the content should not recomputed
* @return error code
* \endif
*
* \_de
* Holt den gesamt Inhalt vom Provider.
* Der Embperl Compile Provider überstzes den Quellen DOmTree und erzeugt
* ein Perlprogramm und einen übersetzten DomTree
*
* @param r Embperl request record
* @param pProvider The provider record
* @param pData Liefert den Inhalt
* @param bUseCache Gesetzt wenn der Inhalt nicht neu berechnet werden soll
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderEpCompile_GetContentIndex (/*in*/ req * r,
/*in*/ tProvider * pProvider,
/*in*/ tIndex * pData,
/*in*/ bool bUseCache)
{
epTHX_
int rc ;
tIndex xSrcDomTree ;
tCacheItem * pSrcCache ;
SV * pProg = NULL ;
pSrcCache = Cache_GetDependency(r, pProvider -> pCache, 0) ;
if ((rc = Cache_GetContentIndex (r, pSrcCache, &xSrcDomTree, bUseCache)) != ok)
return rc ;
r -> Component.sCurrPackage = ((tProviderEpCompile *)(pProvider)) -> sPackage ;
r -> Component.sEvalPackage = ((tProviderEpCompile *)(pProvider)) -> sPackage ;
r -> Component.nEvalPackage = strlen (((tProviderEpCompile *)(pProvider)) -> sPackage) ;
r -> Component.sMainSub = ((tProviderEpCompile *)(pProvider)) -> sMainSub ;
if (!bUseCache)
{
if ((rc = embperl_Compile (r, xSrcDomTree, pData, &pProg )) != ok)
{
((tProviderEpCompile *)pProvider) -> pSVData = NULL ;
if (pProg)
SvREFCNT_dec (pProg) ;
Cache_FreeContent (r, pSrcCache) ; /* make sure we don't leave an invalid dom tree */
return rc ;
}
((tProviderEpCompile *)pProvider) -> pSVData = pProg ;
}
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpCompile_GetContentIndex */
/* */
/*!
* \_en
* Get the whole content from the provider.
* The Embperl compile provider compiles the source DomTRee and generates
* a Perl program and a compiled DomTRee
*
* @param r Embperl request record
* @param pProvider The provider record
* @param pData Returns the content
* @param bUseCache Set if the content should not recomputed
* @return error code
* \endif
*
* \_de
* Holt den gesamt Inhalt vom Provider.
* Der Embperl Compile Provider überstzes den Quellen DOmTree und erzeugt
* ein Perlprogramm und einen übersetzten DomTree
*
* @param r Embperl request record
* @param pProvider The provider record
* @param pData Liefert den Inhalt
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderEpCompile_GetContentSV (/*in*/ req * r,
/*in*/ tProvider * pProvider,
/*in*/ SV * * pData,
/*in*/ bool bUseCache)
{
epTHX_
if (!bUseCache)
*pData = SvREFCNT_inc (((tProviderEpCompile *)pProvider) -> pSVData) ;
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpCompile_FreeContent */
/* */
/*!
* \_en
* Free the cached data
*
* @param r Embperl request record
* @param pProvider The provider record
* @return error code
* \endif
*
* \_de
* Gibt die gecachten Daten frei
*
* @param r Embperl request record
* @param pProvider The provider record
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
int ProviderEpCompile_FreeContent(/*in*/ req * r,
/*in*/ tCacheItem * pItem)
{
epTHX_
if (pItem -> xData)
return DomTree_delete (r -> pApp, DomTree_self(pItem -> xData)) ;
/*
if (((tProviderEpCompile *)(pItem -> pProvider)) -> sPackage)
free (((tProviderEpCompile *)(pItem -> pProvider)) -> sPackage) ;
*/
return ok ;
}
/* ------------------------------------------------------------------------ */
tProviderClass ProviderClassEpCompile =
{
"X-Embperl/DomTree",
&ProviderEpCompile_New,
&ProviderEpCompile_AppendKey,
NULL,
&ProviderEpCompile_GetContentSV,
NULL,
&ProviderEpCompile_GetContentIndex,
&ProviderEpCompile_FreeContent,
NULL,
} ;
/* ------------------------------------------------------------------------ */
/* */
/*! Provider for Embperl Executer */
/* */
typedef struct tProviderEpRun
{
tProvider Provider ;
char * sPackage ;
} tProviderEpRun ;
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpRun_New */
/* */
/*!
* \_en
* Creates a new Embperl run provider and fills it with data from the
* hash pParam. The resulting provider is put into the cache structure
*
* @param r Embperl request record
* @param pItem CacheItem which holds the output of the provider
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* @param pParam All Parameters
* @param nParamIndex If pParam is an AV, this parameter gives the index into the Array
* @return error code
* \endif
*
* \_de
* Erzeugt einen neue Provider für den Embperl Executer. Der ein Zeiger
* auf den resultierenden Provider wird in die Cachestrutr eingefügt
*
* @param r Embperl request record
* @param pItem CacheItem welches die Ausgabe des Providers
* speichert
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash dieses Providers
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderEpRun_New (/*in*/ req * r,
/*in*/ tCacheItem * pItem,
/*in*/ tProviderClass * pProviderClass,
/*in*/ HV * pProviderParam,
/*in*/ SV * pParam,
/*in*/ IV nParamIndex)
{
int rc ;
if ((rc = Provider_NewDependOne (r, sizeof(tProviderEpRun), "source", pItem, pProviderClass, pProviderParam, pParam, nParamIndex)) != ok)
return rc ;
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpRun_AppendKey */
/* */
/*!
* \_en
* Append it's key to the keystring. If it depends on anything it must
* call Cache_AppendKey for any dependency.
*
* @param r Embperl request record
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* cache_key
* cache_key_options
* cache_key_func
* @param pParam All Parameters
* @param nParamIndex If pParam is an AV, this parameter gives the index into the Array
* @param pKey Key to which string should be appended
* @return error code
* \endif
*
* \_de
* Hängt ein eigenen Schlüssel an den Schlüsselstring an. Wenn irgednwelche
* Abhänigkeiten bestehen, muß Cache_AppendKey für alle Abhänigkeiten aufgerufen
* werden.
*
* @param r Embperl request record
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash dieses Providers
* cache_key
* cache_key_options
* cache_key_func
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @param pKey Schlüssel zu welchem hinzugefügt wird
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderEpRun_AppendKey (/*in*/ req * r,
/*in*/ tProviderClass * pProviderClass,
/*in*/ HV * pProviderParam,
/*in*/ SV * pParam,
/*in*/ IV nParamIndex,
/*i/o*/ SV * pKey)
{
epTHX_
int rc ;
const char * sKey = GetHashValueStr (aTHX_ pProviderParam, "cache_key", r -> Component.Config.sCacheKey) ;
int bKeyOptions = GetHashValueInt (aTHX_ pProviderParam, "cache_key_options", r -> Component.Config.bCacheKeyOptions) ;
CV * pKeyCV ;
if ((rc = Cache_AppendKey (r, pProviderParam, "source", pParam, nParamIndex, pKey)) != ok)
return rc;
sv_catpv (pKey, "*eprun:") ;
if ((rc = GetHashValueCREF (r, pProviderParam, "cache_key_func", &pKeyCV)) != ok)
return rc ;
if (!pKeyCV)
pKeyCV = r -> Component.Config.pCacheKeyFunc ;
if (pKeyCV)
{
SV * pRet ;
if ((rc = CallCV (r, "CacheKey", pKeyCV, 0, &pRet)) != ok)
return rc ;
if (pRet && SvOK(pRet))
sv_catsv (pKey, pRet) ;
}
if ((bKeyOptions & ckoptPathInfo) && r -> Param.sPathInfo)
sv_catpv (pKey, r -> Param.sPathInfo) ;
if ((bKeyOptions & ckoptQueryInfo) && r -> Param.sQueryInfo)
sv_catpv (pKey, r -> Param.sQueryInfo) ;
if (sKey)
sv_catpv (pKey, sKey) ;
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* embperl_PreExecute */
/* */
/* Looks for vars/subs inside compiled document */
/* */
/* ------------------------------------------------------------------------ */
static int embperl_PreExecute (/*in*/ tReq * r,
/*in*/ tCacheItem * pCache,
/*in*/ char * sPackage)
{
epTHX_
STRLEN l ;
SV * pSV ;
CV * pCV ;
SV * pSVVar ;
pSV = newSVpvf("%s::EXPIRES", sPackage) ;
newSVpvf2(pSV) ;
pCV = perl_get_cv (SvPV(pSV, l), 0) ;
if (pCV)
{
SvREFCNT_dec (pCache -> pExpiresCV) ;
pCache -> pExpiresCV = pCV ;
SvREFCNT_inc (pCV) ;
}
SvREFCNT_dec(pSV);
pSV = newSVpvf("%s::EXPIRES", sPackage) ;
newSVpvf2(pSV) ;
pSVVar = perl_get_sv (SvPV(pSV, l), 0) ;
if (pSVVar)
{
pCache -> nExpiresInTime = SvUV (pSVVar) ;
}
SvREFCNT_dec(pSV);
/*
pSV = newSVpvf("%s::CACHE_KEY", r -> Component.sEvalPackage) ;
newSVpvf2(pSV) ;
pCV = perl_get_cv (SvPV(pSV, l), 0) ;
if (pCV)
{
SvREFCNT_dec (pProcessor -> pCacheKeyCV) ;
pProcessor -> pCacheKeyCV = pCV ;
SvREFCNT_inc (pCV) ;
}
SvREFCNT_dec(pSV);
pSV = newSVpvf("%s::CACHE_KEY", r -> Component.sEvalPackage) ;
newSVpvf2(pSV) ;
pSVVar = perl_get_sv (SvPV(pSV, l), 0) ;
if (pSVVar)
{
pProcessor -> sCacheKey = SvPV (pSVVar, l) ;
}
SvREFCNT_dec(pSV);
pSV = newSVpvf("%s::CACHE_KEY_OPTIONS", r -> Component.sEvalPackage) ;
newSVpvf2(pSV) ;
pSVVar = perl_get_sv (SvPV(pSV, l), 0) ;
if (pSVVar)
{
pProcessor -> bCacheKeyOptions = SvIV (pSVVar) ;
}
SvREFCNT_dec(pSV);
*/
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpRun_IsExpired */
/* */
/*!
* \_en
* Check if content of provider is expired
*
* @param r Embperl request record
* @param pProvider Provider
* @return TRUE if expired
* \endif
*
* \_de
* Prüft ob der Inhalt des Providers noch gültig ist.
*
* @param r Embperl request record
* @param pProvider Provider
* @return WAHR wenn abgelaufen
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderEpRun_IsExpired (/*in*/ req * r,
/*in*/ tProvider * pProvider)
{
int rc ;
bool bCache = pProvider -> pCache -> bCache ;
if (!((tProviderEpRun *)(pProvider)) -> sPackage)
return FALSE ;
/* update cache parameters */
if ((rc = embperl_PreExecute (r, pProvider -> pCache, ((tProviderEpRun *)(pProvider)) -> sPackage)) != ok)
{
LogError (r, rc) ;
}
if (pProvider -> pCache -> nExpiresInTime || pProvider -> pCache -> pExpiresCV)
pProvider -> pCache -> bCache = 1 ;
else
{
pProvider -> pCache -> bCache = 0 ;
if (bCache)
Cache_FreeContent (r, pProvider -> pCache) ;
return TRUE ;
}
return FALSE ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpRun_UpdateParam */
/* */
/*!
* \_en
* Update the parameter of the provider
*
* @param r Embperl request record
* @param pProvider Provider record
* @param pParam Parameter Hash
* name name
* @param pKey Key to which string should be appended
* @return error code
* \endif
*
* \_de
* Aktualisiert die Parameter des Providers
*
* @param r Embperl request record
* @param pProvider Provider record
* @param pParam Parameter Hash
* name name
* @param pKey Schlüssel zu welchem hinzugefügt wird
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderEpRun_UpdateParam(/*in*/ req * r,
/*in*/ tProvider * pProvider,
/*in*/ HV * pParam)
{
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpRun_GetContentIndex */
/* */
/*!
* \_en
* Get the whole content from the provider.
* The Embperl Run provider executes the compiled DomTree & Perl program
*
* @param r Embperl request record
* @param pProvider The provider record
* @param pData Returns the content
* @param bUseCache Set if the content should not recomputed
* @return error code
* \endif
*
* \_de
* Holt den gesamt Inhalt vom Provider.
* Der Embperl Run Provider führt den übersetzen DomTree und das Perlprogramm aus
*
* @param r Embperl request record
* @param pProvider The provider record
* @param pData Liefert den Inhalt
* @param bUseCache Gesetzt wenn der Inhalt nicht neu berechnet werden soll
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderEpRun_GetContentIndex (/*in*/ req * r,
/*in*/ tProvider * pProvider,
/*in*/ tIndex * pData,
/*in*/ bool bUseCache)
{
int rc ;
tIndex xSrcDomTree ;
CV * pCV ;
tCacheItem * pSrcCache = Cache_GetDependency(r, pProvider -> pCache, 0) ;
if ((rc = Cache_GetContentSvIndex (r, pSrcCache, (SV **)&pCV, &xSrcDomTree, bUseCache)) != ok)
return rc ;
if (!bUseCache || !*pData || !pProvider -> pCache -> bCache)
{
if ((rc = embperl_Execute (r, xSrcDomTree, pCV, pData)) != ok)
return rc ;
((tProviderEpRun *)(pProvider)) -> sPackage = ((tProviderEpCompile *)(pSrcCache -> pProvider)) -> sPackage ;
/* update cache parameter from source */
ProviderEpRun_IsExpired (r, pProvider) ;
}
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpRun_FreeContent */
/* */
/*!
* \_en
* Free the cached data
*
* @param r Embperl request record
* @param pProvider The provider record
* @return error code
* \endif
*
* \_de
* Gibt die gecachten Daten frei
*
* @param r Embperl request record
* @param pProvider The provider record
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
int ProviderEpRun_FreeContent(/*in*/ req * r,
/*in*/ tCacheItem * pItem)
{
if (pItem -> xData)
return DomTree_delete (r -> pApp, DomTree_self(pItem -> xData)) ;
return ok ;
}
/* ------------------------------------------------------------------------ */
tProviderClass ProviderClassEpRun =
{
"X-Embperl/DomTree",
&ProviderEpRun_New,
&ProviderEpRun_AppendKey,
NULL,
NULL,
NULL,
&ProviderEpRun_GetContentIndex,
&ProviderEpRun_FreeContent,
&ProviderEpRun_IsExpired,
} ;
/* ------------------------------------------------------------------------ */
/* */
/*! Provider for Embperl DomTree to String converter */
/* */
typedef struct tProviderEpToString
{
tProvider Provider ;
} tProviderEpToString ;
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpToString_New */
/* */
/*!
* \_en
* Creates a new DomTree to String provider and fills it with data from the
* hash pParam. The resulting provider is put into the cache structure
*
* @param r Embperl request record
* @param pItem CacheItem which holds the output of the provider
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* @param pParam All Parameters
* @param nParamIndex If pParam is an AV, this parameter gives the index into the Array
* @return error code
* \endif
*
* \_de
* Erzeugt einen neue Provider für den Embperl zu Textkonverter. Der ein Zeiger
* auf den resultierenden Provider wird in die Cachestrutr eingefügt
*
* @param r Embperl request record
* @param pItem CacheItem welches die Ausgabe des Providers
* speichert
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash dieses Providers
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderEpToString_New (/*in*/ req * r,
/*in*/ tCacheItem * pItem,
/*in*/ tProviderClass * pProviderClass,
/*in*/ HV * pProviderParam,
/*in*/ SV * pParam,
/*in*/ IV nParamIndex)
{
int rc ;
if ((rc = Provider_NewDependOne (r, sizeof(tProviderEpToString), "source", pItem, pProviderClass, pProviderParam, pParam, nParamIndex)) != ok)
return rc ;
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpToString_AppendKey */
/* */
/*!
* \_en
* Append it's key to the keystring. If it depends on anything it must
* call Cache_AppendKey for any dependency.
*
* @param r Embperl request record
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* @param pParam All Parameters
* @param nParamIndex If pParam is an AV, this parameter gives the index into the Array
* @param pKey Key to which string should be appended
* @return error code
* \endif
*
* \_de
* Hängt ein eigenen Schlüssel an den Schlüsselstring an. Wenn irgednwelche
* Abhänigkeiten bestehen, muß Cache_AppendKey für alle Abhänigkeiten aufgerufen
* werden.
*
* @param r Embperl request record
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash dieses Providers
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @param pKey Schlüssel zu welchem hinzugefügt wird
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderEpToString_AppendKey (/*in*/ req * r,
/*in*/ tProviderClass * pProviderClass,
/*in*/ HV * pProviderParam,
/*in*/ SV * pParam,
/*in*/ IV nParamIndex,
/*i/o*/ SV * pKey)
{
epTHX_
int rc ;
if ((rc = Cache_AppendKey (r, pProviderParam, "source", pParam, nParamIndex, pKey)) != ok)
return rc;
sv_catpv (pKey, "*eptostring") ;
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpToString_GetContentIndex */
/* */
/*!
* \_en
* Get the whole content from the provider.
* The Embperl parser provider parsers the source and generates a DomTree
*
* @param r Embperl request record
* @param pProvider The provider record
* @param pData Returns the content
* @param bUseCache Set if the content should not recomputed
* @return error code
* \endif
*
* \_de
* Holt den gesamt Inhalt vom Provider.
* Der Embperl Parser Provider parsest die Quelle und erzeugt einen DomTree
*
* @param r Embperl request record
* @param pProvider The provider record
* @param pData Liefert den Inhalt
* @param bUseCache Gesetzt wenn der Inhalt nicht neu berechnet werden soll
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static int ProviderEpToString_GetContentSV (/*in*/ req * r,
/*in*/ tProvider * pProvider,
/*in*/ SV * * pData,
/*in*/ bool bUseCache)
{
epTHX_
int rc ;
STRLEN len ;
tIndex xSrcDomTree ;
tCacheItem * pSrcCache ;
SV * pOut ;
char * pBuf ;
tDomTree * pDomTree ;
pSrcCache = Cache_GetDependency(r, pProvider -> pCache, 0) ;
if ((rc = Cache_GetContentIndex (r, pSrcCache, &xSrcDomTree, bUseCache)) != ok)
return rc ;
if (!bUseCache)
{
if (xSrcDomTree == 0)
{
strncpy (r -> errdat1, "EpToString source", sizeof (r -> errdat1)) ;
return rcMissingInput ;
}
oRollbackOutput (r, NULL) ;
oBegin (r) ;
pDomTree = DomTree_self (xSrcDomTree) ;
Node_toString (r, pDomTree, pDomTree -> xDocument, 0) ;
pOut = newSV (1) ;
len = GetContentLength (r) + 1 ;
SvGROW (pOut, len) ;
pBuf = SvPVX (pOut) ;
oCommitToMem (r, NULL, pBuf) ;
oRollbackOutput (r, NULL) ;
SvCUR_set (pOut, len - 1) ;
SvPOK_on (pOut) ;
*pData = pOut ;
}
return ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderEpToString_FreeContent */
/* */
/*!
* \_en
* Free the cached data
*
* @param r Embperl request record
* @param pProvider The provider record
* @return error code
* \endif
*
* \_de
* Gibt die gecachten Daten frei
*
* @param r Embperl request record
* @param pProvider The provider record
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
int ProviderEpToString_FreeContent(/*in*/ req * r,
/*in*/ tCacheItem * pItem)
{
if (pItem -> xData)
return DomTree_delete (r -> pApp, DomTree_self(pItem -> xData)) ;
return ok ;
}
/* ------------------------------------------------------------------------ */
tProviderClass ProviderClassEpToString =
{
"text/*",
&ProviderEpToString_New,
&ProviderEpToString_AppendKey,
NULL,
&ProviderEpToString_GetContentSV,
NULL,
NULL,
&ProviderEpToString_FreeContent,
NULL,
} ;
/* ------------------------------------------------------------------------ */
/* */
/* Provider_Init */
/* */
/*!
* \_en
* Register all the providers
* @return error code
*
* \endif
*
* \_de
* Provider registrieren
* @return Fehlercode
*
* \endif
*
* ------------------------------------------------------------------------ */
int Provider_Init (/*in*/ tApp * a)
{
Cache_AddProviderClass ("file", &ProviderClassFile) ;
Cache_AddProviderClass ("memory", &ProviderClassMem) ;
Cache_AddProviderClass ("epparse", &ProviderClassEpParse) ;
Cache_AddProviderClass ("epcompile", &ProviderClassEpCompile) ;
Cache_AddProviderClass ("eprun", &ProviderClassEpRun) ;
Cache_AddProviderClass ("eptostring",&ProviderClassEpToString) ;
ep_create_mutex(PackageCountMutex) ;
return ok ;
}