📄 c14n.c
字号:
/*
* "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 memory error
*/
static void
xmlC14NErrMemory(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);
}
/**
* xmlC14NErrParam:
* @extra: extra informations
*
* Handle a redefinition of param error
*/
static void
xmlC14NErrParam(const char *extra)
{
__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N,
XML_ERR_INTERNAL_ERROR, XML_ERR_ERROR, NULL, 0, extra,
NULL, NULL, 0, 0,
"Invalid parameter : %s\n", extra);
}
/**
* xmlC14NErrInternal:
* @extra: extra informations
*
* Handle a redefinition of internal error
*/
static void
xmlC14NErrInternal(const char *extra)
{
__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N,
XML_ERR_INTERNAL_ERROR, XML_ERR_ERROR, NULL, 0, extra,
NULL, NULL, 0, 0,
"Internal error : %s\n", extra);
}
/**
* xmlC14NErrInvalidNode:
* @extra: extra informations
*
* Handle a redefinition of invalid node error
*/
static void
xmlC14NErrInvalidNode(const char *node_type, const char *extra)
{
__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N,
XML_C14N_INVALID_NODE, XML_ERR_ERROR, NULL, 0, extra,
NULL, NULL, 0, 0,
"Node %s is invalid here : %s\n", node_type, extra);
}
/**
* xmlC14NErrUnknownNode:
* @extra: extra informations
*
* Handle a redefinition of unknown node error
*/
static void
xmlC14NErrUnknownNode(int node_type, const char *extra)
{
__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N,
XML_C14N_UNKNOW_NODE, XML_ERR_ERROR, NULL, 0, extra,
NULL, NULL, 0, 0,
"Unknown node type %d found : %s\n", node_type, extra);
}
/**
* xmlC14NErrRelativeNamespace:
* @extra: extra informations
*
* Handle a redefinition of relative namespace error
*/
static void
xmlC14NErrRelativeNamespace(const char *ns_uri)
{
__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N,
XML_C14N_RELATIVE_NAMESPACE, XML_ERR_ERROR, NULL, 0, NULL,
NULL, NULL, 0, 0,
"Relative namespace UR is invalid here : %s\n", ns_uri);
}
/**
* 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 void
xmlC14NErr(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 16
static 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 xmlC14NVisibleNsStackPtr
xmlC14NVisibleNsStackCreate(void) {
xmlC14NVisibleNsStackPtr ret;
ret = (xmlC14NVisibleNsStackPtr) xmlMalloc(sizeof(xmlC14NVisibleNsStack));
if (ret == NULL) {
xmlC14NErrMemory("creating namespaces stack");
return(NULL);
}
memset(ret, 0 , (size_t) sizeof(xmlC14NVisibleNsStack));
return(ret);
}
static void
xmlC14NVisibleNsStackDestroy(xmlC14NVisibleNsStackPtr cur) {
if(cur == NULL) {
xmlC14NErrParam("destroying namespaces stack");
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))) {
xmlC14NErrParam("adding namespace to stack");
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 void
xmlC14NVisibleNsStackSave(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) {
if((cur == NULL) || (state == NULL)) {
xmlC14NErrParam("saving namespaces stack");
return;
}
state->nsCurEnd = cur->nsCurEnd;
state->nsPrevStart = cur->nsPrevStart;
state->nsPrevEnd = cur->nsPrevEnd;
}
static void
xmlC14NVisibleNsStackRestore(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) {
if((cur == NULL) || (state == NULL)) {
xmlC14NErrParam("restoring namespaces stack");
return;
}
cur->nsCurEnd = state->nsCurEnd;
cur->nsPrevStart = state->nsPrevStart;
cur->nsPrevEnd = state->nsPrevEnd;
}
static void
xmlC14NVisibleNsStackShift(xmlC14NVisibleNsStackPtr cur) {
if(cur == NULL) {
xmlC14NErrParam("shifting namespaces stack");
return;
}
cur->nsPrevStart = cur->nsPrevEnd;
cur->nsPrevEnd = cur->nsCurEnd;
}
static int
xmlC14NStrEqual(const xmlChar *str1, const xmlChar *str2) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -