⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xslt.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 3 页
字号:
				}
			}
		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 + -