xmlsecurityengine/xmlsec/src/xmlsec_xpath.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  * XPath transform
       
     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_xpath.h>
       
    19 #include <libxml2_xpathinternals.h>
       
    20 #include <libxml2_xpointer.h>
       
    21 #include <libxml2_valid.h>
       
    22 #include <libxml2_globals.h>
       
    23 
       
    24 #include "xmlsec_xmlsec.h"
       
    25 #include "xmlsec_xmltree.h"
       
    26 #include "xmlsec_keys.h"
       
    27 #include "xmlsec_list.h"
       
    28 #include "xmlsec_transforms.h"
       
    29 #include "xmlsec_errors.h"
       
    30 
       
    31 
       
    32 /**************************************************************************
       
    33  *
       
    34  * xmlSecXPathHereFunction:
       
    35  * @ctxt:		the ponter to XPath context.
       
    36  * @nargs:		the arguments nubmer.
       
    37  *
       
    38  * The implementation of XPath "here()" function.
       
    39  * See xmlXPtrHereFunction() in xpointer.c. the only change is that 
       
    40  * we return NodeSet instead of NodeInterval.
       
    41  *
       
    42  *****************************************************************************/
       
    43 static void 
       
    44 xmlSecXPathHereFunction(xmlXPathParserContextPtr ctxt, int nargs) {
       
    45     CHECK_ARITY(0);
       
    46 
       
    47     if((ctxt == NULL) || (ctxt->context == NULL) || (ctxt->context->here == NULL)) {
       
    48 	XP_ERROR(XPTR_SYNTAX_ERROR);
       
    49     }
       
    50     valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->here));
       
    51 }
       
    52 
       
    53 /**************************************************************************
       
    54  *
       
    55  * XPath/XPointer data
       
    56  *
       
    57  *****************************************************************************/
       
    58 typedef struct _xmlSecXPathData			xmlSecXPathData,
       
    59 						*xmlSecXPathDataPtr;
       
    60 typedef enum {
       
    61     xmlSecXPathDataTypeXPath,
       
    62     xmlSecXPathDataTypeXPath2,
       
    63     xmlSecXPathDataTypeXPointer
       
    64 } xmlSecXPathDataType;
       
    65 
       
    66 struct _xmlSecXPathData {
       
    67     xmlSecXPathDataType			type;
       
    68     xmlXPathContextPtr			ctx;
       
    69     xmlChar*				expr;
       
    70     xmlSecNodeSetOp			nodeSetOp;
       
    71     xmlSecNodeSetType			nodeSetType;    
       
    72 };
       
    73 
       
    74 static xmlSecXPathDataPtr 	xmlSecXPathDataCreate		(xmlSecXPathDataType type);
       
    75 static void		  	xmlSecXPathDataDestroy		(xmlSecXPathDataPtr data);
       
    76 static int		  	xmlSecXPathDataSetExpr		(xmlSecXPathDataPtr data,
       
    77 								 const xmlChar* expr);
       
    78 static int 			xmlSecXPathDataRegisterNamespaces(xmlSecXPathDataPtr data, 
       
    79 								 xmlNodePtr node);
       
    80 static int		  	xmlSecXPathDataNodeRead		(xmlSecXPathDataPtr data,
       
    81 								 xmlNodePtr node);
       
    82 static xmlSecNodeSetPtr		xmlSecXPathDataExecute		(xmlSecXPathDataPtr data,
       
    83 								 xmlDocPtr doc,
       
    84 								 xmlNodePtr hereNode);
       
    85 
       
    86 static xmlSecXPathDataPtr  
       
    87 xmlSecXPathDataCreate(xmlSecXPathDataType type) {
       
    88     xmlSecXPathDataPtr data;
       
    89 
       
    90     data = (xmlSecXPathDataPtr) xmlMalloc(sizeof(xmlSecXPathData));
       
    91     if(data == NULL) {
       
    92 	xmlSecError(XMLSEC_ERRORS_HERE,
       
    93 		    NULL,
       
    94 		    NULL,
       
    95 		    XMLSEC_ERRORS_R_MALLOC_FAILED,
       
    96 		    "sizeof(xmlSecXPathData)=%d",
       
    97 		    sizeof(xmlSecXPathData));
       
    98 	return(NULL);
       
    99     }
       
   100     memset(data, 0, sizeof(xmlSecXPathData)); 
       
   101 
       
   102     data->type = type;
       
   103     data->nodeSetType = xmlSecNodeSetTree;
       
   104 
       
   105     /* create xpath or xpointer context */
       
   106     switch(data->type) {
       
   107     case xmlSecXPathDataTypeXPath:    
       
   108     case xmlSecXPathDataTypeXPath2:    
       
   109 	data->ctx = xmlXPathNewContext(NULL); /* we'll set doc in the context later */
       
   110 	if(data->ctx == NULL) {
       
   111 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   112 			NULL,
       
   113 			"xmlXPathNewContext",
       
   114 			XMLSEC_ERRORS_R_XML_FAILED,
       
   115 			XMLSEC_ERRORS_NO_MESSAGE);
       
   116 	    xmlSecXPathDataDestroy(data);
       
   117 	    return(NULL);
       
   118 	}
       
   119 	break;
       
   120     case xmlSecXPathDataTypeXPointer:    
       
   121 	data->ctx = xmlXPtrNewContext(NULL, NULL, NULL); /* we'll set doc in the context later */
       
   122 	if(data->ctx == NULL) {
       
   123 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   124 			NULL,
       
   125 			"xmlXPtrNewContext",
       
   126 			XMLSEC_ERRORS_R_XML_FAILED,
       
   127 			XMLSEC_ERRORS_NO_MESSAGE);
       
   128 	    xmlSecXPathDataDestroy(data);
       
   129 	    return(NULL);
       
   130 	}
       
   131 	break;
       
   132     }
       
   133 
       
   134     return(data);
       
   135 }
       
   136 
       
   137 static void				
       
   138 xmlSecXPathDataDestroy(xmlSecXPathDataPtr data) {
       
   139     xmlSecAssert(data != NULL);    
       
   140 
       
   141     if(data->expr != NULL) {
       
   142 	xmlFree(data->expr);
       
   143     }
       
   144     if(data->ctx != NULL) {
       
   145 	xmlXPathFreeContext(data->ctx);
       
   146     }
       
   147     memset(data, 0, sizeof(xmlSecXPathData));  
       
   148     xmlFree(data);
       
   149 }
       
   150 
       
   151 static int 
       
   152 xmlSecXPathDataSetExpr(xmlSecXPathDataPtr data, const xmlChar* expr) {
       
   153     xmlSecAssert2(data != NULL, -1);    
       
   154     xmlSecAssert2(data->expr == NULL, -1);
       
   155     xmlSecAssert2(data->ctx != NULL, -1);
       
   156     xmlSecAssert2(expr != NULL, -1);    
       
   157             
       
   158     data->expr = xmlStrdup(expr);
       
   159     if(data->expr == NULL) {
       
   160 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   161 		    NULL,
       
   162 		    NULL,
       
   163 		    XMLSEC_ERRORS_R_STRDUP_FAILED,
       
   164 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   165         return(-1);
       
   166     }
       
   167     return(0);
       
   168 }
       
   169 
       
   170 
       
   171 static int 
       
   172 xmlSecXPathDataRegisterNamespaces(xmlSecXPathDataPtr data, xmlNodePtr node) {
       
   173     xmlNodePtr cur;
       
   174     xmlNsPtr ns;
       
   175     int ret;
       
   176     
       
   177     xmlSecAssert2(data != NULL, -1);    
       
   178     xmlSecAssert2(data->ctx != NULL, -1);
       
   179     xmlSecAssert2(node != NULL, -1);
       
   180 
       
   181     /* register namespaces */
       
   182     for(cur = node; cur != NULL; cur = cur->parent) {
       
   183 	for(ns = cur->nsDef; ns != NULL; ns = ns->next) {
       
   184 	    /* check that we have no other namespace with same prefix already */
       
   185 	    if((ns->prefix != NULL) && (xmlXPathNsLookup(data->ctx, ns->prefix) == NULL)){
       
   186 	        ret = xmlXPathRegisterNs(data->ctx, ns->prefix, ns->href);
       
   187 		if(ret != 0) {
       
   188 		    xmlSecError(XMLSEC_ERRORS_HERE,
       
   189 				NULL,
       
   190 			        "xmlXPathRegisterNs",
       
   191 				XMLSEC_ERRORS_R_XML_FAILED,
       
   192 			        "href=%s;prefix=%s",
       
   193 			        xmlSecErrorsSafeString(ns->href),
       
   194 				xmlSecErrorsSafeString(ns->prefix)); 
       
   195 		    return(-1);
       
   196 		}
       
   197 	    }
       
   198 	}
       
   199     }
       
   200     
       
   201     return(0);
       
   202 }
       
   203 
       
   204 static int 
       
   205 xmlSecXPathDataNodeRead(xmlSecXPathDataPtr data, xmlNodePtr node) {
       
   206     int ret;
       
   207     
       
   208     xmlSecAssert2(data != NULL, -1);    
       
   209     xmlSecAssert2(data->expr == NULL, -1);
       
   210     xmlSecAssert2(data->ctx != NULL, -1);
       
   211     xmlSecAssert2(node != NULL, -1);
       
   212 
       
   213     ret = xmlSecXPathDataRegisterNamespaces (data, node);
       
   214     if(ret < 0) {
       
   215 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   216 		    NULL,
       
   217 		    "xmlSecXPathDataRegisterNamespaces",
       
   218 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   219 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   220         return(-1);
       
   221     }
       
   222     
       
   223     /* read node content and set expr */
       
   224     data->expr = xmlNodeGetContent(node);
       
   225     if(data->expr == NULL) {
       
   226 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   227 		    NULL,
       
   228 		    xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
       
   229 		    XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
       
   230 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   231         return(-1);
       
   232     }
       
   233     
       
   234     return(0);
       
   235 }
       
   236 
       
   237 static xmlSecNodeSetPtr
       
   238 xmlSecXPathDataExecute(xmlSecXPathDataPtr data, xmlDocPtr doc, xmlNodePtr hereNode) {
       
   239     xmlXPathObjectPtr xpathObj = NULL; 
       
   240     xmlSecNodeSetPtr nodes = NULL;
       
   241 
       
   242     xmlSecAssert2(data != NULL, NULL);    
       
   243     xmlSecAssert2(data->expr != NULL, NULL);
       
   244     xmlSecAssert2(data->ctx != NULL, NULL);
       
   245     xmlSecAssert2(doc != NULL, NULL);
       
   246     xmlSecAssert2(hereNode != NULL, NULL);
       
   247 
       
   248     /* do not forget to set the doc */
       
   249     data->ctx->doc = doc;
       
   250     
       
   251     /* here function works only on the same document */
       
   252     if(hereNode->doc == doc) {
       
   253 	xmlXPathRegisterFunc(data->ctx, (xmlChar *)"here", xmlSecXPathHereFunction);
       
   254 	data->ctx->here = hereNode;
       
   255 	data->ctx->xptr = 1;
       
   256     }
       
   257 
       
   258     /* execute xpath or xpointer expression */
       
   259     switch(data->type) {
       
   260     case xmlSecXPathDataTypeXPath:    
       
   261     case xmlSecXPathDataTypeXPath2:    
       
   262 	xpathObj = xmlXPathEvalExpression(data->expr, data->ctx);
       
   263 	if(xpathObj == NULL) {
       
   264 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   265 			NULL,
       
   266 			"xmlXPathEvalExpression",
       
   267 			XMLSEC_ERRORS_R_XML_FAILED,
       
   268 			"expr=%s", 
       
   269 			xmlSecErrorsSafeString(data->expr));
       
   270 	    return(NULL);
       
   271 	}
       
   272 	break;
       
   273     case xmlSecXPathDataTypeXPointer:    
       
   274 	xpathObj = xmlXPtrEval(data->expr, data->ctx);
       
   275 	if(xpathObj == NULL) {
       
   276 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   277 			NULL,
       
   278 			"xmlXPtrEval",
       
   279 			XMLSEC_ERRORS_R_XML_FAILED,
       
   280 			"expr=%s", 
       
   281 			xmlSecErrorsSafeString(data->expr));
       
   282 	    return(NULL);
       
   283 	}
       
   284 	break;
       
   285     }
       
   286     
       
   287     if (xpathObj != NULL) {
       
   288         nodes = xmlSecNodeSetCreate(doc, xpathObj->nodesetval, data->nodeSetType);
       
   289     }
       
   290     if(nodes == NULL) {
       
   291 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   292 		    NULL,
       
   293 		    "xmlSecNodeSetCreate",
       
   294 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   295 		    "type=%d", data->nodeSetType);
       
   296 	xmlXPathFreeObject(xpathObj);     
       
   297 	return(NULL);
       
   298     }
       
   299     xpathObj->nodesetval = NULL;
       
   300     xmlXPathFreeObject(xpathObj); 
       
   301     
       
   302     return(nodes);
       
   303 }
       
   304 
       
   305 
       
   306 /**************************************************************************
       
   307  *
       
   308  * XPath data list
       
   309  *
       
   310  *****************************************************************************/
       
   311 #define xmlSecXPathDataListId	\
       
   312 	xmlSecXPathDataListGetKlass()
       
   313 static xmlSecPtrListId 	xmlSecXPathDataListGetKlass		(void);
       
   314 static xmlSecNodeSetPtr	xmlSecXPathDataListExecute		(xmlSecPtrListPtr dataList,
       
   315 								 xmlDocPtr doc,
       
   316 								 xmlNodePtr hereNode,
       
   317 								 xmlSecNodeSetPtr nodes);
       
   318 
       
   319 static xmlSecPtrListKlass xmlSecXPathDataListKlass = {
       
   320     BAD_CAST "xpath-data-list",
       
   321     NULL,						/* xmlSecPtrDuplicateItemMethod duplicateItem; */
       
   322     (xmlSecPtrDestroyItemMethod)xmlSecXPathDataDestroy,	/* xmlSecPtrDestroyItemMethod destroyItem; */
       
   323     NULL,						/* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
       
   324     NULL,						/* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
       
   325 };
       
   326 
       
   327 static xmlSecPtrListId 
       
   328 xmlSecXPathDataListGetKlass(void) {
       
   329     return(&xmlSecXPathDataListKlass);
       
   330 }
       
   331 
       
   332 static xmlSecNodeSetPtr	
       
   333 xmlSecXPathDataListExecute(xmlSecPtrListPtr dataList, xmlDocPtr doc, 
       
   334 		    	   xmlNodePtr hereNode, xmlSecNodeSetPtr nodes) {
       
   335     xmlSecXPathDataPtr data;
       
   336     xmlSecNodeSetPtr res, tmp, tmp2;
       
   337     xmlSecSize pos;
       
   338     
       
   339     xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), NULL);
       
   340     xmlSecAssert2(xmlSecPtrListGetSize(dataList) > 0, NULL);
       
   341     xmlSecAssert2(doc != NULL, NULL);
       
   342     xmlSecAssert2(hereNode != NULL, NULL);
       
   343 
       
   344     res = nodes;
       
   345     for(pos = 0; pos < xmlSecPtrListGetSize(dataList); ++pos) {
       
   346         data = (xmlSecXPathDataPtr)xmlSecPtrListGetItem(dataList, pos);
       
   347 	if(data == NULL) {
       
   348 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   349 		        NULL,
       
   350 			"xmlSecPtrListGetItem",
       
   351 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   352 			"pos=%d", pos);
       
   353 	    if((res != NULL) && (res != nodes)) {
       
   354 		xmlSecNodeSetDestroy(res);
       
   355 	    }
       
   356 	    return(NULL);
       
   357 	}
       
   358 
       
   359 	tmp = xmlSecXPathDataExecute(data, doc, hereNode);
       
   360 	if(tmp == NULL) {
       
   361 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   362 			NULL,
       
   363 			"xmlSecXPathDataExecute",
       
   364 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   365 			XMLSEC_ERRORS_NO_MESSAGE);
       
   366 	    if((res != NULL) && (res != nodes)) {
       
   367 		xmlSecNodeSetDestroy(res);
       
   368 	    }
       
   369 	    return(NULL);
       
   370 	}    
       
   371 
       
   372 	tmp2 = xmlSecNodeSetAdd(res, tmp, data->nodeSetOp);
       
   373 	if(tmp2 == NULL) {
       
   374 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   375 			NULL,
       
   376 			"xmlSecNodeSetAdd",
       
   377 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   378 			"xmlSecNodeSetIntersection");
       
   379 	    if((res != NULL) && (res != nodes)) {
       
   380 		xmlSecNodeSetDestroy(res);
       
   381 	    }
       
   382 	    xmlSecNodeSetDestroy(tmp);
       
   383 	    return(NULL);
       
   384 	}
       
   385 	res = tmp2;
       
   386     }
       
   387 
       
   388     return(res);
       
   389 }
       
   390 
       
   391 /******************************************************************************
       
   392  *
       
   393  * XPath/XPointer transforms
       
   394  *
       
   395  * xmlSecXPathDataList is located after xmlSecTransform structure
       
   396  * 
       
   397  *****************************************************************************/
       
   398 #define xmlSecXPathTransformSize	\
       
   399     (sizeof(xmlSecTransform) + sizeof(xmlSecPtrList))
       
   400 #define xmlSecXPathTransformGetDataList(transform) \
       
   401     ((xmlSecTransformCheckSize((transform), xmlSecXPathTransformSize)) ? \
       
   402 	(xmlSecPtrListPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \
       
   403 	(xmlSecPtrListPtr)NULL)
       
   404 #define xmlSecTransformXPathCheckId(transform) \
       
   405     (xmlSecTransformCheckId((transform), xmlSecTransformXPathId) || \
       
   406      xmlSecTransformCheckId((transform), xmlSecTransformXPath2Id) || \
       
   407      xmlSecTransformCheckId((transform), xmlSecTransformXPointerId))
       
   408 
       
   409 static int 		xmlSecTransformXPathInitialize	(xmlSecTransformPtr transform);
       
   410 static void		xmlSecTransformXPathFinalize	(xmlSecTransformPtr transform);
       
   411 static int 		xmlSecTransformXPathExecute	(xmlSecTransformPtr transform,
       
   412 							 int last, 
       
   413 							 xmlSecTransformCtxPtr transformCtx);
       
   414 
       
   415 static int
       
   416 xmlSecTransformXPathInitialize(xmlSecTransformPtr transform) {	
       
   417     xmlSecPtrListPtr dataList;
       
   418     int ret;
       
   419         
       
   420     xmlSecAssert2(xmlSecTransformXPathCheckId(transform), -1);
       
   421 
       
   422     dataList = xmlSecXPathTransformGetDataList(transform);
       
   423     xmlSecAssert2(dataList != NULL, -1);
       
   424     
       
   425     ret = xmlSecPtrListInitialize(dataList, xmlSecXPathDataListId);
       
   426     if(ret < 0) {
       
   427 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   428 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   429 		    "xmlSecPtrListInitialize",
       
   430 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   431 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   432 	return(-1);
       
   433     }
       
   434     return(0);
       
   435 }
       
   436 
       
   437 static void
       
   438 xmlSecTransformXPathFinalize(xmlSecTransformPtr transform) {
       
   439     xmlSecPtrListPtr dataList;
       
   440 
       
   441     xmlSecAssert(xmlSecTransformXPathCheckId(transform));
       
   442 
       
   443     dataList = xmlSecXPathTransformGetDataList(transform);
       
   444     xmlSecAssert(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId));
       
   445     
       
   446     xmlSecPtrListFinalize(dataList);
       
   447 }
       
   448 
       
   449 static int
       
   450 xmlSecTransformXPathExecute(xmlSecTransformPtr transform, int last,
       
   451 			    xmlSecTransformCtxPtr transformCtx) {
       
   452     xmlSecPtrListPtr dataList;
       
   453     xmlDocPtr doc;
       
   454     
       
   455     xmlSecAssert2(xmlSecTransformXPathCheckId(transform), -1);
       
   456     xmlSecAssert2(transform->hereNode != NULL, -1);
       
   457     xmlSecAssert2(transform->outNodes == NULL, -1);
       
   458     xmlSecAssert2(last != 0, -1);
       
   459     xmlSecAssert2(transformCtx != NULL, -1);
       
   460 
       
   461     dataList = xmlSecXPathTransformGetDataList(transform);
       
   462     xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1);
       
   463     xmlSecAssert2(xmlSecPtrListGetSize(dataList) > 0, -1);
       
   464 
       
   465     doc = (transform->inNodes != NULL) ? transform->inNodes->doc : transform->hereNode->doc;
       
   466     xmlSecAssert2(doc != NULL, -1);
       
   467 
       
   468     transform->outNodes = xmlSecXPathDataListExecute(dataList, doc, 
       
   469 				transform->hereNode, transform->inNodes);
       
   470     if(transform->outNodes == NULL) {
       
   471 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   472 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   473 		    "xmlSecXPathDataExecute",
       
   474 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   475 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   476 	return(-1);
       
   477     }    
       
   478     return(0);
       
   479 }
       
   480 
       
   481 /******************************************************************************
       
   482  *
       
   483  * XPath transform
       
   484  * 
       
   485  *****************************************************************************/
       
   486 static int 		xmlSecTransformXPathNodeRead	(xmlSecTransformPtr transform,
       
   487 							 xmlNodePtr node,
       
   488 							 xmlSecTransformCtxPtr transformCtx);
       
   489 
       
   490 static xmlSecTransformKlass xmlSecTransformXPathKlass = {
       
   491     /* klass/object sizes */
       
   492     sizeof(xmlSecTransformKlass),		/* xmlSecSize klassSize */
       
   493     xmlSecXPathTransformSize,			/* xmlSecSize objSize */
       
   494 
       
   495     xmlSecNameXPath,				/* const xmlChar* name; */
       
   496     xmlSecXPathNs, 				/* const xmlChar* href; */
       
   497     xmlSecTransformUsageDSigTransform,		/* xmlSecTransformUsage	usage; */
       
   498 
       
   499     xmlSecTransformXPathInitialize,		/* xmlSecTransformInitializeMethod initialize; */
       
   500     xmlSecTransformXPathFinalize,		/* xmlSecTransformFinalizeMethod finalize; */
       
   501     xmlSecTransformXPathNodeRead,		/* xmlSecTransformNodeReadMethod readNode; */
       
   502     NULL,					/* xmlSecTransformNodeWriteMethod writeNode; */
       
   503     NULL,					/* xmlSecTransformSetKeyReqMethod setKeyReq; */
       
   504     NULL,					/* xmlSecTransformSetKeyMethod setKey; */
       
   505     NULL,					/* xmlSecTransformValidateMethod validate; */
       
   506     xmlSecTransformDefaultGetDataType,		/* xmlSecTransformGetDataTypeMethod getDataType; */
       
   507     NULL,					/* xmlSecTransformPushBinMethod pushBin; */
       
   508     NULL,					/* xmlSecTransformPopBinMethod popBin; */
       
   509     xmlSecTransformDefaultPushXml,		/* xmlSecTransformPushXmlMethod pushXml; */
       
   510     xmlSecTransformDefaultPopXml,		/* xmlSecTransformPopXmlMethod popXml; */
       
   511     xmlSecTransformXPathExecute,		/* xmlSecTransformExecuteMethod execute; */
       
   512     
       
   513     NULL,					/* void* reserved0; */
       
   514     NULL,					/* void* reserved1; */
       
   515 };
       
   516 
       
   517 /**
       
   518  * xmlSecTransformXPathGetKlass:
       
   519  *
       
   520  * The XPath transform evaluates given XPath expression and 
       
   521  * intersects the result with the previous nodes set. See 
       
   522  * http://www.w3.org/TR/xmldsig-core/#sec-XPath for more details.
       
   523  *
       
   524  * Returns XPath transform id.
       
   525  */
       
   526 EXPORT_C
       
   527 xmlSecTransformId 
       
   528 xmlSecTransformXPathGetKlass(void) {
       
   529     return(&xmlSecTransformXPathKlass);
       
   530 }
       
   531 
       
   532 static const char xpathPattern[] = "(//. | //@* | //namespace::*)[%s]";
       
   533 static int 
       
   534 xmlSecTransformXPathNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
       
   535     xmlSecPtrListPtr dataList;
       
   536     xmlSecXPathDataPtr data;
       
   537     xmlNodePtr cur;
       
   538     xmlChar* tmp;
       
   539     int ret;
       
   540 
       
   541     xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPathId), -1);
       
   542     xmlSecAssert2(node != NULL, -1);
       
   543     xmlSecAssert2(transformCtx != NULL, -1);
       
   544 
       
   545     dataList = xmlSecXPathTransformGetDataList(transform);
       
   546     xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1);
       
   547     xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1);
       
   548 
       
   549     /* there is only one required node */
       
   550     cur = xmlSecGetNextElementNode(node->children);  
       
   551     if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeXPath, xmlSecDSigNs))) {
       
   552 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   553 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   554 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   555 		    XMLSEC_ERRORS_R_INVALID_NODE,
       
   556 		    "expected=%s",
       
   557 		    xmlSecErrorsSafeString(xmlSecNodeXPath));
       
   558 	return(-1);
       
   559     }
       
   560     
       
   561     /* read information from the node */
       
   562     data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPath);
       
   563     if(data == NULL) {
       
   564 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   565 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   566 		    "xmlSecXPathDataCreate",
       
   567 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   568 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   569 	return(-1);
       
   570     }
       
   571     
       
   572     ret = xmlSecXPathDataNodeRead(data, cur);
       
   573     if(ret < 0) {
       
   574 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   575 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   576 		    "xmlSecXPathDataNodeRead",
       
   577 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   578 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   579 	xmlSecXPathDataDestroy(data);
       
   580 	return(-1);
       
   581     }
       
   582         
       
   583     /* append it to the list */
       
   584     ret = xmlSecPtrListAdd(dataList, data);
       
   585     if(ret < 0) {
       
   586 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   587 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   588 		    "xmlSecPtrListAdd",
       
   589 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   590 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   591 	xmlSecXPathDataDestroy(data);
       
   592 	return(-1);
       
   593     }
       
   594     
       
   595     /* create full XPath expression */
       
   596     xmlSecAssert2(data->expr != NULL, -1);
       
   597     tmp = (xmlChar*) xmlMalloc(sizeof(xmlChar) * (xmlStrlen(data->expr) + 
       
   598 						  strlen(xpathPattern) + 1));
       
   599     if(tmp == NULL) {
       
   600 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   601 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   602 		    NULL,
       
   603 		    XMLSEC_ERRORS_R_MALLOC_FAILED,
       
   604 		    "size=%d",
       
   605 		    xmlStrlen(data->expr) + strlen(xpathPattern) + 1);
       
   606     	return(-1);
       
   607     }
       
   608     sprintf((char*)tmp, xpathPattern, (char*)data->expr);	
       
   609     xmlFree(data->expr);
       
   610     data->expr = tmp;
       
   611 
       
   612     /* set correct node set type and operation */
       
   613     data->nodeSetOp 	= xmlSecNodeSetIntersection;
       
   614     data->nodeSetType 	= xmlSecNodeSetNormal;
       
   615     
       
   616     /* check that we have nothing else */
       
   617     cur = xmlSecGetNextElementNode(cur->next);        
       
   618     if(cur != NULL) {
       
   619 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   620 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   621 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   622 		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
       
   623 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   624 	return(-1);
       
   625     }
       
   626     return(0);
       
   627 }
       
   628 
       
   629 /******************************************************************************
       
   630  *
       
   631  * XPath2 transform
       
   632  * 
       
   633  *****************************************************************************/
       
   634 static int 		xmlSecTransformXPath2NodeRead	(xmlSecTransformPtr transform,
       
   635 							 xmlNodePtr node,
       
   636 							 xmlSecTransformCtxPtr transformCtx);
       
   637 static xmlSecTransformKlass xmlSecTransformXPath2Klass = {
       
   638     /* klass/object sizes */
       
   639     sizeof(xmlSecTransformKlass),		/* xmlSecSize klassSize */
       
   640     xmlSecXPathTransformSize,			/* xmlSecSize objSize */
       
   641 
       
   642     xmlSecNameXPath2,				/* const xmlChar* name; */
       
   643     xmlSecXPath2Ns, 				/* const xmlChar* href; */
       
   644     xmlSecTransformUsageDSigTransform,		/* xmlSecTransformUsage	usage; */
       
   645 
       
   646     xmlSecTransformXPathInitialize,		/* xmlSecTransformInitializeMethod initialize; */
       
   647     xmlSecTransformXPathFinalize,		/* xmlSecTransformFinalizeMethod finalize; */
       
   648     xmlSecTransformXPath2NodeRead,		/* xmlSecTransformNodeReadMethod readNode; */
       
   649     NULL,					/* xmlSecTransformNodeWriteMethod writeNode; */
       
   650     NULL,					/* xmlSecTransformSetKeyReqMethod setKeyReq; */
       
   651     NULL,					/* xmlSecTransformSetKeyMethod setKey; */
       
   652     NULL,					/* xmlSecTransformValidateMethod validate; */
       
   653     xmlSecTransformDefaultGetDataType,		/* xmlSecTransformGetDataTypeMethod getDataType; */
       
   654     NULL,					/* xmlSecTransformPushBinMethod pushBin; */
       
   655     NULL,					/* xmlSecTransformPopBinMethod popBin; */
       
   656     xmlSecTransformDefaultPushXml,		/* xmlSecTransformPushXmlMethod pushXml; */
       
   657     xmlSecTransformDefaultPopXml,		/* xmlSecTransformPopXmlMethod popXml; */
       
   658     xmlSecTransformXPathExecute,		/* xmlSecTransformExecuteMethod execute; */
       
   659 
       
   660     NULL,					/* void* reserved0; */
       
   661     NULL,					/* void* reserved1; */
       
   662 };
       
   663 
       
   664 /**
       
   665  * xmlSecTransformXPath2GetKlass:
       
   666  * 
       
   667  * The XPath2 transform (http://www.w3.org/TR/xmldsig-filter2/).
       
   668  *
       
   669  * Returns XPath2 transform klass.
       
   670  */
       
   671 EXPORT_C
       
   672 xmlSecTransformId 
       
   673 xmlSecTransformXPath2GetKlass(void) {
       
   674     return(&xmlSecTransformXPath2Klass);
       
   675 }
       
   676 
       
   677 static int 
       
   678 xmlSecTransformXPath2NodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
       
   679     xmlSecPtrListPtr dataList;
       
   680     xmlSecXPathDataPtr data;
       
   681     xmlNodePtr cur;
       
   682     xmlChar* op;
       
   683     int ret;
       
   684 
       
   685     xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPath2Id), -1);
       
   686     xmlSecAssert2(node != NULL, -1);
       
   687     xmlSecAssert2(transformCtx != NULL, -1);
       
   688 
       
   689     dataList = xmlSecXPathTransformGetDataList(transform);
       
   690     xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1);
       
   691     xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1);
       
   692     
       
   693     /* There are only xpath nodes */
       
   694     cur = xmlSecGetNextElementNode(node->children);  
       
   695     while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeXPath2, xmlSecXPath2Ns)) {
       
   696         /* read information from the node */
       
   697 	data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPath2);
       
   698 	if(data == NULL) {
       
   699 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   700 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   701 			"xmlSecXPathDataCreate",
       
   702 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   703 			XMLSEC_ERRORS_NO_MESSAGE);
       
   704 	    return(-1);
       
   705 	}
       
   706 
       
   707         ret = xmlSecXPathDataNodeRead(data, cur);
       
   708 	if(ret < 0) {
       
   709 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   710 		        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   711 			"xmlSecXPathDataNodeRead",
       
   712 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   713 			XMLSEC_ERRORS_NO_MESSAGE);
       
   714 	    xmlSecXPathDataDestroy(data);
       
   715 	    return(-1);
       
   716 	}
       
   717     
       
   718         /* append it to the list */
       
   719 	ret = xmlSecPtrListAdd(dataList, data);
       
   720         if(ret < 0) {
       
   721 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   722 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   723 		        "xmlSecPtrListAdd",
       
   724 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   725 		        XMLSEC_ERRORS_NO_MESSAGE);
       
   726 	    xmlSecXPathDataDestroy(data);
       
   727 	    return(-1);
       
   728 	}
       
   729 
       
   730 	/* set correct node set type and operation */
       
   731 	data->nodeSetType = xmlSecNodeSetTree;
       
   732 	op = xmlGetProp(cur, xmlSecAttrFilter);
       
   733 	if(op == NULL) {
       
   734 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   735 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   736 			xmlSecErrorsSafeString(xmlSecAttrFilter),
       
   737 			XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
       
   738 			"node=%s",
       
   739 			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
       
   740 	    return(-1);
       
   741 	}
       
   742         if(xmlStrEqual(op, xmlSecXPath2FilterIntersect)) {
       
   743     	    data->nodeSetOp = xmlSecNodeSetIntersection;
       
   744 	} else if(xmlStrEqual(op, xmlSecXPath2FilterSubtract)) {
       
   745 	    data->nodeSetOp = xmlSecNodeSetSubtraction;
       
   746 	} else if(xmlStrEqual(op, xmlSecXPath2FilterUnion)) {
       
   747 	    data->nodeSetOp = xmlSecNodeSetUnion;
       
   748 	} else {
       
   749 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   750 			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   751 			xmlSecErrorsSafeString(xmlSecAttrFilter),
       
   752 			XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
       
   753 			"filter=%s", 
       
   754 			xmlSecErrorsSafeString(op));
       
   755 	    xmlFree(op);
       
   756 	    return(-1);
       
   757 	}
       
   758 	xmlFree(op);
       
   759 
       
   760         cur = xmlSecGetNextElementNode(cur->next);  
       
   761     }
       
   762 
       
   763     /* check that we have nothing else */
       
   764     if(cur != NULL) {
       
   765 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   766 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   767 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   768 		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
       
   769 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   770 	return(-1);
       
   771     }
       
   772     return(0);
       
   773 }
       
   774 
       
   775 /******************************************************************************
       
   776  *
       
   777  * XPointer transform
       
   778  * 
       
   779  *****************************************************************************/
       
   780 static int 		xmlSecTransformXPointerNodeRead	(xmlSecTransformPtr transform,
       
   781 							 xmlNodePtr node,
       
   782 							 xmlSecTransformCtxPtr transformCtx);
       
   783 static xmlSecTransformKlass xmlSecTransformXPointerKlass = {
       
   784     /* klass/object sizes */
       
   785     sizeof(xmlSecTransformKlass),		/* xmlSecSize klassSize */
       
   786     xmlSecXPathTransformSize,			/* xmlSecSize objSize */
       
   787 
       
   788     xmlSecNameXPointer,				/* const xmlChar* name; */
       
   789     xmlSecXPointerNs, 				/* const xmlChar* href; */
       
   790     xmlSecTransformUsageDSigTransform,		/* xmlSecTransformUsage	usage; */
       
   791 
       
   792     xmlSecTransformXPathInitialize,		/* xmlSecTransformInitializeMethod initialize; */
       
   793     xmlSecTransformXPathFinalize,		/* xmlSecTransformFinalizeMethod finalize; */
       
   794     xmlSecTransformXPointerNodeRead,		/* xmlSecTransformNodeReadMethod readNode; */
       
   795     NULL,					/* xmlSecTransformNodeWriteMethod writeNode; */
       
   796     NULL,					/* xmlSecTransformSetKeyReqMethod setKeyReq; */
       
   797     NULL,					/* xmlSecTransformSetKeyMethod setKey; */
       
   798     NULL,					/* xmlSecTransformValidateMethod validate; */
       
   799     xmlSecTransformDefaultGetDataType,		/* xmlSecTransformGetDataTypeMethod getDataType; */
       
   800     NULL,					/* xmlSecTransformPushBinMethod pushBin; */
       
   801     NULL,					/* xmlSecTransformPopBinMethod popBin; */
       
   802     xmlSecTransformDefaultPushXml,		/* xmlSecTransformPushXmlMethod pushXml; */
       
   803     xmlSecTransformDefaultPopXml,		/* xmlSecTransformPopXmlMethod popXml; */
       
   804     xmlSecTransformXPathExecute,		/* xmlSecTransformExecuteMethod execute; */
       
   805 
       
   806     NULL,					/* void* reserved0; */
       
   807     NULL,					/* void* reserved1; */
       
   808 };
       
   809 
       
   810 /**
       
   811  * xmlSecTransformXPointerGetKlass:
       
   812  * 
       
   813  * The XPointer transform klass 
       
   814  * (http://www.ietf.org/internet-drafts/draft-eastlake-xmldsig-uri-02.txt).
       
   815  *
       
   816  * Returns XPointer transform klass.
       
   817  */
       
   818 EXPORT_C
       
   819 xmlSecTransformId 
       
   820 xmlSecTransformXPointerGetKlass(void) {
       
   821     return(&xmlSecTransformXPointerKlass);
       
   822 }
       
   823 
       
   824 /**
       
   825  * xmlSecTransformXPointerSetExpr: 
       
   826  * @transform:		the pointer to XPointer transform.
       
   827  * @expr:		the XPointer expression.
       
   828  * @nodeSetType:	the type of evaluated XPointer expression.
       
   829  * @hereNode:		the pointer to "here" node.
       
   830  *
       
   831  * Sets the XPointer expression for an XPointer @transform.
       
   832  *
       
   833  * Returns 0 on success or a negative value if an error occurs.
       
   834  */
       
   835 EXPORT_C
       
   836 int 
       
   837 xmlSecTransformXPointerSetExpr(xmlSecTransformPtr transform, const xmlChar* expr, 
       
   838 			    xmlSecNodeSetType  nodeSetType, xmlNodePtr hereNode) {
       
   839     xmlSecPtrListPtr dataList;
       
   840     xmlSecXPathDataPtr data;
       
   841     int ret;
       
   842 
       
   843     xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPointerId), -1);
       
   844     xmlSecAssert2(transform->hereNode == NULL, -1);
       
   845     xmlSecAssert2(expr != NULL, -1);
       
   846     xmlSecAssert2(hereNode != NULL, -1);    
       
   847 
       
   848     transform->hereNode = hereNode;
       
   849     
       
   850     dataList = xmlSecXPathTransformGetDataList(transform);
       
   851     xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1);
       
   852     xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1);
       
   853 
       
   854     data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPointer);
       
   855     if(data == NULL) {
       
   856 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   857 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   858 		    "xmlSecXPathDataCreate",
       
   859 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   860 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   861 	return(-1);
       
   862     }
       
   863 
       
   864     ret = xmlSecXPathDataRegisterNamespaces(data, hereNode);
       
   865     if(ret < 0) {
       
   866 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   867 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   868 		    "xmlSecXPathDataRegisterNamespaces",
       
   869 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   870 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   871 	xmlSecXPathDataDestroy(data);
       
   872 	return(-1);
       
   873     }    
       
   874 
       
   875     ret = xmlSecXPathDataSetExpr(data, expr);
       
   876     if(ret < 0) {
       
   877 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   878 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   879 		    "xmlSecXPathDataSetExpr",
       
   880 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   881 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   882 	xmlSecXPathDataDestroy(data);
       
   883 	return(-1);
       
   884     }
       
   885     
       
   886     /* append it to the list */
       
   887     ret = xmlSecPtrListAdd(dataList, data);
       
   888     if(ret < 0) {
       
   889 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   890 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   891 		    "xmlSecPtrListAdd",
       
   892 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   893 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   894 	xmlSecXPathDataDestroy(data);
       
   895 	return(-1);
       
   896     }
       
   897 
       
   898     /* set correct node set type and operation */
       
   899     data->nodeSetOp 	= xmlSecNodeSetIntersection;
       
   900     data->nodeSetType 	= nodeSetType;
       
   901     
       
   902     return(0);
       
   903 }
       
   904 
       
   905 static int 
       
   906 xmlSecTransformXPointerNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
       
   907     xmlSecPtrListPtr dataList;
       
   908     xmlSecXPathDataPtr data;
       
   909     xmlNodePtr cur;
       
   910     int ret;
       
   911 
       
   912     xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPointerId), -1);
       
   913     xmlSecAssert2(node != NULL, -1);
       
   914     xmlSecAssert2(transformCtx != NULL, -1);
       
   915 
       
   916     dataList = xmlSecXPathTransformGetDataList(transform);
       
   917     xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1);
       
   918     xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1);
       
   919 
       
   920     /* there is only one required node */
       
   921     cur = xmlSecGetNextElementNode(node->children);  
       
   922     if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeXPointer, xmlSecXPointerNs))) {
       
   923 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   924 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   925 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   926 		    XMLSEC_ERRORS_R_INVALID_NODE,
       
   927 		    "expected=%s",
       
   928 		    xmlSecErrorsSafeString(xmlSecNodeXPath));
       
   929 	return(-1);
       
   930     }
       
   931     
       
   932     /* read information from the node */
       
   933     data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPointer);
       
   934     if(data == NULL) {
       
   935 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   936 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   937 		    "xmlSecXPathDataCreate",
       
   938 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   939 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   940 	return(-1);
       
   941     }
       
   942 
       
   943     ret = xmlSecXPathDataNodeRead(data, cur);
       
   944     if(ret < 0) {
       
   945 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   946 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   947 		    "xmlSecXPathDataNodeRead",
       
   948 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   949 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   950 	xmlSecXPathDataDestroy(data);
       
   951 	return(-1);
       
   952     }
       
   953     
       
   954     /* append it to the list */
       
   955     ret = xmlSecPtrListAdd(dataList, data);
       
   956     if(ret < 0) {
       
   957 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   958 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   959 		    "xmlSecPtrListAdd",
       
   960 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   961 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   962 	xmlSecXPathDataDestroy(data);
       
   963 	return(-1);
       
   964     }
       
   965 
       
   966     /* set correct node set type and operation */
       
   967     data->nodeSetOp 	= xmlSecNodeSetIntersection;
       
   968     data->nodeSetType 	= xmlSecNodeSetTree;
       
   969     
       
   970     /* check that we have nothing else */
       
   971     cur = xmlSecGetNextElementNode(cur->next);        
       
   972     if(cur != NULL) {
       
   973 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   974 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
   975 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   976 		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
       
   977 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   978 	return(-1);
       
   979     }
       
   980     return(0);
       
   981 }
       
   982 
       
   983 
       
   984 /******************************************************************************
       
   985  *
       
   986  * Visa3DHack transform
       
   987  * 
       
   988  *****************************************************************************/
       
   989 #define xmlSecVisa3DHackTransformSize	\
       
   990     (sizeof(xmlSecTransform) + sizeof(xmlChar*))
       
   991 #define xmlSecVisa3DHackTransformGetIDPtr(transform) \
       
   992     ((xmlSecTransformCheckSize((transform), xmlSecVisa3DHackTransformSize)) ? \
       
   993 	(xmlChar**)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \
       
   994 	(xmlChar**)NULL)
       
   995 #define xmlSecTransformVisa3DHackCheckId(transform) \
       
   996     (xmlSecTransformCheckId((transform), xmlSecTransformVisa3DHackId))
       
   997 
       
   998 static int 		xmlSecTransformVisa3DHackInitialize	(xmlSecTransformPtr transform);
       
   999 static void		xmlSecTransformVisa3DHackFinalize	(xmlSecTransformPtr transform);
       
  1000 static int 		xmlSecTransformVisa3DHackExecute	(xmlSecTransformPtr transform,
       
  1001 								 int last, 
       
  1002 								 xmlSecTransformCtxPtr transformCtx);
       
  1003 
       
  1004 static xmlSecTransformKlass xmlSecTransformVisa3DHackKlass = {
       
  1005     /* klass/object sizes */
       
  1006     sizeof(xmlSecTransformKlass),		/* xmlSecSize klassSize */
       
  1007     xmlSecVisa3DHackTransformSize,		/* xmlSecSize objSize */
       
  1008 
       
  1009     BAD_CAST "Visa3DHackTransform",		/* const xmlChar* name; */
       
  1010     NULL,					/* const xmlChar* href; */
       
  1011     xmlSecTransformUsageDSigTransform,		/* xmlSecTransformUsage	usage; */
       
  1012 
       
  1013     xmlSecTransformVisa3DHackInitialize,	/* xmlSecTransformInitializeMethod initialize; */
       
  1014     xmlSecTransformVisa3DHackFinalize,		/* xmlSecTransformFinalizeMethod finalize; */
       
  1015     NULL,					/* xmlSecTransformNodeReadMethod readNode; */
       
  1016     NULL,					/* xmlSecTransformNodeWriteMethod writeNode; */
       
  1017     NULL,					/* xmlSecTransformSetKeyReqMethod setKeyReq; */
       
  1018     NULL,					/* xmlSecTransformSetKeyMethod setKey; */
       
  1019     NULL,					/* xmlSecTransformValidateMethod validate; */
       
  1020     xmlSecTransformDefaultGetDataType,		/* xmlSecTransformGetDataTypeMethod getDataType; */
       
  1021     NULL,					/* xmlSecTransformPushBinMethod pushBin; */
       
  1022     NULL,					/* xmlSecTransformPopBinMethod popBin; */
       
  1023     xmlSecTransformDefaultPushXml,		/* xmlSecTransformPushXmlMethod pushXml; */
       
  1024     xmlSecTransformDefaultPopXml,		/* xmlSecTransformPopXmlMethod popXml; */
       
  1025     xmlSecTransformVisa3DHackExecute,		/* xmlSecTransformExecuteMethod execute; */
       
  1026 
       
  1027     NULL,					/* void* reserved0; */
       
  1028     NULL,					/* void* reserved1; */
       
  1029 };
       
  1030 
       
  1031 /**
       
  1032  * xmlSecTransformVisa3DHackGetKlass:
       
  1033  * 
       
  1034  * The Visa3DHack transform klass. The only reason why we need this 
       
  1035  * is Visa3D protocol. It doesn't follow XML/XPointer/XMLDSig specs and allows 
       
  1036  * something like "#12345" in the URI attribute. 
       
  1037  *
       
  1038  * Returns Visa3DHack transform klass.
       
  1039  */
       
  1040 EXPORT_C
       
  1041 xmlSecTransformId 
       
  1042 xmlSecTransformVisa3DHackGetKlass(void) {
       
  1043     return(&xmlSecTransformVisa3DHackKlass);
       
  1044 }
       
  1045 
       
  1046 /**
       
  1047  * xmlSecTransformVisa3DHackSetID:
       
  1048  * @transform:		the pointer to Visa3DHack transform.
       
  1049  * @id:			the ID value.
       
  1050  *
       
  1051  * Sets the ID value for an Visa3DHack @transform.
       
  1052  *
       
  1053  * Returns 0 on success or a negative value if an error occurs.
       
  1054  */
       
  1055 EXPORT_C
       
  1056 int 
       
  1057 xmlSecTransformVisa3DHackSetID(xmlSecTransformPtr transform, const xmlChar* id) {
       
  1058     xmlChar** idPtr;
       
  1059     
       
  1060     xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformVisa3DHackId), -1);
       
  1061     xmlSecAssert2(id != NULL, -1);
       
  1062 
       
  1063     idPtr = xmlSecVisa3DHackTransformGetIDPtr(transform);
       
  1064     xmlSecAssert2(idPtr != NULL, -1);
       
  1065     xmlSecAssert2((*idPtr) == NULL, -1);
       
  1066 
       
  1067     (*idPtr) = xmlStrdup(id);
       
  1068     if((*idPtr) == NULL) {
       
  1069 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1070 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  1071 		    "xmlStrdup",
       
  1072 		    XMLSEC_ERRORS_R_MALLOC_FAILED,
       
  1073 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1074 	return(-1);
       
  1075     }
       
  1076 
       
  1077     return(0);
       
  1078 }
       
  1079 
       
  1080 static int
       
  1081 xmlSecTransformVisa3DHackInitialize(xmlSecTransformPtr transform) {	
       
  1082     xmlSecAssert2(xmlSecTransformVisa3DHackCheckId(transform), -1);
       
  1083 
       
  1084     return(0);
       
  1085 }
       
  1086 
       
  1087 static void
       
  1088 xmlSecTransformVisa3DHackFinalize(xmlSecTransformPtr transform) {
       
  1089     xmlChar** idPtr;
       
  1090 
       
  1091     xmlSecAssert(xmlSecTransformVisa3DHackCheckId(transform));
       
  1092 
       
  1093     idPtr = xmlSecVisa3DHackTransformGetIDPtr(transform);
       
  1094     xmlSecAssert(idPtr != NULL);
       
  1095     
       
  1096     if((*idPtr) != NULL) {
       
  1097 	xmlFree((*idPtr));
       
  1098     }
       
  1099     (*idPtr) = NULL;
       
  1100 }
       
  1101 
       
  1102 static int
       
  1103 xmlSecTransformVisa3DHackExecute(xmlSecTransformPtr transform, int last,
       
  1104 			    xmlSecTransformCtxPtr transformCtx) {
       
  1105     xmlChar** idPtr;
       
  1106     xmlDocPtr doc;
       
  1107     xmlAttrPtr attr;
       
  1108     xmlNodeSetPtr nodeSet;
       
  1109     
       
  1110     xmlSecAssert2(xmlSecTransformVisa3DHackCheckId(transform), -1);
       
  1111     xmlSecAssert2(transform->outNodes == NULL, -1);
       
  1112     xmlSecAssert2(last != 0, -1);
       
  1113     xmlSecAssert2(transformCtx != NULL, -1);
       
  1114 
       
  1115     idPtr = xmlSecVisa3DHackTransformGetIDPtr(transform);
       
  1116     xmlSecAssert2(idPtr != NULL, -1);
       
  1117     xmlSecAssert2((*idPtr) != NULL, -1);
       
  1118 
       
  1119     doc = (transform->inNodes != NULL) ? transform->inNodes->doc : transform->hereNode->doc;
       
  1120     xmlSecAssert2(doc != NULL, -1);
       
  1121 
       
  1122     attr = xmlGetID(doc, (*idPtr));
       
  1123     if((attr == NULL) || (attr->parent == NULL)) {
       
  1124 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1125 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  1126 		    "xmlGetID",
       
  1127 		    XMLSEC_ERRORS_R_XML_FAILED,
       
  1128 		    "id=\"%s\"",
       
  1129 		    xmlSecErrorsSafeString((*idPtr)));
       
  1130 	return(-1);
       
  1131     }    
       
  1132 
       
  1133     nodeSet = xmlXPathNodeSetCreate(attr->parent);
       
  1134     if(nodeSet == NULL) {
       
  1135 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1136 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  1137 		    "xmlXPathNodeSetCreate",
       
  1138 		    XMLSEC_ERRORS_R_XML_FAILED,
       
  1139 		    "id=\"%s\"",
       
  1140 		    xmlSecErrorsSafeString((*idPtr)));
       
  1141 	return(-1);
       
  1142     }    
       
  1143 
       
  1144     transform->outNodes = xmlSecNodeSetCreate(doc, nodeSet, xmlSecNodeSetTreeWithoutComments);
       
  1145     if(transform->outNodes == NULL) {
       
  1146 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1147 		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
       
  1148 		    "xmlSecNodeSetCreate",
       
  1149 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1150 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1151 	xmlXPathFreeNodeSet(nodeSet);
       
  1152 	return(-1);
       
  1153     }    
       
  1154     return(0);
       
  1155 }
       
  1156 
       
  1157 
       
  1158