/*###################################################################################
#
# 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.
#
###################################################################################*/
/* undef some defines that clashs with c++ includes */
#undef bool
#undef HAS_BOOL
extern
"C"
{
#include "../ep.h"
#include "../epmacro.h"
}
#undef assert
#undef vform
#include <Include/PlatformDefinitions.hpp>
#if defined(XALAN_OLD_STREAM_HEADERS)
#include <iostream.h>
#include <strstream.h>
#include <fstream.h>
#else
#include <iostream>
#include <strstream>
#include <fstream>
#endif
#include <util/PlatformUtils.hpp>
#include <XalanTransformer/XalanTransformer.hpp>
extern
"C"
{
XalanTransformer * theXalanTransformer;
static
int
bInitDone = 0 ;
/*! Provider that reads compiles xalan stylesheet */
typedef
struct
tProviderXalanXSL
{
tProvider Provider ;
} tProviderXalanXSL ;
/* ------------------------------------------------------------------------ */
/* */
/* ProviderXalanXSL_New */
/* */
/*!
* \_en
* Creates a new xalan stylesheet 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
* stylesheet filename or provider for the
* stylesheet
* @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 Xalan Stylesheets. 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
* stylesheet dateiname oder provider für das
* stylesheet
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static
int
ProviderXalanXSL_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
(tProviderXalanXSL),
"stylesheet"
, pItem, pProviderClass, pProviderParam, pParam, nParamIndex)) != ok)
return
rc ;
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.
*
* @param r Embperl request record
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* stylesheet filename or provider for the
* stylesheet
* @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
* stylesheet dateiname oder provider für das
* stylesheet
* @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
ProviderXalanXSL_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,
"stylesheet"
, pParam, nParamIndex, pKey)) != ok)
return
rc;
sv_catpv (pKey,
"*xalan-compile-xsl"
) ;
return
ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderXalanXSL_GetContentPtr */
/* */
/*!
* \_en
* Get the whole content from the provider.
* This gets the stylesheet and compiles it
*
* @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.
* Die Funktion holt sich das Stylesheet und kompiliert es
*
* @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
ProviderXalanXSL_GetContentPtr (
/*in*/
req * r,
/*in*/
tProvider * pProvider,
/*in*/
void
* * pData,
/*in*/
bool
bUseCache)
{
epTHX_
int
rc ;
char
* p ;
STRLEN len ;
SV * pSource ;
const
XalanCompiledStylesheet* pCompiledStylesheet = NULL ;
tCacheItem * pFileCache = Cache_GetDependency(r, pProvider -> pCache, 0) ;
if
((rc = Cache_GetContentSV (r, pFileCache, &pSource, bUseCache)) != ok)
return
rc ;
if
(!bUseCache)
{
// Our input streams...
p = SvPV (pSource, len) ;
if
(p == NULL || len == 0)
{
strncpy
(r -> errdat1,
"Xalan XML stylesheet"
,
sizeof
(r -> errdat1)) ;
return
rcMissingInput ;
}
r -> Component.pCurrPos = NULL ;
r -> Component.nSourceline = 1 ;
r -> Component.pSourcelinePos = NULL ;
r -> Component.pLineNoCurrPos = NULL ;
istrstream theXMLStream(p, len);
if
(theXalanTransformer -> compileStylesheet(&theXMLStream, pCompiledStylesheet))
{
Cache_ReleaseContent (r, pFileCache) ;
strncpy
(r -> errdat1,
"XSL compile"
,
sizeof
(r -> errdat1)) ;
strncpy
(r -> errdat2, theXalanTransformer -> getLastError(),
sizeof
(r -> errdat2) - 2) ;
return
rcXalanError ;
}
*pData = (
void
*)pCompiledStylesheet ;
}
return
ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderXalanXSL_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
*
* ------------------------------------------------------------------------ */
static
int
ProviderXalanXSL_FreeContent(
/*in*/
req * r,
/*in*/
tCacheItem * pItem)
{
XalanCompiledStylesheet* pCompiledStylesheet = (XalanCompiledStylesheet*)pItem -> pData ;
if
(pCompiledStylesheet)
theXalanTransformer -> destroyStylesheet (pCompiledStylesheet) ;
return
ok ;
}
/* ------------------------------------------------------------------------ */
static
tProviderClass ProviderClassXalanXSL =
{
"text/*"
,
&ProviderXalanXSL_New,
&ProviderXalanXSL_AppendKey,
NULL,
NULL,
&ProviderXalanXSL_GetContentPtr,
NULL,
&ProviderXalanXSL_FreeContent,
NULL,
} ;
/*! Provider that reads compiles xalan stylesheet */
typedef
struct
tProviderXalanXML
{
tProvider Provider ;
} tProviderXalanXML ;
/* ------------------------------------------------------------------------ */
/* */
/* ProviderXalanXML_New */
/* */
/*!
* \_en
* Creates a new xalan xml source 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 Xalan XML Quellen. 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
ProviderXalanXML_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
(tProviderXalanXML),
"source"
, pItem, pProviderClass, pProviderParam, pParam, nParamIndex)) != ok)
return
rc ;
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.
*
* @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
ProviderXalanXML_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,
"*xalan-parse-xml"
) ;
return
ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderXalanXML_GetContentPtr */
/* */
/*!
* \_en
* Get the whole content from the provider.
* This gets the stylesheet and compiles it
*
* @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.
* Die Funktion holt sich das Stylesheet und kompiliert es
*
* @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
ProviderXalanXML_GetContentPtr (
/*in*/
req * r,
/*in*/
tProvider * pProvider,
/*in*/
void
* * pData,
/*in*/
bool
bUseCache)
{
epTHX_
int
rc ;
char
* p ;
STRLEN len ;
SV * pSource ;
const
XalanParsedSource * parsedXML = NULL ;
tCacheItem * pFileCache = Cache_GetDependency(r, pProvider -> pCache, 0) ;
if
((rc = Cache_GetContentSV (r, pFileCache, &pSource, bUseCache)) != ok)
return
rc ;
if
(!bUseCache)
{
// Our input streams...
p = SvPV (pSource, len) ;
if
(p == NULL || len == 0)
{
strncpy
(r -> errdat1,
"Xalan XML source"
,
sizeof
(r -> errdat1)) ;
return
rcMissingInput ;
}
r -> Component.pCurrPos = NULL ;
r -> Component.nSourceline = 1 ;
r -> Component.pSourcelinePos = NULL ;
r -> Component.pLineNoCurrPos = NULL ;
istrstream theXMLStream(p, len);
if
(theXalanTransformer -> parseSource(&theXMLStream, parsedXML))
{
Cache_ReleaseContent (r, pFileCache) ;
strncpy
(r -> errdat1,
"XSL compile"
,
sizeof
(r -> errdat1)) ;
strncpy
(r -> errdat2, theXalanTransformer -> getLastError(),
sizeof
(r -> errdat2) - 2) ;
return
rcXalanError ;
}
*pData = (
void
*)parsedXML ;
}
return
ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderXalanXML_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
*
* ------------------------------------------------------------------------ */
static
int
ProviderXalanXML_FreeContent(
/*in*/
req * r,
/*in*/
tCacheItem * pItem)
{
const
XalanParsedSource * parsedXML = (XalanParsedSource *)pItem -> pData ;
if
(parsedXML)
theXalanTransformer -> destroyParsedSource (parsedXML);
return
ok ;
}
/* ------------------------------------------------------------------------ */
static
tProviderClass ProviderClassXalanXML =
{
"text/*"
,
&ProviderXalanXML_New,
&ProviderXalanXML_AppendKey,
NULL,
NULL,
&ProviderXalanXML_GetContentPtr,
NULL,
&ProviderXalanXML_FreeContent,
NULL,
} ;
/* ------------------------------------------------------------------------ */
/* */
/* iowrite */
/* */
/* output callback */
/* */
/* ------------------------------------------------------------------------ */
static
long
unsigned
int
iowrite (
const
char
*buffer,
long
unsigned
int
len,
void
*context)
{
return
owrite ((tReq *)context, buffer, len) ;
}
#if 0
/* ------------------------------------------------------------------------ */
/* */
/* embperl_Xalan_Text2Text */
/* */
/* Do an XSL transformation using LibXSLT. Input and Output is Text. */
/* The stylesheet is directly read from disk */
/* */
/* in pReqParameter Parameter for request */
/* xsltparameter Hash which is passed as parameters to libxslt */
/* xsltstylesheet filename of stylsheet */
/* pSource XML source in memory */
/* */
/* ------------------------------------------------------------------------ */
int
embperl_Xalan_Text2Text (
/*in*/
tReq * r,
/*in*/
HV * pReqParameter,
/*in*/
SV * pSource)
{
epTHX_
int
rc ;
HE * pEntry ;
HV * pParam ;
SV * pStylesheetParam ;
SV * * ppSV ;
char
* pKey ;
SV * pValue ;
STRLEN len ;
IV l ;
int
n ;
const
char
* * pParamArray ;
const
char
* sStylesheet ;
char
* p ;
#if !defined(XALAN_NO_NAMESPACES)
using
std::istrstream;
#endif
sStylesheet = GetHashValueStr (aTHX_ pReqParameter,
"xsltstylesheet"
, NULL) ;
if
(!sStylesheet)
{
strncpy
(r -> errdat1,
"XSLT"
,
sizeof
(r -> errdat1)) ;
strncpy
(r -> errdat2,
"No stylesheet given"
,
sizeof
(r -> errdat2)) ;
return
9999 ;
}
ppSV = hv_fetch (pReqParameter,
"xsltparameter"
,
sizeof
(
"xsltparameter"
) - 1, 0) ;
if
(ppSV && *ppSV)
{
if
(!SvROK (*ppSV) || SvTYPE ((SV *)(pParam = (HV *)SvRV (*ppSV))) != SVt_PVHV)
{
strncpy
(r -> errdat1,
"XSLT"
,
sizeof
(r -> errdat1)) ;
sprintf
(r -> errdat2,
"%s"
, pKey) ;
return
rcNotHashRef ;
}
n = hv_iterinit (pParam) ;
if
(!(pParamArray = (
const
char
* *)_malloc(r,
sizeof
(
const
char
*) * (n + 1) * 2)))
return
rcOutOfMemory ;
n = 0 ;
while
((pEntry = hv_iternext (pParam)))
{
pKey = hv_iterkey (pEntry, &l) ;
pValue = hv_iterval (pParam, pEntry) ;
pParamArray[n++] = pKey ;
pParamArray[n++] = SvPV (pValue, len) ;
}
pParamArray[n++] = NULL ;
}
else
{
pParamArray = NULL ;
}
// Our input streams...
p = SvPV (pSource, len) ;
istrstream theXMLStream(p, len);
pStylesheetParam = sv_2mortal (CreateHashRef (r,
(
char
*)
"provider"
, hashtsv, CreateHashRef (r,
(
char
*)
"type"
, hashtstr, (
char
*)
"xalan-compile-xsl"
,
(
char
*)
"stylesheet"
, hashtsv, CreateHashRef (r,
(
char
*)
"provider"
, hashtsv, CreateHashRef (r,
(
char
*)
"type"
, hashtstr, (
char
*)
"file"
,
(
char
*)
"filename"
, hashtstr, sStylesheet,
NULL),
(
char
*)
"cache"
, hashtint, 0,
NULL),
NULL),
NULL)) ;
if
(!SvROK (pStylesheetParam) || SvTYPE(SvRV(pStylesheetParam)) != SVt_PVHV)
{
strncpy
(r -> errdat2,
"stylesheet"
,
sizeof
(r -> errdat2) - 1) ;
return
rcNotHashRef ;
}
tCacheItem * pXSLCache ;
// does not work !!!!!!!!!!!!!!!!!!!!
//if ((rc = Cache_New (r, (HV *)SvRV(pStylesheetParam), &pXSLCache)) != ok)
// return rc ;
XalanCompiledStylesheet * pCompiledXSL ;
bool
bUseCache = 0 ;
if
((rc = Cache_GetContentPtr (r, pXSLCache, (
void
* *)&pCompiledXSL, bUseCache)) != ok)
return
rc ;
// Do the transform.
const
XalanParsedSource * parsedXML = 0;
theXalanTransformer -> parseSource(&theXMLStream, parsedXML);
int
theResult = theXalanTransformer -> transform(*parsedXML, pCompiledXSL, r, iowrite, NULL);
Cache_ReleaseContent (r, pXSLCache) ;
if
(theResult != 0)
{
strncpy
(r -> errdat1,
"XSLT"
,
sizeof
(r -> errdat1)) ;
strncpy
(r -> errdat2, theXalanTransformer -> getLastError(),
sizeof
(r -> errdat2) - 2) ;
return
rcXalanError ;
}
// Terminate Xalan.
//XalanTransformer::terminate();
// Call the static terminator for Xerces.
//XMLPlatformUtils::Terminate();
return
(0);
}
#endif
/*! Provider that reads compiles xalan stylesheet */
typedef
struct
tProviderXalan
{
tProvider Provider ;
SV * pOutputSV ;
HV * pParamHV ;
} tProviderXalan ;
/* ------------------------------------------------------------------------ */
/* */
/* ProviderXalan_New */
/* */
/*!
* \_en
* Creates a new xalan 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
* stylesheet filename or provider for the
* stylesheet
* @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 Xalan. 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
* stylesheet dateiname oder provider für das
* stylesheet
* @param pParam Parameter insgesamt
* @param nParamIndex Wenn pParam ein AV ist, gibt dieser Parameter den Index an
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
int
ProviderXalan_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
(tProviderXalan),
"source"
, pItem, pProviderClass, pProviderParam, pParam, nParamIndex)) != ok)
return
rc ;
if
((rc = Provider_AddDependOne (r, pItem -> pProvider,
"stylesheet"
, pItem, pProviderClass, pProviderParam, NULL, 0)) != ok)
return
rc ;
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.
*
* @param r Embperl request record
* @param pProviderClass Provider class record
* @param pProviderParam Parameter Hash of this Providers
* stylesheet filename or provider for the
* stylesheet
* @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
* stylesheet dateiname oder provider für das
* stylesheet
* @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
ProviderXalan_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;
if
((rc = Cache_AppendKey (r, pProviderParam,
"stylesheet"
, NULL, 0, pKey)) != ok)
return
rc;
sv_catpv (pKey,
"*xalan"
) ;
return
ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderLibXalan_UpdateParam */
/* */
/*!
* \_en
* Update the parameter of the provider
*
* @param r Embperl request record
* @param pProvider Provider record
* @param pParam Parameter Hash
* param hash with parameter
* @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
* param hash mit parametern
* @param pKey Schlüssel zu welchem hinzugefügt wird
* @return Fehlercode
* \endif
*
* ------------------------------------------------------------------------ */
static
int
ProviderXalan_UpdateParam(
/*in*/
req * r,
/*in*/
tProvider * pProvider,
/*in*/
HV * pParam)
{
epTHX_
int
rc ;
HV * pParamHV ;
if
((rc = GetHashValueHREF (r, pParam,
"param"
, &pParamHV)) != ok)
{
pParamHV = r -> Component.Param.pXsltParam ;
}
if
(((tProviderXalan *)pProvider) -> pParamHV)
SvREFCNT_dec (((tProviderXalan *)pProvider) -> pParamHV) ;
((tProviderXalan *)pProvider) -> pParamHV = pParamHV ;
if
(pParamHV)
{
SV * pSV = (SV *)((tProviderXalan *)pProvider) -> pParamHV ;
#ifdef SOLARIS
ATOMIC_INC(SvREFCNT((pSV))) ;
#else
SvREFCNT_inc((pSV)) ;
#endif
}
return
ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderXalan_iowrite */
/* */
/* output callback */
/* */
/* ------------------------------------------------------------------------ */
struct
iowrite
{
tProviderXalan * pProvider ;
tReq * pReq ;
} ;
static
long
unsigned
int
ProviderXalan_iowrite (
const
char
*buffer,
long
unsigned
int
len,
void
*context)
{
tReq * r = ((
struct
iowrite *)context) -> pReq ;
epTHX_
sv_catpvn (((
struct
iowrite *)context) -> pProvider -> pOutputSV, (
char
*)buffer, len) ;
return
len ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderXalan_GetContentSV */
/* */
/*!
* \_en
* Get the whole content from the provider.
* This gets the stylesheet and compiles it
*
* @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.
* Die Funktion holt sich das Stylesheet und kompiliert es
*
* @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
ProviderXalan_GetContentSV (
/*in*/
req * r,
/*in*/
tProvider * pProvider,
/*in*/
SV * * pData,
/*in*/
bool
bUseCache)
{
epTHX_
int
rc ;
XalanParsedSource * parsedXML ;
XalanCompiledStylesheet * pCompiledXSL ;
HV * pParamHV ;
HE * pEntry ;
char
* pKey ;
SV * pValue ;
IV l ;
STRLEN len ;
struct
iowrite iowrite ;
r -> Component.pCurrPos = NULL ;
r -> Component.nSourceline = 1 ;
r -> Component.pSourcelinePos = NULL ;
r -> Component.pLineNoCurrPos = NULL ;
tCacheItem * pSrcCache = Cache_GetDependency(r, pProvider -> pCache, 0) ;
tCacheItem * pXSLCache = Cache_GetDependency(r, pProvider -> pCache, 1) ;
if
((rc = Cache_GetContentPtr (r, pSrcCache, (
void
* *)&parsedXML, bUseCache)) != ok)
return
rc ;
if
((rc = Cache_GetContentPtr (r, pXSLCache, (
void
* *)&pCompiledXSL, bUseCache)) != ok)
return
rc ;
if
(!bUseCache)
{
if
(((tProviderXalan *)pProvider) -> pOutputSV)
SvREFCNT_dec (((tProviderXalan *)pProvider) -> pOutputSV) ;
((tProviderXalan *)pProvider) -> pOutputSV = newSVpv(
""
,0) ;
pParamHV = ((tProviderXalan *)pProvider) -> pParamHV ;
if
(pParamHV)
{
hv_iterinit (pParamHV) ;
while
((pEntry = hv_iternext (pParamHV)))
{
pKey = hv_iterkey (pEntry, &l) ;
pValue = hv_iterval (pParamHV, pEntry) ;
theXalanTransformer -> setStylesheetParam (XalanDOMString(pKey), XalanDOMString(SvPV(pValue, len))) ;
}
}
iowrite.pProvider = (tProviderXalan *)pProvider ;
iowrite.pReq = r ;
// Do the transform.
int
theResult = theXalanTransformer -> transform(*parsedXML, pCompiledXSL, &iowrite, ProviderXalan_iowrite, NULL);
if
(theResult != 0)
{
strncpy
(r -> errdat1,
"XSLT"
,
sizeof
(r -> errdat1)) ;
strncpy
(r -> errdat2, theXalanTransformer -> getLastError(),
sizeof
(r -> errdat2) - 2) ;
return
rcXalanError ;
}
*pData = iowrite.pProvider -> pOutputSV ;
#ifdef SOLARIS
ATOMIC_INC(SvREFCNT((*pData))) ;
#else
SvREFCNT_inc((*pData)) ;
#endif
}
return
ok ;
}
/* ------------------------------------------------------------------------ */
/* */
/* ProviderXalan_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
*
* ------------------------------------------------------------------------ */
static
int
ProviderXalan_FreeContent(
/*in*/
req * r,
/*in*/
tCacheItem * pItem)
{
epTHX_
tProviderXalan * pProvider = ((tProviderXalan *)pItem -> pProvider) ;
if
(pProvider -> pOutputSV)
SvREFCNT_dec (pProvider -> pOutputSV) ;
pProvider -> pOutputSV = NULL ;
/*
if (pProvider -> pParamHV)
SvREFCNT_dec (pProvider -> pParamHV) ;
pProvider -> pParamHV = NULL ;
*/
return
ok ;
}
/* ------------------------------------------------------------------------ */
static
tProviderClass ProviderClassXalan =
{
"text/*"
,
&ProviderXalan_New,
&ProviderXalan_AppendKey,
&ProviderXalan_UpdateParam,
&ProviderXalan_GetContentSV,
NULL,
NULL,
&ProviderXalan_FreeContent,
NULL,
} ;
/* ------------------------------------------------------------------------ */
int
embperl_Xalan_Init ()
{
Cache_AddProviderClass (
"xalan-compile-xsl"
, &ProviderClassXalanXSL) ;
Cache_AddProviderClass (
"xalan-parse-xml"
, &ProviderClassXalanXML) ;
Cache_AddProviderClass (
"xalan"
, &ProviderClassXalan) ;
// Call the static initializer for Xerces.
XMLPlatformUtils::Initialize();
// Initialize Xalan.
XalanTransformer::initialize();
theXalanTransformer =
new
XalanTransformer ;
return
ok ;
}
}
/* extern C */