📄 xslt.cpp
字号:
}
}
else if ( !PIUtil_stricmp( KEY_CONF_EXTRAHDRPREFIX, pVariable ) )
{
sExtraHeadersPrefix = (const char *)DeQuote( pValue );
}
else if ( !PIUtil_stricmp( KEY_CONF_EXTRAHEADERSIGNORE, pVariable ) )
{
StringTokenizer tTokens( (const char *)DeQuote(pValue), " " );
for( int i=0; i<tTokens.NumTokens(); i++)
{
lIgnoreHeaders.Append( (DblList::type)
PI_NEW( PIString( tTokens.GetToken( i ) ) ) );
};
}
else if ( !PIUtil_stricmp( KEY_CONF_EXTRAHEADERS, pVariable ) )
{
if ( !PIUtil_stricmp( VALUE_NO, pValue ) )
{ iExtraHeaders = 0; };
}
else if ( !PIUtil_stricmp( KEY_CONF_MAXDEPTH, pVariable ) )
{
xsltMaxDepth = atoi( DeQuote(pValue) );
}
else if ( !PIUtil_stricmp( KEY_CONF_CONTENTTYPE, pVariable ) )
{
sContentType = (const char *)DeQuote( pValue );
}
else
{
os << "Unknown directive '" << pVariable <<
"'" << ends;
CONFIG_ERR( Object(), os.str() );
return 0;
};
return 1;
};
public:
XSLT( PIObject *pObject, int iArgc, const char *ppArgv[] )
:
pTypes( PIDB_new( 0, "Types" ) ),
iExtraHeaders( 1 ),
default_style( NULL ),
iOptions( 0 ),
iParams( 0 ),
sContentType( "" ),
HandlerBaseXSLT( pObject )
{
xmlInitMemory();
LIBXML_TEST_VERSION
ReadParameters( iArgc, ppArgv );
if ( !IsOK() ) { return; };
// Initialization function for the XML parser. This is not reentrant.
// Call once before processing in case of use in multithreaded programs.
xmlInitParser();
// some initialization stuff
xmlLineNumbersDefault(1);
xmlSubstituteEntitiesDefault(1);
exsltRegisterAll();
// -nonet
if ( iOptions & FLG_NONET )
xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
if (!OriginEntityLoader)
OriginEntityLoader = xmlGetExternalEntityLoader();
xmlSetExternalEntityLoader(xmlEntityLoader);
// -xinclude
if ( iOptions & FLG_XINCLUDE )
xsltSetXIncludeDefault(1);
// -catalogs
if ( iOptions & FLG_CATALOGS ) {
const char *catalogs = getenv("SGML_CATALOG_FILES");
if (catalogs) {
xmlLoadCatalogs(catalogs);
} else {
CONFIG_WARN(pObject, "Environment variable $SGML_CATALOG_FILES not set.");
}
}
/*
-output // not supported
-noout // not supported
-repeat // not supported
-warnnet // not supported (by libxml)
*/
};
virtual ~XSLT()
{
PIDB_delete( pTypes );
for( DblListIterator i( lIgnoreHeaders ); !i.BadIndex(); i++ )
{ PI_DELETE( (PIString *)i.Current() ); };
xsltCleanupGlobals();
xmlCleanupParser();
};
int Handle( int iPhase, PIHTTP &tPIHTTP, PIIOBuffer &tBuffer )
{
if ( iPhase!=PH_HANDLE )
{ return PIAPI_ERROR; };
PIDB *pQ = tPIHTTP.pRequestDB;
PIDB *pR = tPIHTTP.pResponseDB;
int iRet = PIAPI_ERROR;
int iFlags;
int iMethod;
in_ctx ctx;
const char *pDocPath, *pDocURI;
const char *pCLen, *pCType;
int nParams = 0;
const char *pParams[MAX_PARAMETERS + 1];
enum { BUF_SIZE=255 };
char szBuf [BUF_SIZE+1];
char *pBuffer = szBuf;
const char *pKey, *pValue;
Pi3Expression *pExpr;
xsltStylesheetPtr cur = NULL;
xmlDocPtr doc = NULL;
xmlDocPtr res = NULL;
const xmlChar *encoding;
const xmlChar *method;
xmlChar *buffer;
xmlCharEncodingHandlerPtr encoder = NULL;
xmlOutputBufferPtr obuf = NULL;
xmlParserInputBufferPtr ibuf = NULL;
// -novalid
if ( iOptions & FLG_NODTD ) {
xmlLoadExtDtdDefaultValue = 0;
} else {
xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
};
// without this embedded stylesheets don't work
if ( iOptions & FLG_VALIDATE ) {
xmlDoValidityCheckingDefaultValue = 1;
} else {
xmlDoValidityCheckingDefaultValue = 0;
}
/* ---
Get server variables
--- */
PIDBIterator *pIter = PIDB_getIterator( pTypes, PIDBTYPE_OPAQUE, 0, 0 );
if ( !pIter ) {
HTTPCore_logError( &tPIHTTP, "XSLT: Internal error when creating iterator." );
goto do_error;
}
// the number of parameters has been checked on startup already!
for(; PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter ) )
{
pExpr = (Pi3Expression *)PIDBIterator_current( pIter, &pKey );
assert( pKey && pExpr );
int iWritten = Pi3Expression_write( pExpr, &tPIHTTP, NULL,
(char *)pBuffer, BUF_SIZE );
if ( iWritten==-1 )
{
pBuffer = (char *)PIHTTP_allocMem( &tPIHTTP, iWritten );
int iWritten = Pi3Expression_write( pExpr, &tPIHTTP, NULL,
(char *)pBuffer, BUF_SIZE );
if ( iWritten==-1 )
{
HTTPCore_logError( &tPIHTTP, "XSLT: Internal error when writing \
variable expression.");
goto do_error;
}
}
pBuffer[iWritten] = 0;
// -param
pParams[nParams++]=(const char *)xmlStrdup((const xmlChar *)pKey);
pParams[nParams++]=(const char *)xmlStrdup((const xmlChar *)pBuffer);
}
PIDBIterator_delete( pIter );
/* --- Get extra request headers --- */
if ( iExtraHeaders )
{
/* --- loop over all RFC822 headers in request block --- */
PIDBIterator *pIter = PIDB_getIterator( pQ, PIDBTYPE_RFC822, 0, 0 );
if ( !pIter ) {
HTTPCore_logError( &tPIHTTP, "XSLT: Internal error when creating iterator." );
goto do_error;
}
for(; PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter ) )
{
if (nParams < MAX_PARAMETERS - 1)
{
pValue = (const char *)PIDBIterator_current( pIter, &pKey );
assert( pKey && pValue );
if ( !pKey || !pValue ) { /* sanity */ continue; };
if (checkIgnoreList(pKey)) continue;
PIString sTest(sExtraHeadersPrefix);
sTest.Concatenate(pKey);
char *pBuf = (char *)(const char *)sTest;
for( int i=0; i<sTest.Len(); i++ )
{
if ( isalnum( pBuf[i] ) )
{ pBuf[i]=toupper(pBuf[i]); }
else
{ pBuf[i]='_'; };
}
// -stringparam
buffer = xmlStrdup((const xmlChar *)"'");
buffer = xmlStrncat(buffer, (const xmlChar *)pValue, strlen(pValue));
buffer = xmlStrcat(buffer, (const xmlChar *)"'");
pParams[nParams++]=(const char *)xmlStrdup((const xmlChar *)pBuf);
pParams[nParams++]=(const char *)buffer;
}
else
{
HTTPCore_logError( &tPIHTTP, "XSLT: Too much parameters.");
goto do_error;
}
}
PIDBIterator_delete( pIter );
}
pParams[nParams]=NULL;
xsltSetGenericErrorFunc((void *)&tPIHTTP, xmlErrorCB);
// -verbose
if (( iOptions & FLG_VERBOSE ) && HTTPCore_debugEnabled() )
xsltSetGenericDebugFunc((void *)&tPIHTTP, xmlDebugCB);
/* ---
Get file object
--- */
pDocPath = (const char *)PIDB_lookup( pR, PIDBTYPE_STRING,
KEY_INT_PATH, 0 );
pDocURI = getFileURI(pDocPath);
/* ---
Get request method
--- */
iMethod = (int)PIDB_lookup( pQ, PIDBTYPE_OPAQUE, KEY_HTTP_METHOD, 0 );
if ( iMethod == MD_POST ) {
/* ---
Get the Content-Length
--- */
pCLen = (const char *)PIDB_lookup(pQ, PIDBTYPE_RFC822, KEY_HTTP_CONTENTLENGTH, 0);
if (!pCLen) {
HTTPCore_logError( &tPIHTTP, "XSLT: Missing Content-Length \
in POST request." );
goto do_error;
};
/* ---
Get the Content-Type
--- */
pCType = (const char *)PIDB_lookup(pQ, PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE, 0);
if (!pCType) {
HTTPCore_logError( &tPIHTTP, "XSLT: Missing Content-Type \
in POST request." );
goto do_error;
};
ctx.iobuf = &tBuffer;
ctx.clength = atol(pCLen);
ctx.state = STATE_NEW;
ctx.read = 0;
/* ---
Fire off the parser
--- */
if (!PIUtil_stricmp(pCType, "text/plain"))
{
doc = xmlIOParsePlainEntity(
(void *)&ctx,
XML_CHAR_ENCODING_8859_1
);
}
else if (!PIUtil_stricmp(pCType, "application/x-www-form-urlencoded"))
{
doc = xmlIOParseFormEntity(
(void *)&ctx,
XML_CHAR_ENCODING_8859_1
);
}
else
{
HTTPCore_logError( &tPIHTTP, "XSLT: Unknown Content-Type \
in POST request." );
goto do_error;
}
} else {
// -html, -docbook
if ( iOptions & FLG_HTML ) {
doc = xmlPi3ParseHtmlFile(pDocURI, NULL);
} else if ( iOptions & FLG_DOCBOOK ) {
doc = xmlPi3ParseDocbookFile(pDocURI, NULL);
} else {
doc = xmlPi3ParseXmlFile( pDocURI, &tPIHTTP );
};
}
if (!doc) {
HTTPCore_logError( &tPIHTTP, "XSLT: XML parser error in file \
with path '%s'.", pDocPath );
goto do_error;
};
if ( iOptions & FLG_VALIDATE && !doc->_private) {
HTTPCore_logDebug( DBG_MED, "XSLT: Document with path '%s' is not \
valid according to it's DTD", pDocPath);
}
if ( iOptions & FLG_XINCLUDE ) {
xmlXIncludeProcess(doc);
}
cur = default_style ? default_style : xsltLoadStylesheetPI(doc);
if (!cur) {
HTTPCore_logError( &tPIHTTP, "XSLT: Can't load stylesheet for file \
with path '%s'.", pDocPath );
goto do_error;
};
res = xsltApplyStylesheet(cur, doc, pParams);
if (!res) {
HTTPCore_logError( &tPIHTTP, "XSLT: Can't apply stylesheet on file \
with path '%s'.", pDocPath );
goto do_error;
};
if ( iOptions & FLG_DEBUG )
xmlDebugDumpDocument(stdout, res);
XSLT_GET_IMPORT_PTR(encoding, cur, encoding)
if (encoding != NULL) {
encoder = xmlFindCharEncodingHandler((char *)encoding);
if ((encoder != NULL) && (xmlStrEqual((const xmlChar *)encoder->name,
(const xmlChar *) "UTF-8"))) encoder = NULL;
};
obuf = xmlOutputBufferCreateIO(
xmlWriteCB,
xmlOutCloseCB,
(void *)&tBuffer,
encoder
);
if (strlen(sContentType)) {
// Overwrite content-type with configuration value
PIDB_replace(pR, PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE,
(void *)(const char *)sContentType, 0);
} else {
/* --- content-type --- */
XSLT_GET_IMPORT_PTR(method, cur, method)
if ((method == NULL) && (res->type == XML_HTML_DOCUMENT_NODE))
method = (const xmlChar *) "html";
if (method != NULL) {
if (xmlStrEqual(method, (const xmlChar *) "xml")) {
PIDB_replace(pR, PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE, "application/xml", 0);
} else if (xmlStrEqual(method, (const xmlChar *) "html")) {
PIDB_replace(pR, PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE, "text/html", 0);
} else if (xmlStrEqual(method, (const xmlChar *) "xhtml")) {
PIDB_replace(pR, PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE, "text/html", 0);
} else if (xmlStrEqual(method, (const xmlChar *) "text")) {
PIDB_replace(pR, PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE, "text/plain", 0);
// unknown content-type, use server default
} else {
PIDB_replace(pR, PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE,
(void *)HTTPCore_getMIMETypeFromExtension(NULL), 0);
}
// unknown content-type, use server default
} else {
PIDB_replace(pR, PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE,
(void *)HTTPCore_getMIMETypeFromExtension(NULL), 0);
}
}
/* --- transfer-encoding --- */
iFlags = (!PIHTTP_isChild( &tPIHTTP) && (int)PIDB_lookup( tPIHTTP.pRequestDB,
PIDBTYPE_OPAQUE, KEY_HTTP_PROTOCOL, 0 ) == 3 ) ? PIIOBUF_CHUNKED : PIIOBUF_NONE;
if ( iFlags & PIIOBUF_CHUNKED )
{
PIDB_replace( pR, PIDBTYPE_RFC822, KEY_HTTP_TRANSFERENCODING,
(void *)KEY_HTTP_CHUNKED, 0 );
}
else
{
/* ---
disable keep open, assuming content-length cannot be set
--- */
PIDB_replace( tPIHTTP.pConnectionDB, PIDBTYPE_OPAQUE,
KEY_INT_KEEPOPEN, (void *)0, 0 );
};
HTTPCore_sendGeneralHeaders(&tPIHTTP);
HTTPCore_sendEntityHeaders(&tPIHTTP, pR);
if ( iFlags & PIIOBUF_CHUNKED ) PIIOBuffer_flush(&tBuffer);
PIIOBuffer_setUserData(&tBuffer, (void *)iFlags);
if (xsltSaveResultTo(obuf, res, cur) < 0)
{
#define TMP "XSLT: Error on writing XSLT output."
PIIOBuffer_write(&tBuffer, TMP, strlen(TMP), iFlags);
#undef TMP
};
iRet = PIAPI_COMPLETED;
goto done;
do_error:
HTTPCore_logError( &tPIHTTP, "XSLT: Using libxml %s, libxslt %s and \
libexslt %s.", xmlParserVersion, xsltEngineVersion, exsltLibraryVersion);
HTTPCore_logError( &tPIHTTP, "XSLT: Handler was compiled against libxml %d, \
libxslt %d and libexslt %d.", LIBXML_VERSION, LIBXSLT_VERSION, LIBEXSLT_VERSION);
HTTPCore_logError( &tPIHTTP, "XSLT: libxslt %d was compiled against libxml %d.",
xsltLibxsltVersion, xsltLibxmlVersion);
HTTPCore_logError( &tPIHTTP, "XSLT: libexslt %d was compiled against libxml %d \
and libxslt %d.", exsltLibexsltVersion, exsltLibxmlVersion, exsltLibxsltVersion);
iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR);
done:
for (int i=0;i<nParams;i++)
xmlFree((void *)pParams[i]);
// don't free default stylesheet!
if (cur && (cur != default_style)) xsltFreeStylesheet(cur);
if (doc) xmlFreeDoc(doc);
if (res) xmlFreeDoc(res);
xmlCleanupParser();
return iRet;
};
};
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int XSLT_constructor( PIObject *pObj,
int iArgc, const char *ppArgv[] )
{
return HandlerBaseXSLT_constructor( pObj, PI_NEW( XSLT( pObj,
iArgc, ppArgv ) ) );
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int XSLT_destructor( PIObject *pObj, int,
const char *[] )
{
delete (XSLT *)PIObject_getUserData( pObj );
return PIAPI_COMPLETED;
}
#if 0
/*___+++CNF_BEGIN+++___*/
<Class>
Name XSLTClass
Type LogicExtension
Library XSLT
OnClassLoad HandlerBaseXSLT_onClassLoad
Constructor XSLT_constructor
CopyConstructor HandlerBaseXSLT_copyConstructor
Destructor XSLT_destructor
Execute HandlerBaseXSLT_execute
</Class>
<Object>
Name XSLT
Class XSLTClass
</Object>
/*___+++CNF_END+++___*/
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -