📄 c14n.c.svn-base
字号:
/* * "Canonical XML" implementation * http://www.w3.org/TR/xml-c14n * * "Exclusive XML Canonicalization" implementation * http://www.w3.org/TR/xml-exc-c14n * * See Copyright for the status of this software. * * Author: Aleksey Sanin <aleksey@aleksey.com> */#define IN_LIBXML#include "libxml.h"#ifdef LIBXML_C14N_ENABLED#ifdef LIBXML_OUTPUT_ENABLED#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#include <string.h>#include <libxml/tree.h>#include <libxml/parser.h>#include <libxml/uri.h>#include <libxml/xmlerror.h>#include <libxml/globals.h>#include <libxml/xpathInternals.h>#include <libxml/c14n.h>/************************************************************************ * * * Some declaration better left private ATM * * * ************************************************************************/typedef enum { XMLC14N_BEFORE_DOCUMENT_ELEMENT = 0, XMLC14N_INSIDE_DOCUMENT_ELEMENT = 1, XMLC14N_AFTER_DOCUMENT_ELEMENT = 2} xmlC14NPosition;typedef struct _xmlC14NVisibleNsStack { int nsCurEnd; /* number of nodes in the set */ int nsPrevStart; /* the begginning of the stack for previous visible node */ int nsPrevEnd; /* the end of the stack for previous visible node */ int nsMax; /* size of the array as allocated */ xmlNsPtr *nsTab; /* array of ns in no particular order */ xmlNodePtr *nodeTab;/* array of nodes in no particular order */} xmlC14NVisibleNsStack, *xmlC14NVisibleNsStackPtr;typedef struct _xmlC14NCtx { /* input parameters */ xmlDocPtr doc; xmlC14NIsVisibleCallback is_visible_callback; void* user_data; int with_comments; xmlOutputBufferPtr buf; /* position in the XML document */ xmlC14NPosition pos; int parent_is_doc; xmlC14NVisibleNsStackPtr ns_rendered; /* exclusive canonicalization */ int exclusive; xmlChar **inclusive_ns_prefixes; /* error number */ int error;} xmlC14NCtx, *xmlC14NCtxPtr;static xmlC14NVisibleNsStackPtr xmlC14NVisibleNsStackCreate (void);static void xmlC14NVisibleNsStackDestroy (xmlC14NVisibleNsStackPtr cur);static void xmlC14NVisibleNsStackAdd (xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlNodePtr node);static void xmlC14NVisibleNsStackSave (xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state);static void xmlC14NVisibleNsStackRestore (xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state);static void xmlC14NVisibleNsStackShift (xmlC14NVisibleNsStackPtr cur);static int xmlC14NVisibleNsStackFind (xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns);static int xmlExcC14NVisibleNsStackFind (xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlC14NCtxPtr ctx);static int xmlC14NIsNodeInNodeset (xmlNodeSetPtr nodes, xmlNodePtr node, xmlNodePtr parent);static int xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur);static int xmlC14NProcessNodeList(xmlC14NCtxPtr ctx, xmlNodePtr cur);typedef enum { XMLC14N_NORMALIZE_ATTR = 0, XMLC14N_NORMALIZE_COMMENT = 1, XMLC14N_NORMALIZE_PI = 2, XMLC14N_NORMALIZE_TEXT = 3} xmlC14NNormalizationMode;static xmlChar *xmlC11NNormalizeString(const xmlChar * input, xmlC14NNormalizationMode mode);#define xmlC11NNormalizeAttr( a ) \ xmlC11NNormalizeString((a), XMLC14N_NORMALIZE_ATTR)#define xmlC11NNormalizeComment( a ) \ xmlC11NNormalizeString((a), XMLC14N_NORMALIZE_COMMENT)#define xmlC11NNormalizePI( a ) \ xmlC11NNormalizeString((a), XMLC14N_NORMALIZE_PI)#define xmlC11NNormalizeText( a ) \ xmlC11NNormalizeString((a), XMLC14N_NORMALIZE_TEXT)#define xmlC14NIsVisible( ctx, node, parent ) \ (((ctx)->is_visible_callback != NULL) ? \ (ctx)->is_visible_callback((ctx)->user_data, \ (xmlNodePtr)(node), (xmlNodePtr)(parent)) : 1)/************************************************************************ * * * Some factorized error routines * * * ************************************************************************//** * xmlC14NErrMemory: * @extra: extra informations * * Handle a redefinition of attribute error */static voidxmlC14NErrMemory(const char *extra){ __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N, XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, extra, NULL, NULL, 0, 0, "Memory allocation failed : %s\n", extra);}/** * xmlC14NErr: * @ctxt: a C14N evaluation context * @node: the context node * @error: the erorr code * @msg: the message * @extra: extra informations * * Handle a redefinition of attribute error */static voidxmlC14NErr(xmlC14NCtxPtr ctxt, xmlNodePtr node, int error, const char * msg){ if (ctxt != NULL) ctxt->error = error; __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_C14N, error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0, msg);}/************************************************************************ * * * The implementation internals * * * ************************************************************************/#define XML_NAMESPACES_DEFAULT 16static int xmlC14NIsNodeInNodeset(xmlNodeSetPtr nodes, xmlNodePtr node, xmlNodePtr parent) { if((nodes != NULL) && (node != NULL)) { if(node->type != XML_NAMESPACE_DECL) { return(xmlXPathNodeSetContains(nodes, node)); } else { xmlNs ns; memcpy(&ns, node, sizeof(ns)); /* this is a libxml hack! check xpath.c for details */ if((parent != NULL) && (parent->type == XML_ATTRIBUTE_NODE)) { ns.next = (xmlNsPtr)parent->parent; } else { ns.next = (xmlNsPtr)parent; } /* * If the input is an XPath node-set, then the node-set must explicitly * contain every node to be rendered to the canonical form. */ return(xmlXPathNodeSetContains(nodes, (xmlNodePtr)&ns)); } } return(1);}static xmlC14NVisibleNsStackPtrxmlC14NVisibleNsStackCreate(void) { xmlC14NVisibleNsStackPtr ret; ret = (xmlC14NVisibleNsStackPtr) xmlMalloc(sizeof(xmlC14NVisibleNsStack)); if (ret == NULL) { xmlC14NErrMemory("creating stack"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlC14NVisibleNsStack)); return(ret);}static voidxmlC14NVisibleNsStackDestroy(xmlC14NVisibleNsStackPtr cur) { if(cur == NULL) {#ifdef DEBUG_C14N xmlGenericError(xmlGenericErrorContext, "xmlC14NVisibleNsStackDestroy: cur is null.\n");#endif return; } if(cur->nsTab != NULL) { memset(cur->nsTab, 0, cur->nsMax * sizeof(xmlNsPtr)); xmlFree(cur->nsTab); } if(cur->nodeTab != NULL) { memset(cur->nodeTab, 0, cur->nsMax * sizeof(xmlNodePtr)); xmlFree(cur->nodeTab); } memset(cur, 0, sizeof(xmlC14NVisibleNsStack)); xmlFree(cur); }static void xmlC14NVisibleNsStackAdd(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlNodePtr node) { if((cur == NULL) || ((cur->nsTab == NULL) && (cur->nodeTab != NULL)) || ((cur->nsTab != NULL) && (cur->nodeTab == NULL))) {#ifdef DEBUG_C14N xmlGenericError(xmlGenericErrorContext, "xmlC14NVisibleNsStackAdd: cur is null.\n");#endif return; } if ((cur->nsTab == NULL) && (cur->nodeTab == NULL)) { cur->nsTab = (xmlNsPtr*) xmlMalloc(XML_NAMESPACES_DEFAULT * sizeof(xmlNsPtr)); cur->nodeTab = (xmlNodePtr*) xmlMalloc(XML_NAMESPACES_DEFAULT * sizeof(xmlNodePtr)); if ((cur->nsTab == NULL) || (cur->nodeTab == NULL)) { xmlC14NErrMemory("adding node to stack"); return; } memset(cur->nsTab, 0 , XML_NAMESPACES_DEFAULT * sizeof(xmlNsPtr)); memset(cur->nodeTab, 0 , XML_NAMESPACES_DEFAULT * sizeof(xmlNodePtr)); cur->nsMax = XML_NAMESPACES_DEFAULT; } else if(cur->nsMax == cur->nsCurEnd) { void *tmp; int tmpSize; tmpSize = 2 * cur->nsMax; tmp = xmlRealloc(cur->nsTab, tmpSize * sizeof(xmlNsPtr)); if (tmp == NULL) { xmlC14NErrMemory("adding node to stack"); return; } cur->nsTab = (xmlNsPtr*)tmp; tmp = xmlRealloc(cur->nodeTab, tmpSize * sizeof(xmlNodePtr)); if (tmp == NULL) { xmlC14NErrMemory("adding node to stack"); return; } cur->nodeTab = (xmlNodePtr*)tmp; cur->nsMax = tmpSize; } cur->nsTab[cur->nsCurEnd] = ns; cur->nodeTab[cur->nsCurEnd] = node; ++cur->nsCurEnd;}static voidxmlC14NVisibleNsStackSave(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) { if((cur == NULL) || (state == NULL)) {#ifdef DEBUG_C14N xmlGenericError(xmlGenericErrorContext, "xmlC14NVisibleNsStackSave: cur or state is null.\n");#endif return; } state->nsCurEnd = cur->nsCurEnd; state->nsPrevStart = cur->nsPrevStart; state->nsPrevEnd = cur->nsPrevEnd;}static voidxmlC14NVisibleNsStackRestore(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) { if((cur == NULL) || (state == NULL)) {#ifdef DEBUG_C14N xmlGenericError(xmlGenericErrorContext, "xmlC14NVisibleNsStackRestore: cur or state is null.\n");#endif return; } cur->nsCurEnd = state->nsCurEnd; cur->nsPrevStart = state->nsPrevStart; cur->nsPrevEnd = state->nsPrevEnd;}static void xmlC14NVisibleNsStackShift(xmlC14NVisibleNsStackPtr cur) { if(cur == NULL) {#ifdef DEBUG_C14N xmlGenericError(xmlGenericErrorContext, "xmlC14NVisibleNsStackRestore: cur is null.\n");#endif return; } cur->nsPrevStart = cur->nsPrevEnd; cur->nsPrevEnd = cur->nsCurEnd;}static intxmlC14NStrEqual(const xmlChar *str1, const xmlChar *str2) { if (str1 == str2) return(1); if (str1 == NULL) return((*str2) == '\0'); if (str2 == NULL) return((*str1) == '\0'); do { if (*str1++ != *str2) return(0); } while (*str2++); return(1);}/** * xmlC14NVisibleNsStackFind: * @ctx: the C14N context * @ns: the namespace to check * * Checks whether the given namespace was already rendered or not * * Returns 1 if we already wrote this namespace or 0 otherwise */static intxmlC14NVisibleNsStackFind(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns){ int i; const xmlChar *prefix; const xmlChar *href; int has_empty_ns; if(cur == NULL) {#ifdef DEBUG_C14N xmlGenericError(xmlGenericErrorContext, "xmlC14NVisibleNsStackFind: cur is null.\n");#endif return (0); } /* * if the default namespace xmlns="" is not defined yet then * we do not want to print it out */ prefix = ((ns == NULL) || (ns->prefix == NULL)) ? BAD_CAST "" : ns->prefix; href = ((ns == NULL) || (ns->href == NULL)) ? BAD_CAST "" : ns->href; has_empty_ns = (xmlC14NStrEqual(prefix, NULL) && xmlC14NStrEqual(href, NULL)); if (cur->nsTab != NULL) { int start = (has_empty_ns) ? 0 : cur->nsPrevStart; for (i = cur->nsCurEnd - 1; i >= start; --i) { xmlNsPtr ns1 = cur->nsTab[i]; if(xmlC14NStrEqual(prefix, (ns1 != NULL) ? ns1->prefix : NULL)) { return(xmlC14NStrEqual(href, (ns1 != NULL) ? ns1->href : NULL)); } } } return(has_empty_ns);}static int xmlExcC14NVisibleNsStackFind(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlC14NCtxPtr ctx) { int i; const xmlChar *prefix; const xmlChar *href; int has_empty_ns; if(cur == NULL) {#ifdef DEBUG_C14N xmlGenericError(xmlGenericErrorContext, "xmlExcC14NVisibleNsStackFind: cur is null.\n");#endif return (0); } /* * if the default namespace xmlns="" is not defined yet then * we do not want to print it out
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -