summaryrefslogtreecommitdiff
path: root/src/xpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xpath.c')
-rw-r--r--src/xpath.c1148
1 files changed, 1148 insertions, 0 deletions
diff --git a/src/xpath.c b/src/xpath.c
new file mode 100644
index 00000000..afa7c52c
--- /dev/null
+++ b/src/xpath.c
@@ -0,0 +1,1148 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * XPath transform
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/xpointer.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/list.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+
+/**************************************************************************
+ *
+ * xmlSecXPathHereFunction:
+ * @ctxt: the ponter to XPath context.
+ * @nargs: the arguments nubmer.
+ *
+ * The implementation of XPath "here()" function.
+ * See xmlXPtrHereFunction() in xpointer.c. the only change is that
+ * we return NodeSet instead of NodeInterval.
+ *
+ *****************************************************************************/
+static void
+xmlSecXPathHereFunction(xmlXPathParserContextPtr ctxt, int nargs) {
+ CHECK_ARITY(0);
+
+ if((ctxt == NULL) || (ctxt->context == NULL) || (ctxt->context->here == NULL)) {
+ XP_ERROR(XPTR_SYNTAX_ERROR);
+ }
+ valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->here));
+}
+
+/**************************************************************************
+ *
+ * XPath/XPointer data
+ *
+ *****************************************************************************/
+typedef struct _xmlSecXPathData xmlSecXPathData,
+ *xmlSecXPathDataPtr;
+typedef enum {
+ xmlSecXPathDataTypeXPath,
+ xmlSecXPathDataTypeXPath2,
+ xmlSecXPathDataTypeXPointer
+} xmlSecXPathDataType;
+
+struct _xmlSecXPathData {
+ xmlSecXPathDataType type;
+ xmlXPathContextPtr ctx;
+ xmlChar* expr;
+ xmlSecNodeSetOp nodeSetOp;
+ xmlSecNodeSetType nodeSetType;
+};
+
+static xmlSecXPathDataPtr xmlSecXPathDataCreate (xmlSecXPathDataType type);
+static void xmlSecXPathDataDestroy (xmlSecXPathDataPtr data);
+static int xmlSecXPathDataSetExpr (xmlSecXPathDataPtr data,
+ const xmlChar* expr);
+static int xmlSecXPathDataRegisterNamespaces(xmlSecXPathDataPtr data,
+ xmlNodePtr node);
+static int xmlSecXPathDataNodeRead (xmlSecXPathDataPtr data,
+ xmlNodePtr node);
+static xmlSecNodeSetPtr xmlSecXPathDataExecute (xmlSecXPathDataPtr data,
+ xmlDocPtr doc,
+ xmlNodePtr hereNode);
+
+static xmlSecXPathDataPtr
+xmlSecXPathDataCreate(xmlSecXPathDataType type) {
+ xmlSecXPathDataPtr data;
+
+ data = (xmlSecXPathDataPtr) xmlMalloc(sizeof(xmlSecXPathData));
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecXPathData)=%d",
+ sizeof(xmlSecXPathData));
+ return(NULL);
+ }
+ memset(data, 0, sizeof(xmlSecXPathData));
+
+ data->type = type;
+ data->nodeSetType = xmlSecNodeSetTree;
+
+ /* create xpath or xpointer context */
+ switch(data->type) {
+ case xmlSecXPathDataTypeXPath:
+ case xmlSecXPathDataTypeXPath2:
+ data->ctx = xmlXPathNewContext(NULL); /* we'll set doc in the context later */
+ if(data->ctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlXPathNewContext",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(NULL);
+ }
+ break;
+ case xmlSecXPathDataTypeXPointer:
+ data->ctx = xmlXPtrNewContext(NULL, NULL, NULL); /* we'll set doc in the context later */
+ if(data->ctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlXPtrNewContext",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(NULL);
+ }
+ break;
+ }
+
+ return(data);
+}
+
+static void
+xmlSecXPathDataDestroy(xmlSecXPathDataPtr data) {
+ xmlSecAssert(data != NULL);
+
+ if(data->expr != NULL) {
+ xmlFree(data->expr);
+ }
+ if(data->ctx != NULL) {
+ xmlXPathFreeContext(data->ctx);
+ }
+ memset(data, 0, sizeof(xmlSecXPathData));
+ xmlFree(data);
+}
+
+static int
+xmlSecXPathDataSetExpr(xmlSecXPathDataPtr data, const xmlChar* expr) {
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(data->expr == NULL, -1);
+ xmlSecAssert2(data->ctx != NULL, -1);
+ xmlSecAssert2(expr != NULL, -1);
+
+ data->expr = xmlStrdup(expr);
+ if(data->expr == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_STRDUP_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+
+static int
+xmlSecXPathDataRegisterNamespaces(xmlSecXPathDataPtr data, xmlNodePtr node) {
+ xmlNodePtr cur;
+ xmlNsPtr ns;
+ int ret;
+
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(data->ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* register namespaces */
+ for(cur = node; cur != NULL; cur = cur->parent) {
+ for(ns = cur->nsDef; ns != NULL; ns = ns->next) {
+ /* check that we have no other namespace with same prefix already */
+ if((ns->prefix != NULL) && (xmlXPathNsLookup(data->ctx, ns->prefix) == NULL)){
+ ret = xmlXPathRegisterNs(data->ctx, ns->prefix, ns->href);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlXPathRegisterNs",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "href=%s;prefix=%s",
+ xmlSecErrorsSafeString(ns->href),
+ xmlSecErrorsSafeString(ns->prefix));
+ return(-1);
+ }
+ }
+ }
+ }
+
+ return(0);
+}
+
+static int
+xmlSecXPathDataNodeRead(xmlSecXPathDataPtr data, xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(data->expr == NULL, -1);
+ xmlSecAssert2(data->ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ ret = xmlSecXPathDataRegisterNamespaces (data, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXPathDataRegisterNamespaces",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* read node content and set expr */
+ data->expr = xmlNodeGetContent(node);
+ if(data->expr == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static xmlSecNodeSetPtr
+xmlSecXPathDataExecute(xmlSecXPathDataPtr data, xmlDocPtr doc, xmlNodePtr hereNode) {
+ xmlXPathObjectPtr xpathObj = NULL;
+ xmlSecNodeSetPtr nodes;
+
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(data->expr != NULL, NULL);
+ xmlSecAssert2(data->ctx != NULL, NULL);
+ xmlSecAssert2(doc != NULL, NULL);
+ xmlSecAssert2(hereNode != NULL, NULL);
+
+ /* do not forget to set the doc */
+ data->ctx->doc = doc;
+
+ /* here function works only on the same document */
+ if(hereNode->doc == doc) {
+ xmlXPathRegisterFunc(data->ctx, (xmlChar *)"here", xmlSecXPathHereFunction);
+ data->ctx->here = hereNode;
+ data->ctx->xptr = 1;
+ }
+
+ /* execute xpath or xpointer expression */
+ switch(data->type) {
+ case xmlSecXPathDataTypeXPath:
+ case xmlSecXPathDataTypeXPath2:
+ xpathObj = xmlXPathEvalExpression(data->expr, data->ctx);
+ if(xpathObj == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlXPathEvalExpression",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "expr=%s",
+ xmlSecErrorsSafeString(data->expr));
+ return(NULL);
+ }
+ break;
+ case xmlSecXPathDataTypeXPointer:
+ xpathObj = xmlXPtrEval(data->expr, data->ctx);
+ if(xpathObj == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlXPtrEval",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "expr=%s",
+ xmlSecErrorsSafeString(data->expr));
+ return(NULL);
+ }
+ break;
+ }
+
+ nodes = xmlSecNodeSetCreate(doc, xpathObj->nodesetval, data->nodeSetType);
+ if(nodes == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNodeSetCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "type=%d", data->nodeSetType);
+ xmlXPathFreeObject(xpathObj);
+ return(NULL);
+ }
+ xpathObj->nodesetval = NULL;
+ xmlXPathFreeObject(xpathObj);
+
+ return(nodes);
+}
+
+
+/**************************************************************************
+ *
+ * XPath data list
+ *
+ *****************************************************************************/
+#define xmlSecXPathDataListId \
+ xmlSecXPathDataListGetKlass()
+static xmlSecPtrListId xmlSecXPathDataListGetKlass (void);
+static xmlSecNodeSetPtr xmlSecXPathDataListExecute (xmlSecPtrListPtr dataList,
+ xmlDocPtr doc,
+ xmlNodePtr hereNode,
+ xmlSecNodeSetPtr nodes);
+
+static xmlSecPtrListKlass xmlSecXPathDataListKlass = {
+ BAD_CAST "xpath-data-list",
+ NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ (xmlSecPtrDestroyItemMethod)xmlSecXPathDataDestroy, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+static xmlSecPtrListId
+xmlSecXPathDataListGetKlass(void) {
+ return(&xmlSecXPathDataListKlass);
+}
+
+static xmlSecNodeSetPtr
+xmlSecXPathDataListExecute(xmlSecPtrListPtr dataList, xmlDocPtr doc,
+ xmlNodePtr hereNode, xmlSecNodeSetPtr nodes) {
+ xmlSecXPathDataPtr data;
+ xmlSecNodeSetPtr res, tmp, tmp2;
+ xmlSecSize pos;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), NULL);
+ xmlSecAssert2(xmlSecPtrListGetSize(dataList) > 0, NULL);
+ xmlSecAssert2(doc != NULL, NULL);
+ xmlSecAssert2(hereNode != NULL, NULL);
+
+ res = nodes;
+ for(pos = 0; pos < xmlSecPtrListGetSize(dataList); ++pos) {
+ data = (xmlSecXPathDataPtr)xmlSecPtrListGetItem(dataList, pos);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListGetItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ if((res != NULL) && (res != nodes)) {
+ xmlSecNodeSetDestroy(res);
+ }
+ return(NULL);
+ }
+
+ tmp = xmlSecXPathDataExecute(data, doc, hereNode);
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXPathDataExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ if((res != NULL) && (res != nodes)) {
+ xmlSecNodeSetDestroy(res);
+ }
+ return(NULL);
+ }
+
+ tmp2 = xmlSecNodeSetAdd(res, tmp, data->nodeSetOp);
+ if(tmp2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNodeSetAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecNodeSetIntersection");
+ if((res != NULL) && (res != nodes)) {
+ xmlSecNodeSetDestroy(res);
+ }
+ xmlSecNodeSetDestroy(tmp);
+ return(NULL);
+ }
+ res = tmp2;
+ }
+
+ return(res);
+}
+
+/******************************************************************************
+ *
+ * XPath/XPointer transforms
+ *
+ * xmlSecXPathDataList is located after xmlSecTransform structure
+ *
+ *****************************************************************************/
+#define xmlSecXPathTransformSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecPtrList))
+#define xmlSecXPathTransformGetDataList(transform) \
+ ((xmlSecTransformCheckSize((transform), xmlSecXPathTransformSize)) ? \
+ (xmlSecPtrListPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \
+ (xmlSecPtrListPtr)NULL)
+#define xmlSecTransformXPathCheckId(transform) \
+ (xmlSecTransformCheckId((transform), xmlSecTransformXPathId) || \
+ xmlSecTransformCheckId((transform), xmlSecTransformXPath2Id) || \
+ xmlSecTransformCheckId((transform), xmlSecTransformXPointerId))
+
+static int xmlSecTransformXPathInitialize (xmlSecTransformPtr transform);
+static void xmlSecTransformXPathFinalize (xmlSecTransformPtr transform);
+static int xmlSecTransformXPathExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static int
+xmlSecTransformXPathInitialize(xmlSecTransformPtr transform) {
+ xmlSecPtrListPtr dataList;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformXPathCheckId(transform), -1);
+
+ dataList = xmlSecXPathTransformGetDataList(transform);
+ xmlSecAssert2(dataList != NULL, -1);
+
+ ret = xmlSecPtrListInitialize(dataList, xmlSecXPathDataListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+static void
+xmlSecTransformXPathFinalize(xmlSecTransformPtr transform) {
+ xmlSecPtrListPtr dataList;
+
+ xmlSecAssert(xmlSecTransformXPathCheckId(transform));
+
+ dataList = xmlSecXPathTransformGetDataList(transform);
+ xmlSecAssert(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId));
+
+ xmlSecPtrListFinalize(dataList);
+}
+
+static int
+xmlSecTransformXPathExecute(xmlSecTransformPtr transform, int last,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecPtrListPtr dataList;
+ xmlDocPtr doc;
+
+ xmlSecAssert2(xmlSecTransformXPathCheckId(transform), -1);
+ xmlSecAssert2(transform->hereNode != NULL, -1);
+ xmlSecAssert2(transform->outNodes == NULL, -1);
+ xmlSecAssert2(last != 0, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ dataList = xmlSecXPathTransformGetDataList(transform);
+ xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1);
+ xmlSecAssert2(xmlSecPtrListGetSize(dataList) > 0, -1);
+
+ doc = (transform->inNodes != NULL) ? transform->inNodes->doc : transform->hereNode->doc;
+ xmlSecAssert2(doc != NULL, -1);
+
+ transform->outNodes = xmlSecXPathDataListExecute(dataList, doc,
+ transform->hereNode, transform->inNodes);
+ if(transform->outNodes == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+/******************************************************************************
+ *
+ * XPath transform
+ *
+ *****************************************************************************/
+static int xmlSecTransformXPathNodeRead (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+
+static xmlSecTransformKlass xmlSecTransformXPathKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecXPathTransformSize, /* xmlSecSize objSize */
+
+ xmlSecNameXPath, /* const xmlChar* name; */
+ xmlSecXPathNs, /* const xmlChar* href; */
+ xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */
+
+ xmlSecTransformXPathInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformXPathFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecTransformXPathNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ NULL, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecTransformXPathExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformXPathGetKlass:
+ *
+ * The XPath transform evaluates given XPath expression and
+ * intersects the result with the previous nodes set. See
+ * http://www.w3.org/TR/xmldsig-core/#sec-XPath for more details.
+ *
+ * Returns: XPath transform id.
+ */
+xmlSecTransformId
+xmlSecTransformXPathGetKlass(void) {
+ return(&xmlSecTransformXPathKlass);
+}
+
+static const char xpathPattern[] = "(//. | //@* | //namespace::*)[boolean(%s)]";
+static int
+xmlSecTransformXPathNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecPtrListPtr dataList;
+ xmlSecXPathDataPtr data;
+ xmlNodePtr cur;
+ xmlChar* tmp;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPathId), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ dataList = xmlSecXPathTransformGetDataList(transform);
+ xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1);
+ xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1);
+
+ /* there is only one required node */
+ cur = xmlSecGetNextElementNode(node->children);
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeXPath, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeXPath));
+ return(-1);
+ }
+
+ /* read information from the node */
+ data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPath);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecXPathDataNodeRead(data, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* append it to the list */
+ ret = xmlSecPtrListAdd(dataList, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* create full XPath expression */
+ xmlSecAssert2(data->expr != NULL, -1);
+ tmp = (xmlChar*) xmlMalloc(sizeof(xmlChar) * (xmlStrlen(data->expr) +
+ strlen(xpathPattern) + 1));
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d",
+ xmlStrlen(data->expr) + strlen(xpathPattern) + 1);
+ return(-1);
+ }
+ sprintf((char*)tmp, xpathPattern, (char*)data->expr);
+ xmlFree(data->expr);
+ data->expr = tmp;
+
+ /* set correct node set type and operation */
+ data->nodeSetOp = xmlSecNodeSetIntersection;
+ data->nodeSetType = xmlSecNodeSetNormal;
+
+ /* check that we have nothing else */
+ cur = xmlSecGetNextElementNode(cur->next);
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+/******************************************************************************
+ *
+ * XPath2 transform
+ *
+ *****************************************************************************/
+static int xmlSecTransformXPath2NodeRead (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+static xmlSecTransformKlass xmlSecTransformXPath2Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecXPathTransformSize, /* xmlSecSize objSize */
+
+ xmlSecNameXPath2, /* const xmlChar* name; */
+ xmlSecXPath2Ns, /* const xmlChar* href; */
+ xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */
+
+ xmlSecTransformXPathInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformXPathFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecTransformXPath2NodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ NULL, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecTransformXPathExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformXPath2GetKlass:
+ *
+ * The XPath2 transform (http://www.w3.org/TR/xmldsig-filter2/).
+ *
+ * Returns: XPath2 transform klass.
+ */
+xmlSecTransformId
+xmlSecTransformXPath2GetKlass(void) {
+ return(&xmlSecTransformXPath2Klass);
+}
+
+static int
+xmlSecTransformXPath2NodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecPtrListPtr dataList;
+ xmlSecXPathDataPtr data;
+ xmlNodePtr cur;
+ xmlChar* op;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPath2Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ dataList = xmlSecXPathTransformGetDataList(transform);
+ xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1);
+ xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1);
+
+ /* There are only xpath nodes */
+ cur = xmlSecGetNextElementNode(node->children);
+ while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeXPath2, xmlSecXPath2Ns)) {
+ /* read information from the node */
+ data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPath2);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecXPathDataNodeRead(data, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* append it to the list */
+ ret = xmlSecPtrListAdd(dataList, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* set correct node set type and operation */
+ data->nodeSetType = xmlSecNodeSetTree;
+ op = xmlGetProp(cur, xmlSecAttrFilter);
+ if(op == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecAttrFilter),
+ XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+ if(xmlStrEqual(op, xmlSecXPath2FilterIntersect)) {
+ data->nodeSetOp = xmlSecNodeSetIntersection;
+ } else if(xmlStrEqual(op, xmlSecXPath2FilterSubtract)) {
+ data->nodeSetOp = xmlSecNodeSetSubtraction;
+ } else if(xmlStrEqual(op, xmlSecXPath2FilterUnion)) {
+ data->nodeSetOp = xmlSecNodeSetUnion;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecAttrFilter),
+ XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
+ "filter=%s",
+ xmlSecErrorsSafeString(op));
+ xmlFree(op);
+ return(-1);
+ }
+ xmlFree(op);
+
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* check that we have nothing else */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+/******************************************************************************
+ *
+ * XPointer transform
+ *
+ *****************************************************************************/
+static int xmlSecTransformXPointerNodeRead (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+static xmlSecTransformKlass xmlSecTransformXPointerKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecXPathTransformSize, /* xmlSecSize objSize */
+
+ xmlSecNameXPointer, /* const xmlChar* name; */
+ xmlSecXPointerNs, /* const xmlChar* href; */
+ xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */
+
+ xmlSecTransformXPathInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformXPathFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecTransformXPointerNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ NULL, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecTransformXPathExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformXPointerGetKlass:
+ *
+ * The XPointer transform klass
+ * (http://www.ietf.org/internet-drafts/draft-eastlake-xmldsig-uri-02.txt).
+ *
+ * Returns: XPointer transform klass.
+ */
+xmlSecTransformId
+xmlSecTransformXPointerGetKlass(void) {
+ return(&xmlSecTransformXPointerKlass);
+}
+
+/**
+ * xmlSecTransformXPointerSetExpr:
+ * @transform: the pointer to XPointer transform.
+ * @expr: the XPointer expression.
+ * @nodeSetType: the type of evaluated XPointer expression.
+ * @hereNode: the pointer to "here" node.
+ *
+ * Sets the XPointer expression for an XPointer @transform.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformXPointerSetExpr(xmlSecTransformPtr transform, const xmlChar* expr,
+ xmlSecNodeSetType nodeSetType, xmlNodePtr hereNode) {
+ xmlSecPtrListPtr dataList;
+ xmlSecXPathDataPtr data;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPointerId), -1);
+ xmlSecAssert2(transform->hereNode == NULL, -1);
+ xmlSecAssert2(expr != NULL, -1);
+ xmlSecAssert2(hereNode != NULL, -1);
+
+ transform->hereNode = hereNode;
+
+ dataList = xmlSecXPathTransformGetDataList(transform);
+ xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1);
+ xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1);
+
+ data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPointer);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecXPathDataRegisterNamespaces(data, hereNode);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataRegisterNamespaces",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ ret = xmlSecXPathDataSetExpr(data, expr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataSetExpr",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* append it to the list */
+ ret = xmlSecPtrListAdd(dataList, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* set correct node set type and operation */
+ data->nodeSetOp = xmlSecNodeSetIntersection;
+ data->nodeSetType = nodeSetType;
+
+ return(0);
+}
+
+static int
+xmlSecTransformXPointerNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecPtrListPtr dataList;
+ xmlSecXPathDataPtr data;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPointerId), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ dataList = xmlSecXPathTransformGetDataList(transform);
+ xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1);
+ xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1);
+
+ /* there is only one required node */
+ cur = xmlSecGetNextElementNode(node->children);
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeXPointer, xmlSecXPointerNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeXPath));
+ return(-1);
+ }
+
+ /* read information from the node */
+ data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPointer);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecXPathDataNodeRead(data, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* append it to the list */
+ ret = xmlSecPtrListAdd(dataList, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* set correct node set type and operation */
+ data->nodeSetOp = xmlSecNodeSetIntersection;
+ data->nodeSetType = xmlSecNodeSetTree;
+
+ /* check that we have nothing else */
+ cur = xmlSecGetNextElementNode(cur->next);
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+
+/******************************************************************************
+ *
+ * Visa3DHack transform
+ *
+ *****************************************************************************/
+#define xmlSecVisa3DHackTransformSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlChar*))
+#define xmlSecVisa3DHackTransformGetIDPtr(transform) \
+ ((xmlSecTransformCheckSize((transform), xmlSecVisa3DHackTransformSize)) ? \
+ (xmlChar**)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \
+ (xmlChar**)NULL)
+#define xmlSecTransformVisa3DHackCheckId(transform) \
+ (xmlSecTransformCheckId((transform), xmlSecTransformVisa3DHackId))
+
+static int xmlSecTransformVisa3DHackInitialize (xmlSecTransformPtr transform);
+static void xmlSecTransformVisa3DHackFinalize (xmlSecTransformPtr transform);
+static int xmlSecTransformVisa3DHackExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static xmlSecTransformKlass xmlSecTransformVisa3DHackKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecVisa3DHackTransformSize, /* xmlSecSize objSize */
+
+ BAD_CAST "Visa3DHackTransform", /* const xmlChar* name; */
+ NULL, /* const xmlChar* href; */
+ xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */
+
+ xmlSecTransformVisa3DHackInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformVisa3DHackFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ NULL, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecTransformVisa3DHackExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformVisa3DHackGetKlass:
+ *
+ * The Visa3DHack transform klass. The only reason why we need this
+ * is Visa3D protocol. It doesn't follow XML/XPointer/XMLDSig specs and allows
+ * invalid XPointer expressions in the URI attribute. Since we couldn't evaluate
+ * such expressions thru XPath/XPointer engine, we need to have this hack here.
+ *
+ * Returns: Visa3DHack transform klass.
+ */
+xmlSecTransformId
+xmlSecTransformVisa3DHackGetKlass(void) {
+ return(&xmlSecTransformVisa3DHackKlass);
+}
+
+/**
+ * xmlSecTransformVisa3DHackSetID:
+ * @transform: the pointer to Visa3DHack transform.
+ * @id: the ID value.
+ *
+ * Sets the ID value for an Visa3DHack @transform.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformVisa3DHackSetID(xmlSecTransformPtr transform, const xmlChar* id) {
+ xmlChar** idPtr;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformVisa3DHackId), -1);
+ xmlSecAssert2(id != NULL, -1);
+
+ idPtr = xmlSecVisa3DHackTransformGetIDPtr(transform);
+ xmlSecAssert2(idPtr != NULL, -1);
+ xmlSecAssert2((*idPtr) == NULL, -1);
+
+ (*idPtr) = xmlStrdup(id);
+ if((*idPtr) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecTransformVisa3DHackInitialize(xmlSecTransformPtr transform) {
+ xmlSecAssert2(xmlSecTransformVisa3DHackCheckId(transform), -1);
+
+ return(0);
+}
+
+static void
+xmlSecTransformVisa3DHackFinalize(xmlSecTransformPtr transform) {
+ xmlChar** idPtr;
+
+ xmlSecAssert(xmlSecTransformVisa3DHackCheckId(transform));
+
+ idPtr = xmlSecVisa3DHackTransformGetIDPtr(transform);
+ xmlSecAssert(idPtr != NULL);
+
+ if((*idPtr) != NULL) {
+ xmlFree((*idPtr));
+ }
+ (*idPtr) = NULL;
+}
+
+static int
+xmlSecTransformVisa3DHackExecute(xmlSecTransformPtr transform, int last,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlChar** idPtr;
+ xmlDocPtr doc;
+ xmlAttrPtr attr;
+ xmlNodeSetPtr nodeSet;
+
+ xmlSecAssert2(xmlSecTransformVisa3DHackCheckId(transform), -1);
+ xmlSecAssert2(transform->outNodes == NULL, -1);
+ xmlSecAssert2(last != 0, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ idPtr = xmlSecVisa3DHackTransformGetIDPtr(transform);
+ xmlSecAssert2(idPtr != NULL, -1);
+ xmlSecAssert2((*idPtr) != NULL, -1);
+
+ doc = (transform->inNodes != NULL) ? transform->inNodes->doc : transform->hereNode->doc;
+ xmlSecAssert2(doc != NULL, -1);
+
+ attr = xmlGetID(doc, (*idPtr));
+ if((attr == NULL) || (attr->parent == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlGetID",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "id=\"%s\"",
+ xmlSecErrorsSafeString((*idPtr)));
+ return(-1);
+ }
+
+ nodeSet = xmlXPathNodeSetCreate(attr->parent);
+ if(nodeSet == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlXPathNodeSetCreate",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "id=\"%s\"",
+ xmlSecErrorsSafeString((*idPtr)));
+ return(-1);
+ }
+
+ transform->outNodes = xmlSecNodeSetCreate(doc, nodeSet, xmlSecNodeSetTreeWithoutComments);
+ if(transform->outNodes == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNodeSetCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlXPathFreeNodeSet(nodeSet);
+ return(-1);
+ }
+ return(0);
+}
+
+
+