/*###################################################################################
#
# 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 ;
}