xmlsecurityengine/xmlsec/src/xmlsec_xslt.c
changeset 0 e35f40988205
child 24 74f0b3eb154c
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 /** 
       
     2  * XML Security Library (http://www.aleksey.com/xmlsec).
       
     3  *
       
     4  * XSLT Transform (http://www.w3.org/TR/xmldsig-core/#sec-XSLT)
       
     5  *
       
     6  * This is free software; see Copyright file in the source
       
     7  * distribution for preciese wording.
       
     8  * 
       
     9  * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
       
    10  * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 
       
    11  */
       
    12 #include "xmlsec_config.h"
       
    13 #ifndef XMLSEC_NO_XSLT
       
    14 #include "xmlsec_globals.h"
       
    15 
       
    16 #include <stdlib.h>
       
    17 #include <string.h>
       
    18  
       
    19 #include <libxml2_tree.h>
       
    20 #include <libxml2_xmlmemory.h> //added for symbian port
       
    21 #include <libxslt/libxslt_xslt.h>
       
    22 #include <libxslt/libxslt_xsltinternals.h>
       
    23 #include <libxslt/libxslt_transform.h>
       
    24 #include <libxslt/libxslt_xsltutils.h>
       
    25 
       
    26 #include "xmlsec_xmlsec.h"
       
    27 #include "xmlsec_xmltree.h"
       
    28 #include "xmlsec_keys.h"
       
    29 #include "xmlsec_transforms.h"
       
    30 #include "xmlsec_keys.h"
       
    31 #include "xmlsec_parser.h"
       
    32 #include "xmlsec_errors.h"
       
    33 
       
    34 /**************************************************************************
       
    35  *
       
    36  * Internal xslt ctx
       
    37  *
       
    38  *****************************************************************************/
       
    39 typedef struct _xmlSecXsltCtx			xmlSecXsltCtx, *xmlSecXsltCtxPtr;
       
    40 struct _xmlSecXsltCtx {
       
    41     xsltStylesheetPtr	xslt;
       
    42     xmlParserCtxtPtr 	parserCtx;
       
    43 };	    
       
    44 
       
    45 /****************************************************************************
       
    46  *
       
    47  * XSLT transform
       
    48  *
       
    49  * xmlSecXsltCtx is located after xmlSecTransform
       
    50  * 
       
    51  ***************************************************************************/
       
    52 #define xmlSecXsltSize	\
       
    53     (sizeof(xmlSecTransform) + sizeof(xmlSecXsltCtx))	
       
    54 #define xmlSecXsltGetCtx(transform) \
       
    55     ((xmlSecXsltCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
       
    56 
       
    57 static int		xmlSecXsltInitialize			(xmlSecTransformPtr transform);
       
    58 static void		xmlSecXsltFinalize			(xmlSecTransformPtr transform);
       
    59 static int 		xmlSecXsltReadNode			(xmlSecTransformPtr transform,
       
    60 								 xmlNodePtr node,
       
    61 								 xmlSecTransformCtxPtr transformCtx);
       
    62 static int 		xmlSecXsltPushBin			(xmlSecTransformPtr transform, 
       
    63 								 const xmlSecByte* data,
       
    64 								 xmlSecSize dataSize,
       
    65 								 int final,
       
    66 							         xmlSecTransformCtxPtr transformCtx);
       
    67 static int  		xmlSecXsltExecute			(xmlSecTransformPtr transform, 
       
    68 								 int last,
       
    69 								 xmlSecTransformCtxPtr transformCtx);
       
    70 static int		xmlSecXslProcess			(xmlSecBufferPtr in,
       
    71 								 xmlSecBufferPtr out,
       
    72 								 xsltStylesheetPtr stylesheet);
       
    73 static xmlSecTransformKlass xmlSecXsltKlass = {
       
    74     /* klass/object sizes */
       
    75     sizeof(xmlSecTransformKlass),		/* xmlSecSize klassSize */
       
    76     xmlSecXsltSize,				/* xmlSecSize objSize */
       
    77 
       
    78     xmlSecNameXslt,				/* const xmlChar* name; */
       
    79     xmlSecHrefXslt, 				/* const xmlChar* href; */
       
    80     xmlSecTransformUsageDSigTransform,		/* xmlSecAlgorithmUsage usage; */
       
    81 
       
    82     xmlSecXsltInitialize,			/* xmlSecTransformInitializeMethod initialize; */
       
    83     xmlSecXsltFinalize,				/* xmlSecTransformFinalizeMethod finalize; */
       
    84     xmlSecXsltReadNode,				/* xmlSecTransformNodeReadMethod readNode; */
       
    85     NULL,					/* xmlSecTransformNodeWriteMethod writeNode; */
       
    86     NULL,					/* xmlSecTransformSetKeyReqMethod setKeyReq; */
       
    87     NULL,					/* xmlSecTransformSetKeyMethod setKey; */
       
    88     NULL,					/* xmlSecTransformValidateMethod validate; */
       
    89     xmlSecTransformDefaultGetDataType,		/* xmlSecTransformGetDataTypeMethod getDataType; */
       
    90     xmlSecXsltPushBin,				/* xmlSecTransformPushBinMethod pushBin; */
       
    91     xmlSecTransformDefaultPopBin,		/* xmlSecTransformPopBinMethod popBin; */
       
    92     NULL,					/* xmlSecTransformPushXmlMethod pushXml; */
       
    93     NULL,					/* xmlSecTransformPopXmlMethod popXml; */
       
    94     xmlSecXsltExecute,				/* xmlSecTransformExecuteMethod execute; */
       
    95     
       
    96     NULL,					/* void* reserved0; */
       
    97     NULL,					/* void* reserved1; */
       
    98 };
       
    99 
       
   100 /**
       
   101  * xmlSecTransformXsltGetKlass:
       
   102  *
       
   103  * XSLT transform klass (http://www.w3.org/TR/xmldsig-core/#sec-XSLT):
       
   104  *
       
   105  * The normative specification for XSL Transformations is [XSLT]. 
       
   106  * Specification of a namespace-qualified stylesheet element, which MUST be 
       
   107  * the sole child of the Transform element, indicates that the specified style 
       
   108  * sheet should be used. Whether this instantiates in-line processing of local 
       
   109  * XSLT declarations within the resource is determined by the XSLT processing 
       
   110  * model; the ordered application of multiple stylesheet may require multiple 
       
   111  * Transforms. No special provision is made for the identification of a remote 
       
   112  * stylesheet at a given URI because it can be communicated via an  xsl:include 
       
   113  * or  xsl:import within the stylesheet child of the Transform.
       
   114  *
       
   115  * This transform requires an octet stream as input. If the actual input is an 
       
   116  * XPath node-set, then the signature application should attempt to convert it 
       
   117  * to octets (apply Canonical XML]) as described in the Reference Processing 
       
   118  * Model (section 4.3.3.2).]
       
   119  *
       
   120  * The output of this transform is an octet stream. The processing rules for 
       
   121  * the XSL style sheet or transform element are stated in the XSLT specification
       
   122  * [XSLT]. We RECOMMEND that XSLT transform authors use an output method of xml 
       
   123  * for XML and HTML. As XSLT implementations do not produce consistent 
       
   124  * serializations of their output, we further RECOMMEND inserting a transform 
       
   125  * after the XSLT transform to canonicalize the output. These steps will help 
       
   126  * to ensure interoperability of the resulting signatures among applications 
       
   127  * that support the XSLT transform. Note that if the output is actually HTML, 
       
   128  * then the result of these steps is logically equivalent [XHTML].
       
   129  *
       
   130  * Returns pointer to XSLT transform klass.
       
   131  */
       
   132 xmlSecTransformId 
       
   133 xmlSecTransformXsltGetKlass(void) {
       
   134     return(&xmlSecXsltKlass);
       
   135 }
       
   136     
       
   137 static int 
       
   138 xmlSecXsltInitialize(xmlSecTransformPtr transform) {    
       
   139     xmlSecXsltCtxPtr ctx;
       
   140     
       
   141     xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXsltId), -1);
       
   142     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecXsltSize), -1);
       
   143 
       
   144     ctx = xmlSecXsltGetCtx(transform);
       
   145     xmlSecAssert2(ctx != NULL, -1);
       
   146     
       
   147     /* initialize context */
       
   148     memset(ctx, 0, sizeof(xmlSecXsltCtx));
       
   149     return(0);
       
   150 }
       
   151 
       
   152 static void
       
   153 xmlSecXsltFinalize(xmlSecTransformPtr transform) {
       
   154     xmlSecXsltCtxPtr ctx;
       
   155 
       
   156     xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecTransformXsltId));
       
   157     xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecXsltSize));
       
   158 
       
   159     ctx = xmlSecXsltGetCtx(transform);
       
   160     xmlSecAssert(ctx != NULL);
       
   161     
       
   162     if(ctx->xslt != NULL) {
       
   163 	xsltFreeStylesheet(ctx->xslt);
       
   164     }
       
   165     if(ctx->parserCtx != NULL) {
       
   166 	xmlFreeParserCtxt(ctx->parserCtx);
       
   167     }
       
   168     memset(ctx, 0, sizeof(xmlSecXsltCtx));
       
   169 }
       
   170 
       
   171 /**
       
   172  * xmlSecXsltReadNode:
       
   173  */
       
   174 static int
       
   175 xmlSecXsltReadNode(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
       
   176     xmlSecXsltCtxPtr ctx;
       
   177     xmlBufferPtr buffer;
       
   178     xmlDocPtr doc;
       
   179     xmlNodePtr cur;
       
   180     
       
   181     xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXsltId), -1);
       
   182     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecXsltSize), -1);
       
   183     xmlSecAssert2(node != NULL, -1);    
       
   184     xmlSecAssert2(transformCtx != NULL, -1);    
       
   185 
       
   186     ctx = xmlSecXsltGetCtx(transform);
       
   187     xmlSecAssert2(ctx != NULL, -1);
       
   188     xmlSecAssert2(ctx->xslt == NULL, -1);
       
   189 
       
   190     /* read content in the buffer */    
       
   191     buffer = xmlBufferCreate();
       
   192     if(buffer == NULL) {
       
   193 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   194 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   195 		    "xmlBufferCreate",
       
   196 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   197 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   198 	return(-1);
       
   199     }    
       
   200     cur = node->children;
       
   201     while(cur != NULL) {
       
   202 	xmlNodeDump(buffer, cur->doc, cur, 0, 0);
       
   203 	cur = cur->next;
       
   204     }
       
   205     
       
   206     /* parse the buffer */
       
   207     doc = xmlSecParseMemory(xmlBufferContent(buffer), 
       
   208 			     xmlBufferLength(buffer), 1);
       
   209     if(doc == NULL) {
       
   210 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   211 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   212 		    "xmlSecParseMemory",
       
   213 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   214 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   215 	xmlBufferFree(buffer);
       
   216 	return(-1);
       
   217     }
       
   218 
       
   219     /* pre-process stylesheet */    
       
   220     ctx->xslt = xsltParseStylesheetDoc(doc);
       
   221     if(ctx->xslt == NULL) {
       
   222 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   223 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   224 		    "xsltParseStylesheetDoc",
       
   225 		    XMLSEC_ERRORS_R_XSLT_FAILED,
       
   226 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   227 	/* after parsing stylesheet doc is assigned
       
   228 	 * to it and will be freed by xsltFreeStylesheet() */    
       
   229 	xmlFreeDoc(doc);
       
   230 	xmlBufferFree(buffer);
       
   231 	return(-1);
       
   232     }
       
   233     
       
   234     xmlBufferFree(buffer);
       
   235     return(0);
       
   236 }
       
   237 
       
   238 static int 
       
   239 xmlSecXsltPushBin(xmlSecTransformPtr transform, const xmlSecByte* data,
       
   240 				xmlSecSize dataSize, int final, xmlSecTransformCtxPtr transformCtx) {
       
   241     xmlSecXsltCtxPtr ctx;
       
   242     int ret;
       
   243     
       
   244     xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXsltId), -1);
       
   245     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecXsltSize), -1);
       
   246     xmlSecAssert2(transformCtx != NULL, -1);
       
   247 
       
   248     ctx = xmlSecXsltGetCtx(transform);
       
   249     xmlSecAssert2(ctx != NULL, -1);
       
   250     xmlSecAssert2(ctx->xslt != NULL, -1);
       
   251 
       
   252     /* check/update current transform status */
       
   253     if(transform->status == xmlSecTransformStatusNone) {
       
   254 	xmlSecAssert2(ctx->parserCtx == NULL, -1);
       
   255 	
       
   256 	ctx->parserCtx = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
       
   257 	if(ctx->parserCtx == NULL) {
       
   258 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   259 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   260 			"xmlCreatePushParserCtxt",
       
   261 		        XMLSEC_ERRORS_R_XML_FAILED,
       
   262 			XMLSEC_ERRORS_NO_MESSAGE);
       
   263 	    return(-1);
       
   264 	}
       
   265 
       
   266         /* required for c14n! */
       
   267 	ctx->parserCtx->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS; 
       
   268 	ctx->parserCtx->replaceEntities = 1;
       
   269 
       
   270 	transform->status = xmlSecTransformStatusWorking;
       
   271     } else if(transform->status == xmlSecTransformStatusFinished) {
       
   272 	return(0);
       
   273     } else if(transform->status != xmlSecTransformStatusWorking) {
       
   274 	xmlSecError(XMLSEC_ERRORS_HERE, 
       
   275 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   276 		    NULL,
       
   277 		    XMLSEC_ERRORS_R_INVALID_STATUS,
       
   278 		    "status=%d", transform->status);
       
   279 	return(-1);
       
   280     }
       
   281     xmlSecAssert2(transform->status == xmlSecTransformStatusWorking, -1);
       
   282     xmlSecAssert2(ctx->parserCtx != NULL, -1);
       
   283     
       
   284     /* push data to the input buffer */
       
   285     if((data != NULL) && (dataSize > 0)) {
       
   286 	ret = xmlParseChunk(ctx->parserCtx, (const char*)data, dataSize, 0);
       
   287 	if(ret != 0) {
       
   288 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   289 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   290 			"xmlParseChunk",
       
   291 			XMLSEC_ERRORS_R_XML_FAILED,
       
   292 			"size=%d", dataSize);
       
   293 	    return(-1);
       
   294 	}	
       
   295     }    
       
   296     
       
   297     /* finish parsing, apply xslt transforms and push to next in the chain */
       
   298     if(final != 0) {
       
   299         xmlDocPtr docIn;
       
   300         xmlDocPtr docOut;
       
   301         xmlOutputBufferPtr output;
       
   302 
       
   303 	/* finalize */
       
   304 	ret = xmlParseChunk(ctx->parserCtx, NULL, 0, 1);
       
   305 	if((ret != 0) || (ctx->parserCtx->myDoc == NULL)) {
       
   306 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   307 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   308 			"xmlParseChunk",
       
   309 			XMLSEC_ERRORS_R_XML_FAILED,
       
   310 			XMLSEC_ERRORS_NO_MESSAGE);
       
   311 	    return(-1);
       
   312 	}	
       
   313 
       
   314 	docIn = ctx->parserCtx->myDoc;
       
   315 	ctx->parserCtx->myDoc = NULL;
       
   316 
       
   317 	docOut = xsltApplyStylesheet(ctx->xslt, docIn, NULL);
       
   318 	if(docOut == NULL) {
       
   319 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   320 		        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   321 			"xsltApplyStylesheet",
       
   322 			XMLSEC_ERRORS_R_XSLT_FAILED,
       
   323 			XMLSEC_ERRORS_NO_MESSAGE);
       
   324 	    xmlFreeDoc(docIn);
       
   325 	    return(-1);
       
   326 	}
       
   327 	xmlFreeDoc(docIn);
       
   328     
       
   329 	if(transform->next != NULL) {
       
   330 	    output = xmlSecTransformCreateOutputBuffer(transform->next, transformCtx);
       
   331 	    if(output == NULL) {
       
   332 		xmlSecError(XMLSEC_ERRORS_HERE,
       
   333 		    	    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   334 			    "xmlSecTransformCreateOutputBuffer",
       
   335 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   336 			    XMLSEC_ERRORS_NO_MESSAGE);
       
   337 		xmlFreeDoc(docOut);
       
   338 		return(-1);
       
   339 	    }
       
   340 	} else {
       
   341 	    output = xmlSecBufferCreateOutputBuffer(&(transform->outBuf));
       
   342 	    if(output == NULL) {
       
   343 		xmlSecError(XMLSEC_ERRORS_HERE,
       
   344 			    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   345 			    "xmlSecBufferCreateOutputBuffer",
       
   346 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   347 			    XMLSEC_ERRORS_NO_MESSAGE);
       
   348 		xmlFreeDoc(docOut);
       
   349 		return(-1);
       
   350 	    }
       
   351 	}	
       
   352 
       
   353 	ret = xsltSaveResultTo(output, docOut, ctx->xslt);
       
   354 	if(ret < 0) {
       
   355 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   356 		        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   357 			"xsltSaveResultTo",
       
   358 			XMLSEC_ERRORS_R_XSLT_FAILED,
       
   359 			XMLSEC_ERRORS_NO_MESSAGE);
       
   360 	    xmlOutputBufferClose(output);
       
   361 	    xmlFreeDoc(docOut);
       
   362 	    return(-1);
       
   363 	}
       
   364 	ret = xmlOutputBufferClose(output);
       
   365 	if(ret < 0) {
       
   366 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   367 		        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   368 			"xmlOutputBufferClose",
       
   369 			XMLSEC_ERRORS_R_XML_FAILED,
       
   370 		        XMLSEC_ERRORS_NO_MESSAGE);
       
   371 	    xmlFreeDoc(docOut);
       
   372 	    return(-1);
       
   373 	}
       
   374 	xmlFreeDoc(docOut);
       
   375 
       
   376 	transform->status = xmlSecTransformStatusFinished;
       
   377     }
       
   378 
       
   379     return(0);
       
   380 }
       
   381 
       
   382 static int 
       
   383 xmlSecXsltExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
       
   384     xmlSecXsltCtxPtr ctx;
       
   385     xmlSecBufferPtr in, out;
       
   386     xmlSecSize inSize, outSize;
       
   387     int ret;
       
   388 
       
   389     xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXsltId), -1);
       
   390     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecXsltSize), -1);
       
   391     xmlSecAssert2(transformCtx != NULL, -1);
       
   392 
       
   393     ctx = xmlSecXsltGetCtx(transform);
       
   394     xmlSecAssert2(ctx != NULL, -1);
       
   395     xmlSecAssert2(ctx->xslt != NULL, -1);
       
   396 
       
   397     in = &(transform->inBuf);
       
   398     out = &(transform->outBuf);
       
   399     inSize = xmlSecBufferGetSize(in);
       
   400     outSize = xmlSecBufferGetSize(out);    
       
   401     
       
   402     if(transform->status == xmlSecTransformStatusNone) {
       
   403 	transform->status = xmlSecTransformStatusWorking;
       
   404     } 
       
   405     
       
   406     if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
       
   407 	/* just do nothing */
       
   408 	xmlSecAssert2(outSize == 0, -1);
       
   409 
       
   410     } else  if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
       
   411 	xmlSecAssert2(outSize == 0, -1);
       
   412 
       
   413 	ret = xmlSecXslProcess(in, out, ctx->xslt);
       
   414 	if(ret < 0) {
       
   415 	    xmlSecError(XMLSEC_ERRORS_HERE, 
       
   416 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   417 			"xmlSecXslProcess",
       
   418 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   419 			XMLSEC_ERRORS_NO_MESSAGE);
       
   420 	    return(-1);
       
   421 	}
       
   422 	
       
   423 	ret = xmlSecBufferRemoveHead(in, inSize);
       
   424 	if(ret < 0) {
       
   425 	    xmlSecError(XMLSEC_ERRORS_HERE, 
       
   426 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   427 			"xmlSecBufferRemoveHead",
       
   428 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   429 			"size=%d", inSize);
       
   430 	    return(-1);
       
   431 	}
       
   432 	
       
   433 	transform->status = xmlSecTransformStatusFinished;
       
   434     } else if(transform->status == xmlSecTransformStatusFinished) {
       
   435 	/* the only way we can get here is if there is no input */
       
   436 	xmlSecAssert2(inSize == 0, -1);
       
   437     } else {
       
   438 	xmlSecError(XMLSEC_ERRORS_HERE, 
       
   439 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   440 		    NULL,
       
   441 		    XMLSEC_ERRORS_R_INVALID_STATUS,
       
   442 		    "status=%d", transform->status);
       
   443 	return(-1);
       
   444     }
       
   445     return(0);
       
   446 }
       
   447 
       
   448 static int 
       
   449 xmlSecXslProcess(xmlSecBufferPtr in, xmlSecBufferPtr out,  xsltStylesheetPtr stylesheet) {
       
   450     xmlDocPtr docIn = NULL;
       
   451     xmlDocPtr docOut = NULL;
       
   452     xmlOutputBufferPtr output = NULL;
       
   453     int res = -1;
       
   454     int ret;
       
   455 
       
   456     xmlSecAssert2(in != NULL, -1);
       
   457     xmlSecAssert2(out != NULL, -1);
       
   458     xmlSecAssert2(stylesheet != NULL, -1);
       
   459 
       
   460     docIn = xmlSecParseMemory(xmlSecBufferGetData(in), xmlSecBufferGetSize(in), 1);
       
   461     if(docIn == NULL) {
       
   462 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   463 		    NULL,
       
   464 		    "xmlSecParseMemory",
       
   465 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   466 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   467 	goto done;	
       
   468     }
       
   469 
       
   470     docOut = xsltApplyStylesheet(stylesheet, docIn, NULL);
       
   471     if(docOut == NULL) {
       
   472 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   473 		    NULL,
       
   474 		    "xsltApplyStylesheet",
       
   475 		    XMLSEC_ERRORS_R_XSLT_FAILED,
       
   476 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   477 	goto done;	
       
   478     }
       
   479 
       
   480     output = xmlSecBufferCreateOutputBuffer(out);
       
   481     if(output == NULL) {
       
   482 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   483 		    NULL,
       
   484 		    "xmlSecBufferCreateOutputBuffer",
       
   485 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   486 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   487 	goto done;	
       
   488     }
       
   489 
       
   490     ret = xsltSaveResultTo(output, docOut, stylesheet);
       
   491     if(ret < 0) {
       
   492 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   493 		    NULL,
       
   494 		    "xsltSaveResultTo",
       
   495 		    XMLSEC_ERRORS_R_XSLT_FAILED,
       
   496 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   497 	goto done;	
       
   498     }
       
   499 
       
   500     ret = xmlOutputBufferClose(output);
       
   501     output = NULL;
       
   502     if(ret < 0) {
       
   503 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   504 		    NULL,
       
   505 		    "xmlOutputBufferClose",
       
   506 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   507 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   508 	return(-1);
       
   509     }
       
   510 
       
   511     res = 0;
       
   512 
       
   513 done:   
       
   514     if(output != NULL) xmlOutputBufferClose(output);
       
   515     if(docIn != NULL) xmlFreeDoc(docIn);
       
   516     if(docOut != NULL) xmlFreeDoc(docOut);
       
   517     return(res);    
       
   518 }
       
   519 
       
   520 #endif /* XMLSEC_NO_XSLT */
       
   521