xmlsecurityengine/xmlsec/src/xmlsec_parser.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  * XML Parser transform and utility functions.
       
     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_globals.h"
       
    13 
       
    14 #include <stdlib.h>
       
    15 #include <string.h>
       
    16 
       
    17 #include <libxml2_tree.h>
       
    18 #include <libxml2_parser.h>
       
    19 #include <libxml2_parserinternals.h>
       
    20 
       
    21 #include "xmlsec_xmlsec.h"
       
    22 #include "xmlsec_xmltree.h"
       
    23 #include "xmlsec_keys.h"
       
    24 #include "xmlsec_transforms.h"
       
    25 #include "xmlsec_parser.h"
       
    26 #include "xmlsec_errors.h"
       
    27 
       
    28 /**************************************************************************
       
    29  *
       
    30  * Internal parser
       
    31  *
       
    32  *****************************************************************************/
       
    33 typedef struct _xmlSecParserCtx					xmlSecParserCtx, 
       
    34 								*xmlSecParserCtxPtr;
       
    35 struct _xmlSecParserCtx {
       
    36     xmlParserCtxtPtr 	parserCtx;
       
    37 };	    
       
    38 
       
    39 /**************************************************************************
       
    40  *
       
    41  * XML Parser transform 
       
    42  *
       
    43  * xmlSecParserCtx is located after xmlSecTransform
       
    44  * 
       
    45  ***************************************************************************/
       
    46 #define xmlSecParserSize	\
       
    47     (sizeof(xmlSecTransform) + sizeof(xmlSecParserCtx))	
       
    48 #define xmlSecParserGetCtx(transform) \
       
    49     ((xmlSecTransformCheckSize((transform), xmlSecParserSize)) ? \
       
    50 	((xmlSecParserCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) : \
       
    51 	(xmlSecParserCtxPtr)NULL)	    
       
    52 
       
    53 static int		xmlSecParserInitialize			(xmlSecTransformPtr transform);
       
    54 static void		xmlSecParserFinalize			(xmlSecTransformPtr transform);
       
    55 static int 		xmlSecParserPushBin			(xmlSecTransformPtr transform, 
       
    56 								 const xmlSecByte* data,
       
    57 								 xmlSecSize dataSize,
       
    58 								 int final,
       
    59 							         xmlSecTransformCtxPtr transformCtx);
       
    60 static int 		xmlSecParserPopXml			(xmlSecTransformPtr transform, 
       
    61 								 xmlSecNodeSetPtr* nodes,
       
    62 								 xmlSecTransformCtxPtr transformCtx);
       
    63 
       
    64 static xmlSecTransformKlass xmlSecParserKlass = {
       
    65     /* klass/object sizes */
       
    66     sizeof(xmlSecTransformKlass),		/* xmlSecSize klassSize */
       
    67     xmlSecParserSize,				/* xmlSecSize objSize */
       
    68 
       
    69     BAD_CAST "xml-parser",			/* const xmlChar* name; */
       
    70     NULL,					/* const xmlChar* href; */
       
    71     xmlSecTransformUsageDSigTransform,		/* xmlSecTransformUsage	usage; */
       
    72     
       
    73     xmlSecParserInitialize,			/* xmlSecTransformInitializeMethod initialize; */
       
    74     xmlSecParserFinalize,			/* xmlSecTransformFinalizeMethod finalize; */
       
    75     NULL,					/* xmlSecTransformNodeReadMethod readNode; */
       
    76     NULL,					/* xmlSecTransformNodeWriteMethod writeNode; */
       
    77     NULL,					/* xmlSecTransformSetKeyReqMethod setKeyReq; */
       
    78     NULL,					/* xmlSecTransformSetKeyMethod setKey; */
       
    79     NULL,					/* xmlSecTransformValidateMethod validate; */
       
    80     xmlSecTransformDefaultGetDataType,		/* xmlSecTransformGetDataTypeMethod getDataType; */
       
    81     xmlSecParserPushBin,		/* xmlSecTransformPushBinMethod pushBin; */
       
    82     NULL,					/* xmlSecTransformPopBinMethod popBin; */
       
    83     NULL,					/* xmlSecTransformPushXmlMethod pushXml; */
       
    84     xmlSecParserPopXml,		/* xmlSecTransformPopXmlMethod popXml; */
       
    85     NULL,					/* xmlSecTransformExecuteMethod execute; */
       
    86 
       
    87     NULL,					/* void* reserved0; */
       
    88     NULL,					/* void* reserved1; */
       
    89 };
       
    90 
       
    91 /**
       
    92  * xmlSecTransformXmlParserGetKlass:
       
    93  *
       
    94  * The XML parser transform.
       
    95  *
       
    96  * Returns XML parser transform klass.
       
    97  */
       
    98 EXPORT_C
       
    99 xmlSecTransformId 
       
   100 xmlSecTransformXmlParserGetKlass(void) {
       
   101     return(&xmlSecParserKlass);
       
   102 }
       
   103 
       
   104 static int 
       
   105 xmlSecParserInitialize(xmlSecTransformPtr transform) {    
       
   106     xmlSecParserCtxPtr ctx;
       
   107     
       
   108     xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXmlParserId), -1);
       
   109     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecParserSize), -1);
       
   110 
       
   111     ctx = xmlSecParserGetCtx(transform);
       
   112     xmlSecAssert2(ctx != NULL, -1);
       
   113     
       
   114     /* initialize context */
       
   115     memset(ctx, 0, sizeof(xmlSecParserCtx));
       
   116     return(0);
       
   117 }
       
   118 
       
   119 static void
       
   120 xmlSecParserFinalize(xmlSecTransformPtr transform) {
       
   121     xmlSecParserCtxPtr ctx;
       
   122 
       
   123     xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecTransformXmlParserId));
       
   124     xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecParserSize));
       
   125 
       
   126     ctx = xmlSecParserGetCtx(transform);
       
   127     xmlSecAssert(ctx != NULL);
       
   128     
       
   129     if(ctx->parserCtx != NULL) {
       
   130 	xmlFreeParserCtxt(ctx->parserCtx);
       
   131     }
       
   132     memset(ctx, 0, sizeof(xmlSecParserCtx));
       
   133 }
       
   134 
       
   135 static int 
       
   136 xmlSecParserPushBin(xmlSecTransformPtr transform, const xmlSecByte* data,
       
   137 				xmlSecSize dataSize, int final, xmlSecTransformCtxPtr transformCtx) {
       
   138     xmlSecParserCtxPtr ctx;
       
   139     int ret;
       
   140     
       
   141     xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXmlParserId), -1);
       
   142     xmlSecAssert2(transformCtx != NULL, -1);
       
   143 
       
   144     ctx = xmlSecParserGetCtx(transform);
       
   145     xmlSecAssert2(ctx != NULL, -1);
       
   146 
       
   147     /* check/update current transform status */
       
   148     if(transform->status == xmlSecTransformStatusNone) {
       
   149 	xmlSecAssert2(ctx->parserCtx == NULL, -1);
       
   150     
       
   151 	ctx->parserCtx = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
       
   152 	if(ctx->parserCtx == NULL) {
       
   153 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   154 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   155 			"xmlCreatePushParserCtxt",
       
   156 		        XMLSEC_ERRORS_R_XML_FAILED,
       
   157 			XMLSEC_ERRORS_NO_MESSAGE);
       
   158 	    return(-1);
       
   159 	}
       
   160 
       
   161         /* required for c14n! */
       
   162 	ctx->parserCtx->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS; 
       
   163 	ctx->parserCtx->replaceEntities = 1;
       
   164 
       
   165 	transform->status = xmlSecTransformStatusWorking;
       
   166     } else if(transform->status == xmlSecTransformStatusFinished) {
       
   167 	return(0);
       
   168     } else if(transform->status != xmlSecTransformStatusWorking) {
       
   169 	xmlSecError(XMLSEC_ERRORS_HERE, 
       
   170 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   171 		    NULL,
       
   172 		    XMLSEC_ERRORS_R_INVALID_STATUS,
       
   173 		    "status=%d", transform->status);
       
   174 	return(-1);
       
   175     }
       
   176     xmlSecAssert2(transform->status == xmlSecTransformStatusWorking, -1);
       
   177     xmlSecAssert2(ctx->parserCtx != NULL, -1);
       
   178     
       
   179     /* push data to the input buffer */
       
   180     if((data != NULL) && (dataSize > 0)) {
       
   181 	ret = xmlParseChunk(ctx->parserCtx, (const char*)data, dataSize, 0);
       
   182 	if(ret != 0) {
       
   183 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   184 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   185 			"xmlParseChunk",
       
   186 			XMLSEC_ERRORS_R_XML_FAILED,
       
   187 			"size=%d", dataSize);
       
   188 	    return(-1);
       
   189 	}	
       
   190     }    
       
   191     
       
   192     /* finish parsing and push to next in the chain */
       
   193     if(final != 0) {
       
   194 	ret = xmlParseChunk(ctx->parserCtx, NULL, 0, 1);
       
   195 	if((ret != 0) || (ctx->parserCtx->myDoc == NULL)) {
       
   196 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   197 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   198 			"xmlParseChunk",
       
   199 			XMLSEC_ERRORS_R_XML_FAILED,
       
   200 			XMLSEC_ERRORS_NO_MESSAGE);
       
   201 	    return(-1);
       
   202 	}	
       
   203 
       
   204 	transform->outNodes = xmlSecNodeSetCreate(ctx->parserCtx->myDoc, 
       
   205 						  NULL, xmlSecNodeSetTree);
       
   206 	if(transform->outNodes == NULL) {
       
   207 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   208 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   209 			"xmlSecNodeSetCreate",
       
   210 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   211 			XMLSEC_ERRORS_NO_MESSAGE);
       
   212 	    xmlFreeDoc(ctx->parserCtx->myDoc);
       
   213 	    ctx->parserCtx->myDoc = NULL;
       
   214 	    return(-1);
       
   215 	}
       
   216 	xmlSecNodeSetDocDestroy(transform->outNodes); /* this node set "owns" the doc pointer */
       
   217 	ctx->parserCtx->myDoc = NULL;
       
   218 	
       
   219 	/* push result to the next transform (if exist) */
       
   220 	if(transform->next != NULL) {
       
   221 	    ret = xmlSecTransformPushXml(transform->next, transform->outNodes, transformCtx);
       
   222 	    if(ret < 0) {
       
   223 		xmlSecError(XMLSEC_ERRORS_HERE,
       
   224 			    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   225 			    "xmlSecTransformPushXml",
       
   226 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   227 			    XMLSEC_ERRORS_NO_MESSAGE);
       
   228 		return(-1);
       
   229 	    }
       
   230 	}        
       
   231 	
       
   232 	transform->status = xmlSecTransformStatusFinished;
       
   233     }
       
   234 
       
   235     return(0);
       
   236 }
       
   237 
       
   238 static int 
       
   239 xmlSecParserPopXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr* nodes,
       
   240 			       xmlSecTransformCtxPtr transformCtx) {
       
   241     xmlSecParserCtxPtr ctx;
       
   242     xmlParserInputBufferPtr buf;
       
   243     xmlParserInputPtr input;
       
   244     xmlParserCtxtPtr ctxt;
       
   245     xmlDocPtr doc;
       
   246     int ret;
       
   247     
       
   248     xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXmlParserId), -1);
       
   249     xmlSecAssert2(nodes != NULL, -1);    
       
   250     xmlSecAssert2(transformCtx != NULL, -1);
       
   251 
       
   252     ctx = xmlSecParserGetCtx(transform);
       
   253     xmlSecAssert2(ctx != NULL, -1);
       
   254 
       
   255     /* check/update current transform status */
       
   256     switch(transform->status) {
       
   257     case xmlSecTransformStatusNone:
       
   258 	transform->status = xmlSecTransformStatusWorking;
       
   259 	break;
       
   260     case xmlSecTransformStatusWorking:
       
   261 	/* just do nothing */
       
   262 	break;
       
   263     case xmlSecTransformStatusFinished:
       
   264 	(*nodes) = NULL;
       
   265 	return(0);
       
   266     default:
       
   267 	xmlSecError(XMLSEC_ERRORS_HERE, 
       
   268 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   269 		    NULL,
       
   270 		    XMLSEC_ERRORS_R_INVALID_STATUS,
       
   271 		    "status=%d", transform->status);
       
   272 	return(-1);
       
   273     }
       
   274     xmlSecAssert2(transform->status == xmlSecTransformStatusWorking, -1);
       
   275     
       
   276     /* prepare parser context */
       
   277     if(transform->prev == NULL) {
       
   278 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   279 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   280 		    NULL,
       
   281 		    XMLSEC_ERRORS_R_INVALID_TRANSFORM,
       
   282 		    "prev transform is null");
       
   283 	return(-1);
       
   284     }
       
   285     
       
   286     buf = xmlSecTransformCreateInputBuffer(transform->prev, transformCtx);
       
   287     if(buf == NULL) {
       
   288 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   289 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   290 		    "xmlSecTransformCreateInputBuffer",
       
   291 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   292 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   293 	return(-1);
       
   294     }
       
   295     
       
   296     ctxt = xmlNewParserCtxt();
       
   297     if (ctxt == NULL) {
       
   298 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   299 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   300 		    "xmlNewParserCtxt",
       
   301 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   302 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   303 	xmlFreeParserInputBuffer(buf);
       
   304 	return(-1);
       
   305     }
       
   306     
       
   307     input = xmlNewIOInputStream(ctxt, buf, XML_CHAR_ENCODING_NONE);
       
   308     if(input == NULL) {
       
   309 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   310 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   311 		    "xmlNewParserCtxt",
       
   312 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   313 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   314 	xmlFreeParserCtxt(ctxt);
       
   315 	xmlFreeParserInputBuffer(buf);
       
   316 	return(-1);
       
   317     }
       
   318     
       
   319     ret = inputPush(ctxt, input);
       
   320     if(input == NULL) {
       
   321 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   322 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   323 		    "inputPush",
       
   324 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   325 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   326 	xmlFreeInputStream(input);
       
   327 	xmlFreeParserCtxt(ctxt);
       
   328 	return(-1);
       
   329     }
       
   330 
       
   331     /* required for c14n! */
       
   332     ctxt->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS; 
       
   333     ctxt->replaceEntities = 1;
       
   334 
       
   335     /* finaly do the parsing */
       
   336     ret = xmlParseDocument(ctxt);
       
   337     if(ret < 0) {
       
   338 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   339 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   340 		    "xmlParseDocument",
       
   341 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   342 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   343 	if(ctxt->myDoc != NULL) {
       
   344 	    xmlFreeDoc(ctxt->myDoc);
       
   345 	    ctxt->myDoc = NULL;
       
   346 	}
       
   347 	xmlFreeParserCtxt(ctxt);
       
   348 	return(-1);
       
   349     }
       
   350     
       
   351     /* remember the result and free parsing context */
       
   352     doc = ctxt->myDoc;
       
   353     ctxt->myDoc = NULL;
       
   354     xmlFreeParserCtxt(ctxt);    
       
   355 
       
   356     /* return result to the caller */
       
   357     (*nodes) = xmlSecNodeSetCreate(doc, NULL, xmlSecNodeSetTree);
       
   358     if((*nodes) == NULL) {
       
   359 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   360 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   361 		    "xmlSecNodeSetCreate",
       
   362 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   363 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   364 	xmlFreeDoc(doc);
       
   365 	return(-1);
       
   366     }	
       
   367     xmlSecNodeSetDocDestroy((*nodes)); /* this node set "owns" the doc pointer */
       
   368     transform->status = xmlSecTransformStatusFinished;
       
   369     return(0);
       
   370 }
       
   371 
       
   372 /**************************************************************************
       
   373  *
       
   374  * XML Parser functions
       
   375  *
       
   376  *************************************************************************/
       
   377 typedef struct _xmlSecExtMemoryParserCtx {
       
   378     const xmlSecByte 	*prefix; 
       
   379     xmlSecSize 			prefixSize;
       
   380     const xmlSecByte 	*buffer;
       
   381     xmlSecSize			bufferSize;
       
   382     const xmlSecByte 	*postfix;
       
   383     xmlSecSize 			postfixSize;
       
   384 } xmlSecExtMemoryParserCtx, *xmlSecExtMemoryParserCtxPtr;
       
   385 
       
   386 /** 
       
   387  * xmlSecParseFile:
       
   388  * @filename: 		the filename.
       
   389  *
       
   390  * Loads XML Doc from file @filename. We need a special version because of 
       
   391  * c14n issue. The code is copied from xmlSAXParseFileWithData() function.
       
   392  *
       
   393  * Returns pointer to the loaded XML document or NULL if an error occurs.
       
   394  */
       
   395 EXPORT_C
       
   396 xmlDocPtr
       
   397 xmlSecParseFile(const char *filename) {
       
   398     xmlDocPtr ret;
       
   399     xmlParserCtxtPtr ctxt;
       
   400     char *directory = NULL;
       
   401     
       
   402     xmlSecAssert2(filename != NULL, NULL);
       
   403 
       
   404     xmlInitParser();
       
   405     ctxt = xmlCreateFileParserCtxt(filename);
       
   406     if (ctxt == NULL) {
       
   407 	return(NULL);
       
   408     }
       
   409 
       
   410     if ((ctxt->directory == NULL) && (directory == NULL))
       
   411         directory = xmlParserGetDirectory(filename);
       
   412     if ((ctxt->directory == NULL) && (directory != NULL))
       
   413         ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
       
   414 
       
   415     /* required for c14n! */
       
   416     ctxt->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS; 
       
   417     ctxt->replaceEntities = 1;
       
   418     
       
   419     xmlParseDocument(ctxt);
       
   420 
       
   421     if(ctxt->wellFormed) { 
       
   422 	ret = ctxt->myDoc;
       
   423     } else {
       
   424        ret = NULL;
       
   425        xmlFreeDoc(ctxt->myDoc);
       
   426        ctxt->myDoc = NULL;
       
   427     }
       
   428     xmlFreeParserCtxt(ctxt);    
       
   429     return(ret);
       
   430     
       
   431 }
       
   432 
       
   433 /**
       
   434  * xmlSecParseMemoryExt:
       
   435  * @prefix: 		the first part of the input.
       
   436  * @prefixSize: 	the size of the first part of the input.
       
   437  * @buffer: 		the second part of the input.
       
   438  * @bufferSize: 	the size of the second part of the input.
       
   439  * @postfix: 		the third part of the input.
       
   440  * @postfixSize: 	the size of the third part of the input.
       
   441  *
       
   442  * Loads XML Doc from 3 chunks of memory: @prefix, @buffer and @postfix. 
       
   443  *
       
   444  * Returns pointer to the loaded XML document or NULL if an error occurs.
       
   445  */
       
   446 EXPORT_C
       
   447 xmlDocPtr
       
   448 xmlSecParseMemoryExt(const xmlSecByte *prefix, xmlSecSize prefixSize,
       
   449 		     const xmlSecByte *buffer, xmlSecSize bufferSize, 
       
   450 		     const xmlSecByte *postfix, xmlSecSize postfixSize) {
       
   451     xmlParserCtxtPtr ctxt = NULL;
       
   452     xmlDocPtr doc = NULL;
       
   453     int ret;
       
   454     
       
   455     /* create context */
       
   456     ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
       
   457     if(ctxt == NULL) {
       
   458 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   459 		    NULL,
       
   460 		    "xmlCreatePushParserCtxt",
       
   461 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   462 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   463 	goto done;
       
   464     }
       
   465 
       
   466     /* required for c14n! */
       
   467     ctxt->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS; 
       
   468     ctxt->replaceEntities = 1;
       
   469 
       
   470     /* prefix */
       
   471     if((prefix != NULL) && (prefixSize > 0)) {
       
   472         ret = xmlParseChunk(ctxt, (const char*)prefix, prefixSize, 0);
       
   473 	if(ret != 0) {
       
   474 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   475 			NULL,
       
   476 			"xmlParseChunk",
       
   477 			XMLSEC_ERRORS_R_XML_FAILED,
       
   478 			"prefixSize=%d", prefixSize);
       
   479 	    goto done;
       
   480 	}
       
   481     }	
       
   482 
       
   483     /* buffer */
       
   484     if((buffer != NULL) && (bufferSize > 0)) {
       
   485         ret = xmlParseChunk(ctxt, (const char*)buffer, bufferSize, 0);
       
   486 	if(ret != 0) {
       
   487 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   488 			NULL,
       
   489 			"xmlParseChunk",
       
   490 			XMLSEC_ERRORS_R_XML_FAILED,
       
   491 			"bufferSize=%d", bufferSize);
       
   492 	    goto done;
       
   493 	}
       
   494     }	
       
   495 
       
   496     /* postfix */
       
   497     if((postfix != NULL) && (postfixSize > 0)) {
       
   498         ret = xmlParseChunk(ctxt, (const char*)postfix, postfixSize, 0);
       
   499 	if(ret != 0) {
       
   500 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   501 			NULL,
       
   502 			"xmlParseChunk",
       
   503 			XMLSEC_ERRORS_R_XML_FAILED,
       
   504 			"postfixSize=%d", postfixSize);
       
   505 	    goto done;
       
   506 	}
       
   507     }	
       
   508 
       
   509     /* finishing */
       
   510     ret = xmlParseChunk(ctxt, NULL, 0, 1);
       
   511     if((ret != 0) || (ctxt->myDoc == NULL)) {
       
   512 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   513 		    NULL,
       
   514 		    "xmlParseChunk",
       
   515 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   516 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   517 	goto done;
       
   518     }	
       
   519     doc = ctxt->myDoc;
       
   520 
       
   521 done:
       
   522     if(ctxt != NULL) {
       
   523 	xmlFreeParserCtxt(ctxt);
       
   524     }
       
   525     return(doc);
       
   526 }
       
   527 
       
   528 
       
   529 /**
       
   530  * xmlSecParseMemory:
       
   531  * @buffer: 		the input buffer.
       
   532  * @size: 		the input buffer size.
       
   533  * @recovery: 		the flag.
       
   534  *
       
   535  * Loads XML Doc from memory. We need a special version because of 
       
   536  * c14n issue. The code is copied from xmlSAXParseMemory() function.
       
   537  *
       
   538  * Returns pointer to the loaded XML document or NULL if an error occurs.
       
   539  */
       
   540 EXPORT_C
       
   541 xmlDocPtr
       
   542 xmlSecParseMemory(const xmlSecByte *buffer, xmlSecSize size, int recovery) {
       
   543     xmlDocPtr ret;
       
   544     xmlParserCtxtPtr ctxt;
       
   545 
       
   546     xmlSecAssert2(buffer != NULL, NULL);
       
   547     
       
   548     ctxt = xmlCreateMemoryParserCtxt((char*)buffer, size);
       
   549     if (ctxt == NULL) {
       
   550 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   551 		    NULL,
       
   552 		    "xmlCreateMemoryParserCtxt",
       
   553 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   554 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   555 	return(NULL);
       
   556     }
       
   557 
       
   558     /* required for c14n! */
       
   559     ctxt->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS; 
       
   560     ctxt->replaceEntities = 1;
       
   561 
       
   562     xmlParseDocument(ctxt);
       
   563 
       
   564     if((ctxt->wellFormed) || recovery) {
       
   565 	ret = ctxt->myDoc; 
       
   566     } else {
       
   567        ret = NULL;
       
   568        xmlFreeDoc(ctxt->myDoc);
       
   569        ctxt->myDoc = NULL;
       
   570     }
       
   571     xmlFreeParserCtxt(ctxt);    
       
   572     return(ret);
       
   573 }
       
   574