1*7c568831SAndroid Build Coastguard Worker /*
2*7c568831SAndroid Build Coastguard Worker * "Canonical XML" implementation
3*7c568831SAndroid Build Coastguard Worker * http://www.w3.org/TR/xml-c14n
4*7c568831SAndroid Build Coastguard Worker *
5*7c568831SAndroid Build Coastguard Worker * "Exclusive XML Canonicalization" implementation
6*7c568831SAndroid Build Coastguard Worker * http://www.w3.org/TR/xml-exc-c14n
7*7c568831SAndroid Build Coastguard Worker *
8*7c568831SAndroid Build Coastguard Worker * See Copyright for the status of this software.
9*7c568831SAndroid Build Coastguard Worker *
10*7c568831SAndroid Build Coastguard Worker * Author: Aleksey Sanin <[email protected]>
11*7c568831SAndroid Build Coastguard Worker */
12*7c568831SAndroid Build Coastguard Worker #define IN_LIBXML
13*7c568831SAndroid Build Coastguard Worker #include "libxml.h"
14*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_C14N_ENABLED
15*7c568831SAndroid Build Coastguard Worker
16*7c568831SAndroid Build Coastguard Worker #include <stdlib.h>
17*7c568831SAndroid Build Coastguard Worker #include <string.h>
18*7c568831SAndroid Build Coastguard Worker
19*7c568831SAndroid Build Coastguard Worker #include <libxml/tree.h>
20*7c568831SAndroid Build Coastguard Worker #include <libxml/parser.h>
21*7c568831SAndroid Build Coastguard Worker #include <libxml/uri.h>
22*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlerror.h>
23*7c568831SAndroid Build Coastguard Worker #include <libxml/xpathInternals.h>
24*7c568831SAndroid Build Coastguard Worker #include <libxml/c14n.h>
25*7c568831SAndroid Build Coastguard Worker
26*7c568831SAndroid Build Coastguard Worker #include "private/error.h"
27*7c568831SAndroid Build Coastguard Worker #include "private/io.h"
28*7c568831SAndroid Build Coastguard Worker
29*7c568831SAndroid Build Coastguard Worker /************************************************************************
30*7c568831SAndroid Build Coastguard Worker * *
31*7c568831SAndroid Build Coastguard Worker * Some declaration better left private ATM *
32*7c568831SAndroid Build Coastguard Worker * *
33*7c568831SAndroid Build Coastguard Worker ************************************************************************/
34*7c568831SAndroid Build Coastguard Worker
35*7c568831SAndroid Build Coastguard Worker typedef enum {
36*7c568831SAndroid Build Coastguard Worker XMLC14N_BEFORE_DOCUMENT_ELEMENT = 0,
37*7c568831SAndroid Build Coastguard Worker XMLC14N_INSIDE_DOCUMENT_ELEMENT = 1,
38*7c568831SAndroid Build Coastguard Worker XMLC14N_AFTER_DOCUMENT_ELEMENT = 2
39*7c568831SAndroid Build Coastguard Worker } xmlC14NPosition;
40*7c568831SAndroid Build Coastguard Worker
41*7c568831SAndroid Build Coastguard Worker typedef struct _xmlC14NVisibleNsStack {
42*7c568831SAndroid Build Coastguard Worker int nsCurEnd; /* number of nodes in the set */
43*7c568831SAndroid Build Coastguard Worker int nsPrevStart; /* the beginning of the stack for previous visible node */
44*7c568831SAndroid Build Coastguard Worker int nsPrevEnd; /* the end of the stack for previous visible node */
45*7c568831SAndroid Build Coastguard Worker int nsMax; /* size of the array as allocated */
46*7c568831SAndroid Build Coastguard Worker xmlNsPtr *nsTab; /* array of ns in no particular order */
47*7c568831SAndroid Build Coastguard Worker xmlNodePtr *nodeTab; /* array of nodes in no particular order */
48*7c568831SAndroid Build Coastguard Worker } xmlC14NVisibleNsStack, *xmlC14NVisibleNsStackPtr;
49*7c568831SAndroid Build Coastguard Worker
50*7c568831SAndroid Build Coastguard Worker typedef struct _xmlC14NCtx {
51*7c568831SAndroid Build Coastguard Worker /* input parameters */
52*7c568831SAndroid Build Coastguard Worker xmlDocPtr doc;
53*7c568831SAndroid Build Coastguard Worker xmlC14NIsVisibleCallback is_visible_callback;
54*7c568831SAndroid Build Coastguard Worker void* user_data;
55*7c568831SAndroid Build Coastguard Worker int with_comments;
56*7c568831SAndroid Build Coastguard Worker xmlOutputBufferPtr buf;
57*7c568831SAndroid Build Coastguard Worker
58*7c568831SAndroid Build Coastguard Worker /* position in the XML document */
59*7c568831SAndroid Build Coastguard Worker xmlC14NPosition pos;
60*7c568831SAndroid Build Coastguard Worker int parent_is_doc;
61*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStackPtr ns_rendered;
62*7c568831SAndroid Build Coastguard Worker
63*7c568831SAndroid Build Coastguard Worker /* C14N mode */
64*7c568831SAndroid Build Coastguard Worker xmlC14NMode mode;
65*7c568831SAndroid Build Coastguard Worker
66*7c568831SAndroid Build Coastguard Worker /* exclusive canonicalization */
67*7c568831SAndroid Build Coastguard Worker xmlChar **inclusive_ns_prefixes;
68*7c568831SAndroid Build Coastguard Worker
69*7c568831SAndroid Build Coastguard Worker /* error number */
70*7c568831SAndroid Build Coastguard Worker int error;
71*7c568831SAndroid Build Coastguard Worker } xmlC14NCtx, *xmlC14NCtxPtr;
72*7c568831SAndroid Build Coastguard Worker
73*7c568831SAndroid Build Coastguard Worker static xmlC14NVisibleNsStackPtr xmlC14NVisibleNsStackCreate (void);
74*7c568831SAndroid Build Coastguard Worker static void xmlC14NVisibleNsStackDestroy (xmlC14NVisibleNsStackPtr cur);
75*7c568831SAndroid Build Coastguard Worker static int xmlC14NVisibleNsStackAdd (xmlC14NVisibleNsStackPtr cur,
76*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns,
77*7c568831SAndroid Build Coastguard Worker xmlNodePtr node);
78*7c568831SAndroid Build Coastguard Worker static void xmlC14NVisibleNsStackSave (xmlC14NVisibleNsStackPtr cur,
79*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStackPtr state);
80*7c568831SAndroid Build Coastguard Worker static void xmlC14NVisibleNsStackRestore (xmlC14NVisibleNsStackPtr cur,
81*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStackPtr state);
82*7c568831SAndroid Build Coastguard Worker static void xmlC14NVisibleNsStackShift (xmlC14NVisibleNsStackPtr cur);
83*7c568831SAndroid Build Coastguard Worker static int xmlC14NVisibleNsStackFind (xmlC14NVisibleNsStackPtr cur,
84*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns);
85*7c568831SAndroid Build Coastguard Worker static int xmlExcC14NVisibleNsStackFind (xmlC14NVisibleNsStackPtr cur,
86*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns,
87*7c568831SAndroid Build Coastguard Worker xmlC14NCtxPtr ctx);
88*7c568831SAndroid Build Coastguard Worker
89*7c568831SAndroid Build Coastguard Worker static int xmlC14NIsNodeInNodeset (void *user_data,
90*7c568831SAndroid Build Coastguard Worker xmlNodePtr node,
91*7c568831SAndroid Build Coastguard Worker xmlNodePtr parent);
92*7c568831SAndroid Build Coastguard Worker
93*7c568831SAndroid Build Coastguard Worker
94*7c568831SAndroid Build Coastguard Worker
95*7c568831SAndroid Build Coastguard Worker static int xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur);
96*7c568831SAndroid Build Coastguard Worker static int xmlC14NProcessNodeList(xmlC14NCtxPtr ctx, xmlNodePtr cur);
97*7c568831SAndroid Build Coastguard Worker typedef enum {
98*7c568831SAndroid Build Coastguard Worker XMLC14N_NORMALIZE_ATTR = 0,
99*7c568831SAndroid Build Coastguard Worker XMLC14N_NORMALIZE_COMMENT = 1,
100*7c568831SAndroid Build Coastguard Worker XMLC14N_NORMALIZE_PI = 2,
101*7c568831SAndroid Build Coastguard Worker XMLC14N_NORMALIZE_TEXT = 3
102*7c568831SAndroid Build Coastguard Worker } xmlC14NNormalizationMode;
103*7c568831SAndroid Build Coastguard Worker
104*7c568831SAndroid Build Coastguard Worker static xmlChar *xmlC11NNormalizeString(const xmlChar * input,
105*7c568831SAndroid Build Coastguard Worker xmlC14NNormalizationMode mode);
106*7c568831SAndroid Build Coastguard Worker
107*7c568831SAndroid Build Coastguard Worker #define xmlC11NNormalizeAttr( a ) \
108*7c568831SAndroid Build Coastguard Worker xmlC11NNormalizeString((a), XMLC14N_NORMALIZE_ATTR)
109*7c568831SAndroid Build Coastguard Worker #define xmlC11NNormalizeComment( a ) \
110*7c568831SAndroid Build Coastguard Worker xmlC11NNormalizeString((a), XMLC14N_NORMALIZE_COMMENT)
111*7c568831SAndroid Build Coastguard Worker #define xmlC11NNormalizePI( a ) \
112*7c568831SAndroid Build Coastguard Worker xmlC11NNormalizeString((a), XMLC14N_NORMALIZE_PI)
113*7c568831SAndroid Build Coastguard Worker #define xmlC11NNormalizeText( a ) \
114*7c568831SAndroid Build Coastguard Worker xmlC11NNormalizeString((a), XMLC14N_NORMALIZE_TEXT)
115*7c568831SAndroid Build Coastguard Worker
116*7c568831SAndroid Build Coastguard Worker #define xmlC14NIsVisible( ctx, node, parent ) \
117*7c568831SAndroid Build Coastguard Worker (((ctx)->is_visible_callback != NULL) ? \
118*7c568831SAndroid Build Coastguard Worker (ctx)->is_visible_callback((ctx)->user_data, \
119*7c568831SAndroid Build Coastguard Worker (xmlNodePtr)(node), (xmlNodePtr)(parent)) : 1)
120*7c568831SAndroid Build Coastguard Worker
121*7c568831SAndroid Build Coastguard Worker #define xmlC14NIsExclusive( ctx ) \
122*7c568831SAndroid Build Coastguard Worker ( (ctx)->mode == XML_C14N_EXCLUSIVE_1_0 )
123*7c568831SAndroid Build Coastguard Worker
124*7c568831SAndroid Build Coastguard Worker /************************************************************************
125*7c568831SAndroid Build Coastguard Worker * *
126*7c568831SAndroid Build Coastguard Worker * Some factorized error routines *
127*7c568831SAndroid Build Coastguard Worker * *
128*7c568831SAndroid Build Coastguard Worker ************************************************************************/
129*7c568831SAndroid Build Coastguard Worker
130*7c568831SAndroid Build Coastguard Worker /**
131*7c568831SAndroid Build Coastguard Worker * xmlC14NErrMemory:
132*7c568831SAndroid Build Coastguard Worker * @extra: extra information
133*7c568831SAndroid Build Coastguard Worker *
134*7c568831SAndroid Build Coastguard Worker * Handle a redefinition of memory error
135*7c568831SAndroid Build Coastguard Worker */
136*7c568831SAndroid Build Coastguard Worker static void
xmlC14NErrMemory(xmlC14NCtxPtr ctxt)137*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(xmlC14NCtxPtr ctxt)
138*7c568831SAndroid Build Coastguard Worker {
139*7c568831SAndroid Build Coastguard Worker if (ctxt != NULL)
140*7c568831SAndroid Build Coastguard Worker ctxt->error = XML_ERR_NO_MEMORY;
141*7c568831SAndroid Build Coastguard Worker
142*7c568831SAndroid Build Coastguard Worker xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_C14N, NULL);
143*7c568831SAndroid Build Coastguard Worker }
144*7c568831SAndroid Build Coastguard Worker
145*7c568831SAndroid Build Coastguard Worker static void
xmlC14NErrFull(xmlC14NCtxPtr ctxt,xmlNodePtr node,int code,const char * str1,const char * msg,...)146*7c568831SAndroid Build Coastguard Worker xmlC14NErrFull(xmlC14NCtxPtr ctxt, xmlNodePtr node, int code, const char *str1,
147*7c568831SAndroid Build Coastguard Worker const char *msg, ...)
148*7c568831SAndroid Build Coastguard Worker {
149*7c568831SAndroid Build Coastguard Worker va_list ap;
150*7c568831SAndroid Build Coastguard Worker int res;
151*7c568831SAndroid Build Coastguard Worker
152*7c568831SAndroid Build Coastguard Worker if (ctxt != NULL)
153*7c568831SAndroid Build Coastguard Worker ctxt->error = code;
154*7c568831SAndroid Build Coastguard Worker
155*7c568831SAndroid Build Coastguard Worker va_start(ap, msg);
156*7c568831SAndroid Build Coastguard Worker res = xmlVRaiseError(NULL, NULL, NULL, ctxt, node,
157*7c568831SAndroid Build Coastguard Worker XML_FROM_C14N, code, XML_ERR_ERROR, NULL, 0,
158*7c568831SAndroid Build Coastguard Worker str1, NULL, NULL, 0, 0,
159*7c568831SAndroid Build Coastguard Worker msg, ap);
160*7c568831SAndroid Build Coastguard Worker va_end(ap);
161*7c568831SAndroid Build Coastguard Worker if (res < 0)
162*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctxt);
163*7c568831SAndroid Build Coastguard Worker }
164*7c568831SAndroid Build Coastguard Worker
165*7c568831SAndroid Build Coastguard Worker /**
166*7c568831SAndroid Build Coastguard Worker * xmlC14NErrParam:
167*7c568831SAndroid Build Coastguard Worker * @extra: extra information
168*7c568831SAndroid Build Coastguard Worker *
169*7c568831SAndroid Build Coastguard Worker * Handle a param error
170*7c568831SAndroid Build Coastguard Worker */
171*7c568831SAndroid Build Coastguard Worker static void
xmlC14NErrParam(xmlC14NCtxPtr ctxt)172*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(xmlC14NCtxPtr ctxt)
173*7c568831SAndroid Build Coastguard Worker {
174*7c568831SAndroid Build Coastguard Worker xmlC14NErrFull(ctxt, NULL, XML_ERR_ARGUMENT, NULL,
175*7c568831SAndroid Build Coastguard Worker "Invalid argument\n", NULL);
176*7c568831SAndroid Build Coastguard Worker }
177*7c568831SAndroid Build Coastguard Worker
178*7c568831SAndroid Build Coastguard Worker /**
179*7c568831SAndroid Build Coastguard Worker * xmlC14NErrInvalidNode:
180*7c568831SAndroid Build Coastguard Worker * @extra: extra information
181*7c568831SAndroid Build Coastguard Worker *
182*7c568831SAndroid Build Coastguard Worker * Handle an invalid node error
183*7c568831SAndroid Build Coastguard Worker */
184*7c568831SAndroid Build Coastguard Worker static void
xmlC14NErrInvalidNode(xmlC14NCtxPtr ctxt,const char * node_type,const char * extra)185*7c568831SAndroid Build Coastguard Worker xmlC14NErrInvalidNode(xmlC14NCtxPtr ctxt, const char *node_type,
186*7c568831SAndroid Build Coastguard Worker const char *extra)
187*7c568831SAndroid Build Coastguard Worker {
188*7c568831SAndroid Build Coastguard Worker xmlC14NErrFull(ctxt, NULL, XML_C14N_INVALID_NODE, extra,
189*7c568831SAndroid Build Coastguard Worker "Node %s is invalid here : %s\n", node_type, extra);
190*7c568831SAndroid Build Coastguard Worker }
191*7c568831SAndroid Build Coastguard Worker
192*7c568831SAndroid Build Coastguard Worker /**
193*7c568831SAndroid Build Coastguard Worker * xmlC14NErrUnknownNode:
194*7c568831SAndroid Build Coastguard Worker * @extra: extra information
195*7c568831SAndroid Build Coastguard Worker *
196*7c568831SAndroid Build Coastguard Worker * Handle an unknown node error
197*7c568831SAndroid Build Coastguard Worker */
198*7c568831SAndroid Build Coastguard Worker static void
xmlC14NErrUnknownNode(xmlC14NCtxPtr ctxt,int node_type,const char * extra)199*7c568831SAndroid Build Coastguard Worker xmlC14NErrUnknownNode(xmlC14NCtxPtr ctxt, int node_type, const char *extra)
200*7c568831SAndroid Build Coastguard Worker {
201*7c568831SAndroid Build Coastguard Worker xmlC14NErrFull(ctxt, NULL, XML_C14N_UNKNOW_NODE, extra,
202*7c568831SAndroid Build Coastguard Worker "Unknown node type %d found : %s\n", node_type, extra);
203*7c568831SAndroid Build Coastguard Worker }
204*7c568831SAndroid Build Coastguard Worker
205*7c568831SAndroid Build Coastguard Worker /**
206*7c568831SAndroid Build Coastguard Worker * xmlC14NErrRelativeNamespace:
207*7c568831SAndroid Build Coastguard Worker * @extra: extra information
208*7c568831SAndroid Build Coastguard Worker *
209*7c568831SAndroid Build Coastguard Worker * Handle a relative namespace error
210*7c568831SAndroid Build Coastguard Worker */
211*7c568831SAndroid Build Coastguard Worker static void
xmlC14NErrRelativeNamespace(xmlC14NCtxPtr ctxt,const char * ns_uri)212*7c568831SAndroid Build Coastguard Worker xmlC14NErrRelativeNamespace(xmlC14NCtxPtr ctxt, const char *ns_uri)
213*7c568831SAndroid Build Coastguard Worker {
214*7c568831SAndroid Build Coastguard Worker xmlC14NErrFull(ctxt, NULL, XML_C14N_RELATIVE_NAMESPACE, ns_uri,
215*7c568831SAndroid Build Coastguard Worker "Relative namespace UR is invalid here : %s\n", ns_uri);
216*7c568831SAndroid Build Coastguard Worker }
217*7c568831SAndroid Build Coastguard Worker
218*7c568831SAndroid Build Coastguard Worker
219*7c568831SAndroid Build Coastguard Worker
220*7c568831SAndroid Build Coastguard Worker /**
221*7c568831SAndroid Build Coastguard Worker * xmlC14NErr:
222*7c568831SAndroid Build Coastguard Worker * @ctxt: a C14N evaluation context
223*7c568831SAndroid Build Coastguard Worker * @node: the context node
224*7c568831SAndroid Build Coastguard Worker * @error: the error code
225*7c568831SAndroid Build Coastguard Worker * @msg: the message
226*7c568831SAndroid Build Coastguard Worker * @extra: extra information
227*7c568831SAndroid Build Coastguard Worker *
228*7c568831SAndroid Build Coastguard Worker * Handle an error
229*7c568831SAndroid Build Coastguard Worker */
230*7c568831SAndroid Build Coastguard Worker static void
xmlC14NErr(xmlC14NCtxPtr ctxt,xmlNodePtr node,int error,const char * msg)231*7c568831SAndroid Build Coastguard Worker xmlC14NErr(xmlC14NCtxPtr ctxt, xmlNodePtr node, int error,
232*7c568831SAndroid Build Coastguard Worker const char * msg)
233*7c568831SAndroid Build Coastguard Worker {
234*7c568831SAndroid Build Coastguard Worker xmlC14NErrFull(ctxt, node, error, NULL, "%s", msg);
235*7c568831SAndroid Build Coastguard Worker }
236*7c568831SAndroid Build Coastguard Worker
237*7c568831SAndroid Build Coastguard Worker /************************************************************************
238*7c568831SAndroid Build Coastguard Worker * *
239*7c568831SAndroid Build Coastguard Worker * The implementation internals *
240*7c568831SAndroid Build Coastguard Worker * *
241*7c568831SAndroid Build Coastguard Worker ************************************************************************/
242*7c568831SAndroid Build Coastguard Worker #define XML_NAMESPACES_DEFAULT 16
243*7c568831SAndroid Build Coastguard Worker
244*7c568831SAndroid Build Coastguard Worker static int
xmlC14NIsNodeInNodeset(void * user_data,xmlNodePtr node,xmlNodePtr parent)245*7c568831SAndroid Build Coastguard Worker xmlC14NIsNodeInNodeset(void *user_data, xmlNodePtr node, xmlNodePtr parent) {
246*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr nodes = (xmlNodeSetPtr) user_data;
247*7c568831SAndroid Build Coastguard Worker if((nodes != NULL) && (node != NULL)) {
248*7c568831SAndroid Build Coastguard Worker if(node->type != XML_NAMESPACE_DECL) {
249*7c568831SAndroid Build Coastguard Worker return(xmlXPathNodeSetContains(nodes, node));
250*7c568831SAndroid Build Coastguard Worker } else {
251*7c568831SAndroid Build Coastguard Worker xmlNs ns;
252*7c568831SAndroid Build Coastguard Worker
253*7c568831SAndroid Build Coastguard Worker memcpy(&ns, node, sizeof(ns));
254*7c568831SAndroid Build Coastguard Worker
255*7c568831SAndroid Build Coastguard Worker /* this is a libxml hack! check xpath.c for details */
256*7c568831SAndroid Build Coastguard Worker if((parent != NULL) && (parent->type == XML_ATTRIBUTE_NODE)) {
257*7c568831SAndroid Build Coastguard Worker ns.next = (xmlNsPtr)parent->parent;
258*7c568831SAndroid Build Coastguard Worker } else {
259*7c568831SAndroid Build Coastguard Worker ns.next = (xmlNsPtr)parent;
260*7c568831SAndroid Build Coastguard Worker }
261*7c568831SAndroid Build Coastguard Worker
262*7c568831SAndroid Build Coastguard Worker /*
263*7c568831SAndroid Build Coastguard Worker * If the input is an XPath node-set, then the node-set must explicitly
264*7c568831SAndroid Build Coastguard Worker * contain every node to be rendered to the canonical form.
265*7c568831SAndroid Build Coastguard Worker */
266*7c568831SAndroid Build Coastguard Worker return(xmlXPathNodeSetContains(nodes, (xmlNodePtr)&ns));
267*7c568831SAndroid Build Coastguard Worker }
268*7c568831SAndroid Build Coastguard Worker }
269*7c568831SAndroid Build Coastguard Worker return(1);
270*7c568831SAndroid Build Coastguard Worker }
271*7c568831SAndroid Build Coastguard Worker
272*7c568831SAndroid Build Coastguard Worker static xmlC14NVisibleNsStackPtr
xmlC14NVisibleNsStackCreate(void)273*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStackCreate(void) {
274*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStackPtr ret;
275*7c568831SAndroid Build Coastguard Worker
276*7c568831SAndroid Build Coastguard Worker ret = (xmlC14NVisibleNsStackPtr) xmlMalloc(sizeof(xmlC14NVisibleNsStack));
277*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
278*7c568831SAndroid Build Coastguard Worker return(NULL);
279*7c568831SAndroid Build Coastguard Worker memset(ret, 0, sizeof(xmlC14NVisibleNsStack));
280*7c568831SAndroid Build Coastguard Worker return(ret);
281*7c568831SAndroid Build Coastguard Worker }
282*7c568831SAndroid Build Coastguard Worker
283*7c568831SAndroid Build Coastguard Worker static void
xmlC14NVisibleNsStackDestroy(xmlC14NVisibleNsStackPtr cur)284*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStackDestroy(xmlC14NVisibleNsStackPtr cur) {
285*7c568831SAndroid Build Coastguard Worker if(cur == NULL) {
286*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(NULL);
287*7c568831SAndroid Build Coastguard Worker return;
288*7c568831SAndroid Build Coastguard Worker }
289*7c568831SAndroid Build Coastguard Worker if(cur->nsTab != NULL) {
290*7c568831SAndroid Build Coastguard Worker memset(cur->nsTab, 0, cur->nsMax * sizeof(xmlNsPtr));
291*7c568831SAndroid Build Coastguard Worker xmlFree(cur->nsTab);
292*7c568831SAndroid Build Coastguard Worker }
293*7c568831SAndroid Build Coastguard Worker if(cur->nodeTab != NULL) {
294*7c568831SAndroid Build Coastguard Worker memset(cur->nodeTab, 0, cur->nsMax * sizeof(xmlNodePtr));
295*7c568831SAndroid Build Coastguard Worker xmlFree(cur->nodeTab);
296*7c568831SAndroid Build Coastguard Worker }
297*7c568831SAndroid Build Coastguard Worker memset(cur, 0, sizeof(xmlC14NVisibleNsStack));
298*7c568831SAndroid Build Coastguard Worker xmlFree(cur);
299*7c568831SAndroid Build Coastguard Worker
300*7c568831SAndroid Build Coastguard Worker }
301*7c568831SAndroid Build Coastguard Worker
302*7c568831SAndroid Build Coastguard Worker static int
xmlC14NVisibleNsStackAdd(xmlC14NVisibleNsStackPtr cur,xmlNsPtr ns,xmlNodePtr node)303*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStackAdd(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlNodePtr node) {
304*7c568831SAndroid Build Coastguard Worker if((cur == NULL) ||
305*7c568831SAndroid Build Coastguard Worker ((cur->nsTab == NULL) && (cur->nodeTab != NULL)) ||
306*7c568831SAndroid Build Coastguard Worker ((cur->nsTab != NULL) && (cur->nodeTab == NULL)))
307*7c568831SAndroid Build Coastguard Worker return (1);
308*7c568831SAndroid Build Coastguard Worker
309*7c568831SAndroid Build Coastguard Worker if ((cur->nsTab == NULL) && (cur->nodeTab == NULL)) {
310*7c568831SAndroid Build Coastguard Worker cur->nsTab = (xmlNsPtr*) xmlMalloc(XML_NAMESPACES_DEFAULT * sizeof(xmlNsPtr));
311*7c568831SAndroid Build Coastguard Worker cur->nodeTab = (xmlNodePtr*) xmlMalloc(XML_NAMESPACES_DEFAULT * sizeof(xmlNodePtr));
312*7c568831SAndroid Build Coastguard Worker if ((cur->nsTab == NULL) || (cur->nodeTab == NULL))
313*7c568831SAndroid Build Coastguard Worker return (-1);
314*7c568831SAndroid Build Coastguard Worker memset(cur->nsTab, 0 , XML_NAMESPACES_DEFAULT * sizeof(xmlNsPtr));
315*7c568831SAndroid Build Coastguard Worker memset(cur->nodeTab, 0 , XML_NAMESPACES_DEFAULT * sizeof(xmlNodePtr));
316*7c568831SAndroid Build Coastguard Worker cur->nsMax = XML_NAMESPACES_DEFAULT;
317*7c568831SAndroid Build Coastguard Worker } else if(cur->nsMax == cur->nsCurEnd) {
318*7c568831SAndroid Build Coastguard Worker void *tmp;
319*7c568831SAndroid Build Coastguard Worker int tmpSize;
320*7c568831SAndroid Build Coastguard Worker
321*7c568831SAndroid Build Coastguard Worker tmpSize = 2 * cur->nsMax;
322*7c568831SAndroid Build Coastguard Worker tmp = xmlRealloc(cur->nsTab, tmpSize * sizeof(xmlNsPtr));
323*7c568831SAndroid Build Coastguard Worker if (tmp == NULL)
324*7c568831SAndroid Build Coastguard Worker return (-1);
325*7c568831SAndroid Build Coastguard Worker cur->nsTab = (xmlNsPtr*)tmp;
326*7c568831SAndroid Build Coastguard Worker
327*7c568831SAndroid Build Coastguard Worker tmp = xmlRealloc(cur->nodeTab, tmpSize * sizeof(xmlNodePtr));
328*7c568831SAndroid Build Coastguard Worker if (tmp == NULL)
329*7c568831SAndroid Build Coastguard Worker return (-1);
330*7c568831SAndroid Build Coastguard Worker cur->nodeTab = (xmlNodePtr*)tmp;
331*7c568831SAndroid Build Coastguard Worker
332*7c568831SAndroid Build Coastguard Worker cur->nsMax = tmpSize;
333*7c568831SAndroid Build Coastguard Worker }
334*7c568831SAndroid Build Coastguard Worker cur->nsTab[cur->nsCurEnd] = ns;
335*7c568831SAndroid Build Coastguard Worker cur->nodeTab[cur->nsCurEnd] = node;
336*7c568831SAndroid Build Coastguard Worker
337*7c568831SAndroid Build Coastguard Worker ++cur->nsCurEnd;
338*7c568831SAndroid Build Coastguard Worker
339*7c568831SAndroid Build Coastguard Worker return (0);
340*7c568831SAndroid Build Coastguard Worker }
341*7c568831SAndroid Build Coastguard Worker
342*7c568831SAndroid Build Coastguard Worker static void
xmlC14NVisibleNsStackSave(xmlC14NVisibleNsStackPtr cur,xmlC14NVisibleNsStackPtr state)343*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStackSave(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) {
344*7c568831SAndroid Build Coastguard Worker if((cur == NULL) || (state == NULL)) {
345*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(NULL);
346*7c568831SAndroid Build Coastguard Worker return;
347*7c568831SAndroid Build Coastguard Worker }
348*7c568831SAndroid Build Coastguard Worker
349*7c568831SAndroid Build Coastguard Worker state->nsCurEnd = cur->nsCurEnd;
350*7c568831SAndroid Build Coastguard Worker state->nsPrevStart = cur->nsPrevStart;
351*7c568831SAndroid Build Coastguard Worker state->nsPrevEnd = cur->nsPrevEnd;
352*7c568831SAndroid Build Coastguard Worker }
353*7c568831SAndroid Build Coastguard Worker
354*7c568831SAndroid Build Coastguard Worker static void
xmlC14NVisibleNsStackRestore(xmlC14NVisibleNsStackPtr cur,xmlC14NVisibleNsStackPtr state)355*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStackRestore(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) {
356*7c568831SAndroid Build Coastguard Worker if((cur == NULL) || (state == NULL)) {
357*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(NULL);
358*7c568831SAndroid Build Coastguard Worker return;
359*7c568831SAndroid Build Coastguard Worker }
360*7c568831SAndroid Build Coastguard Worker cur->nsCurEnd = state->nsCurEnd;
361*7c568831SAndroid Build Coastguard Worker cur->nsPrevStart = state->nsPrevStart;
362*7c568831SAndroid Build Coastguard Worker cur->nsPrevEnd = state->nsPrevEnd;
363*7c568831SAndroid Build Coastguard Worker }
364*7c568831SAndroid Build Coastguard Worker
365*7c568831SAndroid Build Coastguard Worker static void
xmlC14NVisibleNsStackShift(xmlC14NVisibleNsStackPtr cur)366*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStackShift(xmlC14NVisibleNsStackPtr cur) {
367*7c568831SAndroid Build Coastguard Worker if(cur == NULL) {
368*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(NULL);
369*7c568831SAndroid Build Coastguard Worker return;
370*7c568831SAndroid Build Coastguard Worker }
371*7c568831SAndroid Build Coastguard Worker cur->nsPrevStart = cur->nsPrevEnd;
372*7c568831SAndroid Build Coastguard Worker cur->nsPrevEnd = cur->nsCurEnd;
373*7c568831SAndroid Build Coastguard Worker }
374*7c568831SAndroid Build Coastguard Worker
375*7c568831SAndroid Build Coastguard Worker static int
xmlC14NStrEqual(const xmlChar * str1,const xmlChar * str2)376*7c568831SAndroid Build Coastguard Worker xmlC14NStrEqual(const xmlChar *str1, const xmlChar *str2) {
377*7c568831SAndroid Build Coastguard Worker if (str1 == str2) return(1);
378*7c568831SAndroid Build Coastguard Worker if (str1 == NULL) return((*str2) == '\0');
379*7c568831SAndroid Build Coastguard Worker if (str2 == NULL) return((*str1) == '\0');
380*7c568831SAndroid Build Coastguard Worker do {
381*7c568831SAndroid Build Coastguard Worker if (*str1++ != *str2) return(0);
382*7c568831SAndroid Build Coastguard Worker } while (*str2++);
383*7c568831SAndroid Build Coastguard Worker return(1);
384*7c568831SAndroid Build Coastguard Worker }
385*7c568831SAndroid Build Coastguard Worker
386*7c568831SAndroid Build Coastguard Worker /**
387*7c568831SAndroid Build Coastguard Worker * xmlC14NVisibleNsStackFind:
388*7c568831SAndroid Build Coastguard Worker * @ctx: the C14N context
389*7c568831SAndroid Build Coastguard Worker * @ns: the namespace to check
390*7c568831SAndroid Build Coastguard Worker *
391*7c568831SAndroid Build Coastguard Worker * Checks whether the given namespace was already rendered or not
392*7c568831SAndroid Build Coastguard Worker *
393*7c568831SAndroid Build Coastguard Worker * Returns 1 if we already wrote this namespace or 0 otherwise
394*7c568831SAndroid Build Coastguard Worker */
395*7c568831SAndroid Build Coastguard Worker static int
xmlC14NVisibleNsStackFind(xmlC14NVisibleNsStackPtr cur,xmlNsPtr ns)396*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStackFind(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns)
397*7c568831SAndroid Build Coastguard Worker {
398*7c568831SAndroid Build Coastguard Worker int i;
399*7c568831SAndroid Build Coastguard Worker const xmlChar *prefix;
400*7c568831SAndroid Build Coastguard Worker const xmlChar *href;
401*7c568831SAndroid Build Coastguard Worker int has_empty_ns;
402*7c568831SAndroid Build Coastguard Worker
403*7c568831SAndroid Build Coastguard Worker if(cur == NULL) {
404*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(NULL);
405*7c568831SAndroid Build Coastguard Worker return (0);
406*7c568831SAndroid Build Coastguard Worker }
407*7c568831SAndroid Build Coastguard Worker
408*7c568831SAndroid Build Coastguard Worker /*
409*7c568831SAndroid Build Coastguard Worker * if the default namespace xmlns="" is not defined yet then
410*7c568831SAndroid Build Coastguard Worker * we do not want to print it out
411*7c568831SAndroid Build Coastguard Worker */
412*7c568831SAndroid Build Coastguard Worker prefix = ((ns == NULL) || (ns->prefix == NULL)) ? BAD_CAST "" : ns->prefix;
413*7c568831SAndroid Build Coastguard Worker href = ((ns == NULL) || (ns->href == NULL)) ? BAD_CAST "" : ns->href;
414*7c568831SAndroid Build Coastguard Worker has_empty_ns = (xmlC14NStrEqual(prefix, NULL) && xmlC14NStrEqual(href, NULL));
415*7c568831SAndroid Build Coastguard Worker
416*7c568831SAndroid Build Coastguard Worker if (cur->nsTab != NULL) {
417*7c568831SAndroid Build Coastguard Worker int start = (has_empty_ns) ? 0 : cur->nsPrevStart;
418*7c568831SAndroid Build Coastguard Worker for (i = cur->nsCurEnd - 1; i >= start; --i) {
419*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns1 = cur->nsTab[i];
420*7c568831SAndroid Build Coastguard Worker
421*7c568831SAndroid Build Coastguard Worker if(xmlC14NStrEqual(prefix, (ns1 != NULL) ? ns1->prefix : NULL)) {
422*7c568831SAndroid Build Coastguard Worker return(xmlC14NStrEqual(href, (ns1 != NULL) ? ns1->href : NULL));
423*7c568831SAndroid Build Coastguard Worker }
424*7c568831SAndroid Build Coastguard Worker }
425*7c568831SAndroid Build Coastguard Worker }
426*7c568831SAndroid Build Coastguard Worker return(has_empty_ns);
427*7c568831SAndroid Build Coastguard Worker }
428*7c568831SAndroid Build Coastguard Worker
429*7c568831SAndroid Build Coastguard Worker static int
xmlExcC14NVisibleNsStackFind(xmlC14NVisibleNsStackPtr cur,xmlNsPtr ns,xmlC14NCtxPtr ctx)430*7c568831SAndroid Build Coastguard Worker xmlExcC14NVisibleNsStackFind(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlC14NCtxPtr ctx) {
431*7c568831SAndroid Build Coastguard Worker int i;
432*7c568831SAndroid Build Coastguard Worker const xmlChar *prefix;
433*7c568831SAndroid Build Coastguard Worker const xmlChar *href;
434*7c568831SAndroid Build Coastguard Worker int has_empty_ns;
435*7c568831SAndroid Build Coastguard Worker
436*7c568831SAndroid Build Coastguard Worker if(cur == NULL) {
437*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(ctx);
438*7c568831SAndroid Build Coastguard Worker return (0);
439*7c568831SAndroid Build Coastguard Worker }
440*7c568831SAndroid Build Coastguard Worker
441*7c568831SAndroid Build Coastguard Worker /*
442*7c568831SAndroid Build Coastguard Worker * if the default namespace xmlns="" is not defined yet then
443*7c568831SAndroid Build Coastguard Worker * we do not want to print it out
444*7c568831SAndroid Build Coastguard Worker */
445*7c568831SAndroid Build Coastguard Worker prefix = ((ns == NULL) || (ns->prefix == NULL)) ? BAD_CAST "" : ns->prefix;
446*7c568831SAndroid Build Coastguard Worker href = ((ns == NULL) || (ns->href == NULL)) ? BAD_CAST "" : ns->href;
447*7c568831SAndroid Build Coastguard Worker has_empty_ns = (xmlC14NStrEqual(prefix, NULL) && xmlC14NStrEqual(href, NULL));
448*7c568831SAndroid Build Coastguard Worker
449*7c568831SAndroid Build Coastguard Worker if (cur->nsTab != NULL) {
450*7c568831SAndroid Build Coastguard Worker int start = 0;
451*7c568831SAndroid Build Coastguard Worker for (i = cur->nsCurEnd - 1; i >= start; --i) {
452*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns1 = cur->nsTab[i];
453*7c568831SAndroid Build Coastguard Worker
454*7c568831SAndroid Build Coastguard Worker if(xmlC14NStrEqual(prefix, (ns1 != NULL) ? ns1->prefix : NULL)) {
455*7c568831SAndroid Build Coastguard Worker if(xmlC14NStrEqual(href, (ns1 != NULL) ? ns1->href : NULL)) {
456*7c568831SAndroid Build Coastguard Worker return(xmlC14NIsVisible(ctx, ns1, cur->nodeTab[i]));
457*7c568831SAndroid Build Coastguard Worker } else {
458*7c568831SAndroid Build Coastguard Worker return(0);
459*7c568831SAndroid Build Coastguard Worker }
460*7c568831SAndroid Build Coastguard Worker }
461*7c568831SAndroid Build Coastguard Worker }
462*7c568831SAndroid Build Coastguard Worker }
463*7c568831SAndroid Build Coastguard Worker return(has_empty_ns);
464*7c568831SAndroid Build Coastguard Worker }
465*7c568831SAndroid Build Coastguard Worker
466*7c568831SAndroid Build Coastguard Worker
467*7c568831SAndroid Build Coastguard Worker
468*7c568831SAndroid Build Coastguard Worker
469*7c568831SAndroid Build Coastguard Worker /**
470*7c568831SAndroid Build Coastguard Worker * xmlC14NIsXmlNs:
471*7c568831SAndroid Build Coastguard Worker * @ns: the namespace to check
472*7c568831SAndroid Build Coastguard Worker *
473*7c568831SAndroid Build Coastguard Worker * Checks whether the given namespace is a default "xml:" namespace
474*7c568831SAndroid Build Coastguard Worker * with href="http://www.w3.org/XML/1998/namespace"
475*7c568831SAndroid Build Coastguard Worker *
476*7c568831SAndroid Build Coastguard Worker * Returns 1 if the node is default or 0 otherwise
477*7c568831SAndroid Build Coastguard Worker */
478*7c568831SAndroid Build Coastguard Worker
479*7c568831SAndroid Build Coastguard Worker /* todo: make it a define? */
480*7c568831SAndroid Build Coastguard Worker static int
xmlC14NIsXmlNs(xmlNsPtr ns)481*7c568831SAndroid Build Coastguard Worker xmlC14NIsXmlNs(xmlNsPtr ns)
482*7c568831SAndroid Build Coastguard Worker {
483*7c568831SAndroid Build Coastguard Worker return ((ns != NULL) &&
484*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(ns->prefix, BAD_CAST "xml")) &&
485*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(ns->href, XML_XML_NAMESPACE)));
486*7c568831SAndroid Build Coastguard Worker }
487*7c568831SAndroid Build Coastguard Worker
488*7c568831SAndroid Build Coastguard Worker
489*7c568831SAndroid Build Coastguard Worker /**
490*7c568831SAndroid Build Coastguard Worker * xmlC14NNsCompare:
491*7c568831SAndroid Build Coastguard Worker * @ns1: the pointer to first namespace
492*7c568831SAndroid Build Coastguard Worker * @ns2: the pointer to second namespace
493*7c568831SAndroid Build Coastguard Worker *
494*7c568831SAndroid Build Coastguard Worker * Compares the namespaces by names (prefixes).
495*7c568831SAndroid Build Coastguard Worker *
496*7c568831SAndroid Build Coastguard Worker * Returns -1 if ns1 < ns2, 0 if ns1 == ns2 or 1 if ns1 > ns2.
497*7c568831SAndroid Build Coastguard Worker */
498*7c568831SAndroid Build Coastguard Worker static int
xmlC14NNsCompare(const void * data1,const void * data2)499*7c568831SAndroid Build Coastguard Worker xmlC14NNsCompare(const void *data1, const void *data2)
500*7c568831SAndroid Build Coastguard Worker {
501*7c568831SAndroid Build Coastguard Worker const xmlNs *ns1 = data1;
502*7c568831SAndroid Build Coastguard Worker const xmlNs *ns2 = data2;
503*7c568831SAndroid Build Coastguard Worker if (ns1 == ns2)
504*7c568831SAndroid Build Coastguard Worker return (0);
505*7c568831SAndroid Build Coastguard Worker if (ns1 == NULL)
506*7c568831SAndroid Build Coastguard Worker return (-1);
507*7c568831SAndroid Build Coastguard Worker if (ns2 == NULL)
508*7c568831SAndroid Build Coastguard Worker return (1);
509*7c568831SAndroid Build Coastguard Worker
510*7c568831SAndroid Build Coastguard Worker return (xmlStrcmp(ns1->prefix, ns2->prefix));
511*7c568831SAndroid Build Coastguard Worker }
512*7c568831SAndroid Build Coastguard Worker
513*7c568831SAndroid Build Coastguard Worker
514*7c568831SAndroid Build Coastguard Worker /**
515*7c568831SAndroid Build Coastguard Worker * xmlC14NPrintNamespaces:
516*7c568831SAndroid Build Coastguard Worker * @ns: the pointer to namespace
517*7c568831SAndroid Build Coastguard Worker * @ctx: the C14N context
518*7c568831SAndroid Build Coastguard Worker *
519*7c568831SAndroid Build Coastguard Worker * Prints the given namespace to the output buffer from C14N context.
520*7c568831SAndroid Build Coastguard Worker *
521*7c568831SAndroid Build Coastguard Worker * Returns 1 on success or 0 on fail.
522*7c568831SAndroid Build Coastguard Worker */
523*7c568831SAndroid Build Coastguard Worker static int
xmlC14NPrintNamespaces(const xmlNs * ns,xmlC14NCtxPtr ctx)524*7c568831SAndroid Build Coastguard Worker xmlC14NPrintNamespaces(const xmlNs *ns, xmlC14NCtxPtr ctx)
525*7c568831SAndroid Build Coastguard Worker {
526*7c568831SAndroid Build Coastguard Worker
527*7c568831SAndroid Build Coastguard Worker if ((ns == NULL) || (ctx == NULL)) {
528*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(ctx);
529*7c568831SAndroid Build Coastguard Worker return 0;
530*7c568831SAndroid Build Coastguard Worker }
531*7c568831SAndroid Build Coastguard Worker
532*7c568831SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
533*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, " xmlns:");
534*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, (const char *) ns->prefix);
535*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, "=");
536*7c568831SAndroid Build Coastguard Worker } else {
537*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, " xmlns=");
538*7c568831SAndroid Build Coastguard Worker }
539*7c568831SAndroid Build Coastguard Worker if(ns->href != NULL) {
540*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteQuotedString(ctx->buf, ns->href);
541*7c568831SAndroid Build Coastguard Worker } else {
542*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, "\"\"");
543*7c568831SAndroid Build Coastguard Worker }
544*7c568831SAndroid Build Coastguard Worker return (1);
545*7c568831SAndroid Build Coastguard Worker }
546*7c568831SAndroid Build Coastguard Worker
547*7c568831SAndroid Build Coastguard Worker static int
xmlC14NPrintNamespacesWalker(const void * ns,void * ctx)548*7c568831SAndroid Build Coastguard Worker xmlC14NPrintNamespacesWalker(const void *ns, void *ctx) {
549*7c568831SAndroid Build Coastguard Worker return xmlC14NPrintNamespaces(ns, ctx);
550*7c568831SAndroid Build Coastguard Worker }
551*7c568831SAndroid Build Coastguard Worker
552*7c568831SAndroid Build Coastguard Worker /**
553*7c568831SAndroid Build Coastguard Worker * xmlC14NProcessNamespacesAxis:
554*7c568831SAndroid Build Coastguard Worker * @ctx: the C14N context
555*7c568831SAndroid Build Coastguard Worker * @node: the current node
556*7c568831SAndroid Build Coastguard Worker *
557*7c568831SAndroid Build Coastguard Worker * Prints out canonical namespace axis of the current node to the
558*7c568831SAndroid Build Coastguard Worker * buffer from C14N context as follows
559*7c568831SAndroid Build Coastguard Worker *
560*7c568831SAndroid Build Coastguard Worker * Canonical XML v 1.0 (http://www.w3.org/TR/xml-c14n)
561*7c568831SAndroid Build Coastguard Worker *
562*7c568831SAndroid Build Coastguard Worker * Namespace Axis
563*7c568831SAndroid Build Coastguard Worker * Consider a list L containing only namespace nodes in the
564*7c568831SAndroid Build Coastguard Worker * axis and in the node-set in lexicographic order (ascending). To begin
565*7c568831SAndroid Build Coastguard Worker * processing L, if the first node is not the default namespace node (a node
566*7c568831SAndroid Build Coastguard Worker * with no namespace URI and no local name), then generate a space followed
567*7c568831SAndroid Build Coastguard Worker * by xmlns="" if and only if the following conditions are met:
568*7c568831SAndroid Build Coastguard Worker * - the element E that owns the axis is in the node-set
569*7c568831SAndroid Build Coastguard Worker * - The nearest ancestor element of E in the node-set has a default
570*7c568831SAndroid Build Coastguard Worker * namespace node in the node-set (default namespace nodes always
571*7c568831SAndroid Build Coastguard Worker * have non-empty values in XPath)
572*7c568831SAndroid Build Coastguard Worker * The latter condition eliminates unnecessary occurrences of xmlns="" in
573*7c568831SAndroid Build Coastguard Worker * the canonical form since an element only receives an xmlns="" if its
574*7c568831SAndroid Build Coastguard Worker * default namespace is empty and if it has an immediate parent in the
575*7c568831SAndroid Build Coastguard Worker * canonical form that has a non-empty default namespace. To finish
576*7c568831SAndroid Build Coastguard Worker * processing L, simply process every namespace node in L, except omit
577*7c568831SAndroid Build Coastguard Worker * namespace node with local name xml, which defines the xml prefix,
578*7c568831SAndroid Build Coastguard Worker * if its string value is http://www.w3.org/XML/1998/namespace.
579*7c568831SAndroid Build Coastguard Worker *
580*7c568831SAndroid Build Coastguard Worker * Exclusive XML Canonicalization v 1.0 (http://www.w3.org/TR/xml-exc-c14n)
581*7c568831SAndroid Build Coastguard Worker * Canonical XML applied to a document subset requires the search of the
582*7c568831SAndroid Build Coastguard Worker * ancestor nodes of each orphan element node for attributes in the xml
583*7c568831SAndroid Build Coastguard Worker * namespace, such as xml:lang and xml:space. These are copied into the
584*7c568831SAndroid Build Coastguard Worker * element node except if a declaration of the same attribute is already
585*7c568831SAndroid Build Coastguard Worker * in the attribute axis of the element (whether or not it is included in
586*7c568831SAndroid Build Coastguard Worker * the document subset). This search and copying are omitted from the
587*7c568831SAndroid Build Coastguard Worker * Exclusive XML Canonicalization method.
588*7c568831SAndroid Build Coastguard Worker *
589*7c568831SAndroid Build Coastguard Worker * Returns 0 on success or -1 on fail.
590*7c568831SAndroid Build Coastguard Worker */
591*7c568831SAndroid Build Coastguard Worker static int
xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx,xmlNodePtr cur,int visible)592*7c568831SAndroid Build Coastguard Worker xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
593*7c568831SAndroid Build Coastguard Worker {
594*7c568831SAndroid Build Coastguard Worker xmlNodePtr n;
595*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns, tmp;
596*7c568831SAndroid Build Coastguard Worker xmlListPtr list;
597*7c568831SAndroid Build Coastguard Worker int already_rendered;
598*7c568831SAndroid Build Coastguard Worker int has_empty_ns = 0;
599*7c568831SAndroid Build Coastguard Worker
600*7c568831SAndroid Build Coastguard Worker if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
601*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(ctx);
602*7c568831SAndroid Build Coastguard Worker return (-1);
603*7c568831SAndroid Build Coastguard Worker }
604*7c568831SAndroid Build Coastguard Worker
605*7c568831SAndroid Build Coastguard Worker /*
606*7c568831SAndroid Build Coastguard Worker * Create a sorted list to store element namespaces
607*7c568831SAndroid Build Coastguard Worker */
608*7c568831SAndroid Build Coastguard Worker list = xmlListCreate(NULL, xmlC14NNsCompare);
609*7c568831SAndroid Build Coastguard Worker if (list == NULL) {
610*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
611*7c568831SAndroid Build Coastguard Worker return (-1);
612*7c568831SAndroid Build Coastguard Worker }
613*7c568831SAndroid Build Coastguard Worker
614*7c568831SAndroid Build Coastguard Worker /* check all namespaces */
615*7c568831SAndroid Build Coastguard Worker for(n = cur; n != NULL; n = n->parent) {
616*7c568831SAndroid Build Coastguard Worker for(ns = n->nsDef; ns != NULL; ns = ns->next) {
617*7c568831SAndroid Build Coastguard Worker tmp = xmlSearchNs(cur->doc, cur, ns->prefix);
618*7c568831SAndroid Build Coastguard Worker
619*7c568831SAndroid Build Coastguard Worker if((tmp == ns) && !xmlC14NIsXmlNs(ns) && xmlC14NIsVisible(ctx, ns, cur)) {
620*7c568831SAndroid Build Coastguard Worker already_rendered = xmlC14NVisibleNsStackFind(ctx->ns_rendered, ns);
621*7c568831SAndroid Build Coastguard Worker if(visible) {
622*7c568831SAndroid Build Coastguard Worker if (xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur) < 0) {
623*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
624*7c568831SAndroid Build Coastguard Worker goto error;
625*7c568831SAndroid Build Coastguard Worker }
626*7c568831SAndroid Build Coastguard Worker }
627*7c568831SAndroid Build Coastguard Worker if(!already_rendered) {
628*7c568831SAndroid Build Coastguard Worker xmlListInsert(list, ns);
629*7c568831SAndroid Build Coastguard Worker }
630*7c568831SAndroid Build Coastguard Worker if(xmlStrlen(ns->prefix) == 0) {
631*7c568831SAndroid Build Coastguard Worker has_empty_ns = 1;
632*7c568831SAndroid Build Coastguard Worker }
633*7c568831SAndroid Build Coastguard Worker }
634*7c568831SAndroid Build Coastguard Worker }
635*7c568831SAndroid Build Coastguard Worker }
636*7c568831SAndroid Build Coastguard Worker
637*7c568831SAndroid Build Coastguard Worker /**
638*7c568831SAndroid Build Coastguard Worker * if the first node is not the default namespace node (a node with no
639*7c568831SAndroid Build Coastguard Worker * namespace URI and no local name), then generate a space followed by
640*7c568831SAndroid Build Coastguard Worker * xmlns="" if and only if the following conditions are met:
641*7c568831SAndroid Build Coastguard Worker * - the element E that owns the axis is in the node-set
642*7c568831SAndroid Build Coastguard Worker * - the nearest ancestor element of E in the node-set has a default
643*7c568831SAndroid Build Coastguard Worker * namespace node in the node-set (default namespace nodes always
644*7c568831SAndroid Build Coastguard Worker * have non-empty values in XPath)
645*7c568831SAndroid Build Coastguard Worker */
646*7c568831SAndroid Build Coastguard Worker if(visible && !has_empty_ns) {
647*7c568831SAndroid Build Coastguard Worker xmlNs ns_default;
648*7c568831SAndroid Build Coastguard Worker
649*7c568831SAndroid Build Coastguard Worker memset(&ns_default, 0, sizeof(ns_default));
650*7c568831SAndroid Build Coastguard Worker if(!xmlC14NVisibleNsStackFind(ctx->ns_rendered, &ns_default)) {
651*7c568831SAndroid Build Coastguard Worker xmlC14NPrintNamespaces(&ns_default, ctx);
652*7c568831SAndroid Build Coastguard Worker }
653*7c568831SAndroid Build Coastguard Worker }
654*7c568831SAndroid Build Coastguard Worker
655*7c568831SAndroid Build Coastguard Worker
656*7c568831SAndroid Build Coastguard Worker /*
657*7c568831SAndroid Build Coastguard Worker * print out all elements from list
658*7c568831SAndroid Build Coastguard Worker */
659*7c568831SAndroid Build Coastguard Worker xmlListWalk(list, xmlC14NPrintNamespacesWalker, (void *) ctx);
660*7c568831SAndroid Build Coastguard Worker
661*7c568831SAndroid Build Coastguard Worker /*
662*7c568831SAndroid Build Coastguard Worker * Cleanup
663*7c568831SAndroid Build Coastguard Worker */
664*7c568831SAndroid Build Coastguard Worker error:
665*7c568831SAndroid Build Coastguard Worker xmlListDelete(list);
666*7c568831SAndroid Build Coastguard Worker return (0);
667*7c568831SAndroid Build Coastguard Worker }
668*7c568831SAndroid Build Coastguard Worker
669*7c568831SAndroid Build Coastguard Worker
670*7c568831SAndroid Build Coastguard Worker /**
671*7c568831SAndroid Build Coastguard Worker * xmlExcC14NProcessNamespacesAxis:
672*7c568831SAndroid Build Coastguard Worker * @ctx: the C14N context
673*7c568831SAndroid Build Coastguard Worker * @node: the current node
674*7c568831SAndroid Build Coastguard Worker *
675*7c568831SAndroid Build Coastguard Worker * Prints out exclusive canonical namespace axis of the current node to the
676*7c568831SAndroid Build Coastguard Worker * buffer from C14N context as follows
677*7c568831SAndroid Build Coastguard Worker *
678*7c568831SAndroid Build Coastguard Worker * Exclusive XML Canonicalization
679*7c568831SAndroid Build Coastguard Worker * http://www.w3.org/TR/xml-exc-c14n
680*7c568831SAndroid Build Coastguard Worker *
681*7c568831SAndroid Build Coastguard Worker * If the element node is in the XPath subset then output the node in
682*7c568831SAndroid Build Coastguard Worker * accordance with Canonical XML except for namespace nodes which are
683*7c568831SAndroid Build Coastguard Worker * rendered as follows:
684*7c568831SAndroid Build Coastguard Worker *
685*7c568831SAndroid Build Coastguard Worker * 1. Render each namespace node iff:
686*7c568831SAndroid Build Coastguard Worker * * it is visibly utilized by the immediate parent element or one of
687*7c568831SAndroid Build Coastguard Worker * its attributes, or is present in InclusiveNamespaces PrefixList, and
688*7c568831SAndroid Build Coastguard Worker * * its prefix and value do not appear in ns_rendered. ns_rendered is
689*7c568831SAndroid Build Coastguard Worker * obtained by popping the state stack in order to obtain a list of
690*7c568831SAndroid Build Coastguard Worker * prefixes and their values which have already been rendered by
691*7c568831SAndroid Build Coastguard Worker * an output ancestor of the namespace node's parent element.
692*7c568831SAndroid Build Coastguard Worker * 2. Append the rendered namespace node to the list ns_rendered of namespace
693*7c568831SAndroid Build Coastguard Worker * nodes rendered by output ancestors. Push ns_rendered on state stack and
694*7c568831SAndroid Build Coastguard Worker * recurse.
695*7c568831SAndroid Build Coastguard Worker * 3. After the recursion returns, pop thestate stack.
696*7c568831SAndroid Build Coastguard Worker *
697*7c568831SAndroid Build Coastguard Worker *
698*7c568831SAndroid Build Coastguard Worker * Returns 0 on success or -1 on fail.
699*7c568831SAndroid Build Coastguard Worker */
700*7c568831SAndroid Build Coastguard Worker static int
xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx,xmlNodePtr cur,int visible)701*7c568831SAndroid Build Coastguard Worker xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
702*7c568831SAndroid Build Coastguard Worker {
703*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns;
704*7c568831SAndroid Build Coastguard Worker xmlListPtr list;
705*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attr;
706*7c568831SAndroid Build Coastguard Worker int already_rendered;
707*7c568831SAndroid Build Coastguard Worker int has_empty_ns = 0;
708*7c568831SAndroid Build Coastguard Worker int has_visibly_utilized_empty_ns = 0;
709*7c568831SAndroid Build Coastguard Worker int has_empty_ns_in_inclusive_list = 0;
710*7c568831SAndroid Build Coastguard Worker
711*7c568831SAndroid Build Coastguard Worker if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
712*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(ctx);
713*7c568831SAndroid Build Coastguard Worker return (-1);
714*7c568831SAndroid Build Coastguard Worker }
715*7c568831SAndroid Build Coastguard Worker
716*7c568831SAndroid Build Coastguard Worker if(!xmlC14NIsExclusive(ctx)) {
717*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(ctx);
718*7c568831SAndroid Build Coastguard Worker return (-1);
719*7c568831SAndroid Build Coastguard Worker
720*7c568831SAndroid Build Coastguard Worker }
721*7c568831SAndroid Build Coastguard Worker
722*7c568831SAndroid Build Coastguard Worker /*
723*7c568831SAndroid Build Coastguard Worker * Create a sorted list to store element namespaces
724*7c568831SAndroid Build Coastguard Worker */
725*7c568831SAndroid Build Coastguard Worker list = xmlListCreate(NULL, xmlC14NNsCompare);
726*7c568831SAndroid Build Coastguard Worker if (list == NULL) {
727*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
728*7c568831SAndroid Build Coastguard Worker return (-1);
729*7c568831SAndroid Build Coastguard Worker }
730*7c568831SAndroid Build Coastguard Worker
731*7c568831SAndroid Build Coastguard Worker /*
732*7c568831SAndroid Build Coastguard Worker * process inclusive namespaces:
733*7c568831SAndroid Build Coastguard Worker * All namespace nodes appearing on inclusive ns list are
734*7c568831SAndroid Build Coastguard Worker * handled as provided in Canonical XML
735*7c568831SAndroid Build Coastguard Worker */
736*7c568831SAndroid Build Coastguard Worker if(ctx->inclusive_ns_prefixes != NULL) {
737*7c568831SAndroid Build Coastguard Worker xmlChar *prefix;
738*7c568831SAndroid Build Coastguard Worker int i;
739*7c568831SAndroid Build Coastguard Worker
740*7c568831SAndroid Build Coastguard Worker for (i = 0; ctx->inclusive_ns_prefixes[i] != NULL; ++i) {
741*7c568831SAndroid Build Coastguard Worker prefix = ctx->inclusive_ns_prefixes[i];
742*7c568831SAndroid Build Coastguard Worker /*
743*7c568831SAndroid Build Coastguard Worker * Special values for namespace with empty prefix
744*7c568831SAndroid Build Coastguard Worker */
745*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(prefix, BAD_CAST "#default")
746*7c568831SAndroid Build Coastguard Worker || xmlStrEqual(prefix, BAD_CAST "")) {
747*7c568831SAndroid Build Coastguard Worker prefix = NULL;
748*7c568831SAndroid Build Coastguard Worker has_empty_ns_in_inclusive_list = 1;
749*7c568831SAndroid Build Coastguard Worker }
750*7c568831SAndroid Build Coastguard Worker
751*7c568831SAndroid Build Coastguard Worker ns = xmlSearchNs(cur->doc, cur, prefix);
752*7c568831SAndroid Build Coastguard Worker if((ns != NULL) && !xmlC14NIsXmlNs(ns) && xmlC14NIsVisible(ctx, ns, cur)) {
753*7c568831SAndroid Build Coastguard Worker already_rendered = xmlC14NVisibleNsStackFind(ctx->ns_rendered, ns);
754*7c568831SAndroid Build Coastguard Worker if(visible) {
755*7c568831SAndroid Build Coastguard Worker if (xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur) < 0) {
756*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
757*7c568831SAndroid Build Coastguard Worker goto error;
758*7c568831SAndroid Build Coastguard Worker }
759*7c568831SAndroid Build Coastguard Worker }
760*7c568831SAndroid Build Coastguard Worker if(!already_rendered) {
761*7c568831SAndroid Build Coastguard Worker xmlListInsert(list, ns);
762*7c568831SAndroid Build Coastguard Worker }
763*7c568831SAndroid Build Coastguard Worker if(xmlStrlen(ns->prefix) == 0) {
764*7c568831SAndroid Build Coastguard Worker has_empty_ns = 1;
765*7c568831SAndroid Build Coastguard Worker }
766*7c568831SAndroid Build Coastguard Worker }
767*7c568831SAndroid Build Coastguard Worker }
768*7c568831SAndroid Build Coastguard Worker }
769*7c568831SAndroid Build Coastguard Worker
770*7c568831SAndroid Build Coastguard Worker /* add node namespace */
771*7c568831SAndroid Build Coastguard Worker if(cur->ns != NULL) {
772*7c568831SAndroid Build Coastguard Worker ns = cur->ns;
773*7c568831SAndroid Build Coastguard Worker } else {
774*7c568831SAndroid Build Coastguard Worker ns = xmlSearchNs(cur->doc, cur, NULL);
775*7c568831SAndroid Build Coastguard Worker has_visibly_utilized_empty_ns = 1;
776*7c568831SAndroid Build Coastguard Worker }
777*7c568831SAndroid Build Coastguard Worker if((ns != NULL) && !xmlC14NIsXmlNs(ns)) {
778*7c568831SAndroid Build Coastguard Worker if(visible && xmlC14NIsVisible(ctx, ns, cur)) {
779*7c568831SAndroid Build Coastguard Worker if(!xmlExcC14NVisibleNsStackFind(ctx->ns_rendered, ns, ctx)) {
780*7c568831SAndroid Build Coastguard Worker xmlListInsert(list, ns);
781*7c568831SAndroid Build Coastguard Worker }
782*7c568831SAndroid Build Coastguard Worker }
783*7c568831SAndroid Build Coastguard Worker if(visible) {
784*7c568831SAndroid Build Coastguard Worker if (xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur) < 0) {
785*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
786*7c568831SAndroid Build Coastguard Worker goto error;
787*7c568831SAndroid Build Coastguard Worker }
788*7c568831SAndroid Build Coastguard Worker }
789*7c568831SAndroid Build Coastguard Worker if(xmlStrlen(ns->prefix) == 0) {
790*7c568831SAndroid Build Coastguard Worker has_empty_ns = 1;
791*7c568831SAndroid Build Coastguard Worker }
792*7c568831SAndroid Build Coastguard Worker }
793*7c568831SAndroid Build Coastguard Worker
794*7c568831SAndroid Build Coastguard Worker
795*7c568831SAndroid Build Coastguard Worker /* add attributes */
796*7c568831SAndroid Build Coastguard Worker for(attr = cur->properties; attr != NULL; attr = attr->next) {
797*7c568831SAndroid Build Coastguard Worker /*
798*7c568831SAndroid Build Coastguard Worker * we need to check that attribute is visible and has non
799*7c568831SAndroid Build Coastguard Worker * default namespace (XML Namespaces: "default namespaces
800*7c568831SAndroid Build Coastguard Worker * do not apply directly to attributes")
801*7c568831SAndroid Build Coastguard Worker */
802*7c568831SAndroid Build Coastguard Worker if((attr->ns != NULL) && !xmlC14NIsXmlNs(attr->ns) && xmlC14NIsVisible(ctx, attr, cur)) {
803*7c568831SAndroid Build Coastguard Worker already_rendered = xmlExcC14NVisibleNsStackFind(ctx->ns_rendered, attr->ns, ctx);
804*7c568831SAndroid Build Coastguard Worker if (xmlC14NVisibleNsStackAdd(ctx->ns_rendered, attr->ns, cur) < 0) {
805*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
806*7c568831SAndroid Build Coastguard Worker goto error;
807*7c568831SAndroid Build Coastguard Worker }
808*7c568831SAndroid Build Coastguard Worker if(!already_rendered && visible) {
809*7c568831SAndroid Build Coastguard Worker xmlListInsert(list, attr->ns);
810*7c568831SAndroid Build Coastguard Worker }
811*7c568831SAndroid Build Coastguard Worker if(xmlStrlen(attr->ns->prefix) == 0) {
812*7c568831SAndroid Build Coastguard Worker has_empty_ns = 1;
813*7c568831SAndroid Build Coastguard Worker }
814*7c568831SAndroid Build Coastguard Worker } else if((attr->ns != NULL) && (xmlStrlen(attr->ns->prefix) == 0) && (xmlStrlen(attr->ns->href) == 0)) {
815*7c568831SAndroid Build Coastguard Worker has_visibly_utilized_empty_ns = 1;
816*7c568831SAndroid Build Coastguard Worker }
817*7c568831SAndroid Build Coastguard Worker }
818*7c568831SAndroid Build Coastguard Worker
819*7c568831SAndroid Build Coastguard Worker /*
820*7c568831SAndroid Build Coastguard Worker * Process xmlns=""
821*7c568831SAndroid Build Coastguard Worker */
822*7c568831SAndroid Build Coastguard Worker if(visible && has_visibly_utilized_empty_ns &&
823*7c568831SAndroid Build Coastguard Worker !has_empty_ns && !has_empty_ns_in_inclusive_list) {
824*7c568831SAndroid Build Coastguard Worker xmlNs ns_default;
825*7c568831SAndroid Build Coastguard Worker
826*7c568831SAndroid Build Coastguard Worker memset(&ns_default, 0, sizeof(ns_default));
827*7c568831SAndroid Build Coastguard Worker
828*7c568831SAndroid Build Coastguard Worker already_rendered = xmlExcC14NVisibleNsStackFind(ctx->ns_rendered, &ns_default, ctx);
829*7c568831SAndroid Build Coastguard Worker if(!already_rendered) {
830*7c568831SAndroid Build Coastguard Worker xmlC14NPrintNamespaces(&ns_default, ctx);
831*7c568831SAndroid Build Coastguard Worker }
832*7c568831SAndroid Build Coastguard Worker } else if(visible && !has_empty_ns && has_empty_ns_in_inclusive_list) {
833*7c568831SAndroid Build Coastguard Worker xmlNs ns_default;
834*7c568831SAndroid Build Coastguard Worker
835*7c568831SAndroid Build Coastguard Worker memset(&ns_default, 0, sizeof(ns_default));
836*7c568831SAndroid Build Coastguard Worker if(!xmlC14NVisibleNsStackFind(ctx->ns_rendered, &ns_default)) {
837*7c568831SAndroid Build Coastguard Worker xmlC14NPrintNamespaces(&ns_default, ctx);
838*7c568831SAndroid Build Coastguard Worker }
839*7c568831SAndroid Build Coastguard Worker }
840*7c568831SAndroid Build Coastguard Worker
841*7c568831SAndroid Build Coastguard Worker
842*7c568831SAndroid Build Coastguard Worker
843*7c568831SAndroid Build Coastguard Worker /*
844*7c568831SAndroid Build Coastguard Worker * print out all elements from list
845*7c568831SAndroid Build Coastguard Worker */
846*7c568831SAndroid Build Coastguard Worker xmlListWalk(list, xmlC14NPrintNamespacesWalker, (void *) ctx);
847*7c568831SAndroid Build Coastguard Worker
848*7c568831SAndroid Build Coastguard Worker /*
849*7c568831SAndroid Build Coastguard Worker * Cleanup
850*7c568831SAndroid Build Coastguard Worker */
851*7c568831SAndroid Build Coastguard Worker error:
852*7c568831SAndroid Build Coastguard Worker xmlListDelete(list);
853*7c568831SAndroid Build Coastguard Worker return (0);
854*7c568831SAndroid Build Coastguard Worker }
855*7c568831SAndroid Build Coastguard Worker
856*7c568831SAndroid Build Coastguard Worker
857*7c568831SAndroid Build Coastguard Worker /**
858*7c568831SAndroid Build Coastguard Worker * xmlC14NIsXmlAttr:
859*7c568831SAndroid Build Coastguard Worker * @attr: the attr to check
860*7c568831SAndroid Build Coastguard Worker *
861*7c568831SAndroid Build Coastguard Worker * Checks whether the given attribute is a default "xml:" namespace
862*7c568831SAndroid Build Coastguard Worker * with href="http://www.w3.org/XML/1998/namespace"
863*7c568831SAndroid Build Coastguard Worker *
864*7c568831SAndroid Build Coastguard Worker * Returns 1 if the node is default or 0 otherwise
865*7c568831SAndroid Build Coastguard Worker */
866*7c568831SAndroid Build Coastguard Worker
867*7c568831SAndroid Build Coastguard Worker /* todo: make it a define? */
868*7c568831SAndroid Build Coastguard Worker static int
xmlC14NIsXmlAttr(xmlAttrPtr attr)869*7c568831SAndroid Build Coastguard Worker xmlC14NIsXmlAttr(xmlAttrPtr attr)
870*7c568831SAndroid Build Coastguard Worker {
871*7c568831SAndroid Build Coastguard Worker return ((attr->ns != NULL) &&
872*7c568831SAndroid Build Coastguard Worker (xmlC14NIsXmlNs(attr->ns) != 0));
873*7c568831SAndroid Build Coastguard Worker }
874*7c568831SAndroid Build Coastguard Worker
875*7c568831SAndroid Build Coastguard Worker
876*7c568831SAndroid Build Coastguard Worker /**
877*7c568831SAndroid Build Coastguard Worker * xmlC14NAttrsCompare:
878*7c568831SAndroid Build Coastguard Worker * @attr1: the pointer tls o first attr
879*7c568831SAndroid Build Coastguard Worker * @attr2: the pointer to second attr
880*7c568831SAndroid Build Coastguard Worker *
881*7c568831SAndroid Build Coastguard Worker * Prints the given attribute to the output buffer from C14N context.
882*7c568831SAndroid Build Coastguard Worker *
883*7c568831SAndroid Build Coastguard Worker * Returns -1 if attr1 < attr2, 0 if attr1 == attr2 or 1 if attr1 > attr2.
884*7c568831SAndroid Build Coastguard Worker */
885*7c568831SAndroid Build Coastguard Worker static int
xmlC14NAttrsCompare(const void * data1,const void * data2)886*7c568831SAndroid Build Coastguard Worker xmlC14NAttrsCompare(const void *data1, const void *data2)
887*7c568831SAndroid Build Coastguard Worker {
888*7c568831SAndroid Build Coastguard Worker const xmlAttr *attr1 = data1;
889*7c568831SAndroid Build Coastguard Worker const xmlAttr *attr2 = data2;
890*7c568831SAndroid Build Coastguard Worker int ret = 0;
891*7c568831SAndroid Build Coastguard Worker
892*7c568831SAndroid Build Coastguard Worker /*
893*7c568831SAndroid Build Coastguard Worker * Simple cases
894*7c568831SAndroid Build Coastguard Worker */
895*7c568831SAndroid Build Coastguard Worker if (attr1 == attr2)
896*7c568831SAndroid Build Coastguard Worker return (0);
897*7c568831SAndroid Build Coastguard Worker if (attr1 == NULL)
898*7c568831SAndroid Build Coastguard Worker return (-1);
899*7c568831SAndroid Build Coastguard Worker if (attr2 == NULL)
900*7c568831SAndroid Build Coastguard Worker return (1);
901*7c568831SAndroid Build Coastguard Worker if (attr1->ns == attr2->ns) {
902*7c568831SAndroid Build Coastguard Worker return (xmlStrcmp(attr1->name, attr2->name));
903*7c568831SAndroid Build Coastguard Worker }
904*7c568831SAndroid Build Coastguard Worker
905*7c568831SAndroid Build Coastguard Worker /*
906*7c568831SAndroid Build Coastguard Worker * Attributes in the default namespace are first
907*7c568831SAndroid Build Coastguard Worker * because the default namespace is not applied to
908*7c568831SAndroid Build Coastguard Worker * unqualified attributes
909*7c568831SAndroid Build Coastguard Worker */
910*7c568831SAndroid Build Coastguard Worker if (attr1->ns == NULL)
911*7c568831SAndroid Build Coastguard Worker return (-1);
912*7c568831SAndroid Build Coastguard Worker if (attr2->ns == NULL)
913*7c568831SAndroid Build Coastguard Worker return (1);
914*7c568831SAndroid Build Coastguard Worker if (attr1->ns->prefix == NULL)
915*7c568831SAndroid Build Coastguard Worker return (-1);
916*7c568831SAndroid Build Coastguard Worker if (attr2->ns->prefix == NULL)
917*7c568831SAndroid Build Coastguard Worker return (1);
918*7c568831SAndroid Build Coastguard Worker
919*7c568831SAndroid Build Coastguard Worker ret = xmlStrcmp(attr1->ns->href, attr2->ns->href);
920*7c568831SAndroid Build Coastguard Worker if (ret == 0) {
921*7c568831SAndroid Build Coastguard Worker ret = xmlStrcmp(attr1->name, attr2->name);
922*7c568831SAndroid Build Coastguard Worker }
923*7c568831SAndroid Build Coastguard Worker return (ret);
924*7c568831SAndroid Build Coastguard Worker }
925*7c568831SAndroid Build Coastguard Worker
926*7c568831SAndroid Build Coastguard Worker
927*7c568831SAndroid Build Coastguard Worker /**
928*7c568831SAndroid Build Coastguard Worker * xmlC14NPrintAttrs:
929*7c568831SAndroid Build Coastguard Worker * @attr: the pointer to attr
930*7c568831SAndroid Build Coastguard Worker * @ctx: the C14N context
931*7c568831SAndroid Build Coastguard Worker *
932*7c568831SAndroid Build Coastguard Worker * Prints out canonical attribute urrent node to the
933*7c568831SAndroid Build Coastguard Worker * buffer from C14N context as follows
934*7c568831SAndroid Build Coastguard Worker *
935*7c568831SAndroid Build Coastguard Worker * Canonical XML v 1.0 (http://www.w3.org/TR/xml-c14n)
936*7c568831SAndroid Build Coastguard Worker *
937*7c568831SAndroid Build Coastguard Worker * Returns 1 on success or 0 on fail.
938*7c568831SAndroid Build Coastguard Worker */
939*7c568831SAndroid Build Coastguard Worker static int
xmlC14NPrintAttrs(const void * data,void * user)940*7c568831SAndroid Build Coastguard Worker xmlC14NPrintAttrs(const void *data, void *user)
941*7c568831SAndroid Build Coastguard Worker {
942*7c568831SAndroid Build Coastguard Worker const xmlAttr *attr = data;
943*7c568831SAndroid Build Coastguard Worker xmlC14NCtxPtr ctx = (xmlC14NCtxPtr) user;
944*7c568831SAndroid Build Coastguard Worker xmlChar *value;
945*7c568831SAndroid Build Coastguard Worker xmlChar *buffer;
946*7c568831SAndroid Build Coastguard Worker
947*7c568831SAndroid Build Coastguard Worker if ((attr == NULL) || (ctx == NULL)) {
948*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(ctx);
949*7c568831SAndroid Build Coastguard Worker return (0);
950*7c568831SAndroid Build Coastguard Worker }
951*7c568831SAndroid Build Coastguard Worker
952*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, " ");
953*7c568831SAndroid Build Coastguard Worker if (attr->ns != NULL && xmlStrlen(attr->ns->prefix) > 0) {
954*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf,
955*7c568831SAndroid Build Coastguard Worker (const char *) attr->ns->prefix);
956*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, ":");
957*7c568831SAndroid Build Coastguard Worker }
958*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, (const char *) attr->name);
959*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, "=\"");
960*7c568831SAndroid Build Coastguard Worker
961*7c568831SAndroid Build Coastguard Worker value = xmlNodeListGetString(ctx->doc, attr->children, 1);
962*7c568831SAndroid Build Coastguard Worker /* todo: should we log an error if value==NULL ? */
963*7c568831SAndroid Build Coastguard Worker if (value != NULL) {
964*7c568831SAndroid Build Coastguard Worker buffer = xmlC11NNormalizeAttr(value);
965*7c568831SAndroid Build Coastguard Worker xmlFree(value);
966*7c568831SAndroid Build Coastguard Worker if (buffer != NULL) {
967*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, (const char *) buffer);
968*7c568831SAndroid Build Coastguard Worker xmlFree(buffer);
969*7c568831SAndroid Build Coastguard Worker } else {
970*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
971*7c568831SAndroid Build Coastguard Worker return (0);
972*7c568831SAndroid Build Coastguard Worker }
973*7c568831SAndroid Build Coastguard Worker }
974*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, "\"");
975*7c568831SAndroid Build Coastguard Worker return (1);
976*7c568831SAndroid Build Coastguard Worker }
977*7c568831SAndroid Build Coastguard Worker
978*7c568831SAndroid Build Coastguard Worker /**
979*7c568831SAndroid Build Coastguard Worker * xmlC14NFindHiddenParentAttr:
980*7c568831SAndroid Build Coastguard Worker *
981*7c568831SAndroid Build Coastguard Worker * Finds an attribute in a hidden parent node.
982*7c568831SAndroid Build Coastguard Worker *
983*7c568831SAndroid Build Coastguard Worker * Returns a pointer to the attribute node (if found) or NULL otherwise.
984*7c568831SAndroid Build Coastguard Worker */
985*7c568831SAndroid Build Coastguard Worker static xmlAttrPtr
xmlC14NFindHiddenParentAttr(xmlC14NCtxPtr ctx,xmlNodePtr cur,const xmlChar * name,const xmlChar * ns)986*7c568831SAndroid Build Coastguard Worker xmlC14NFindHiddenParentAttr(xmlC14NCtxPtr ctx, xmlNodePtr cur, const xmlChar * name, const xmlChar * ns)
987*7c568831SAndroid Build Coastguard Worker {
988*7c568831SAndroid Build Coastguard Worker xmlAttrPtr res;
989*7c568831SAndroid Build Coastguard Worker while((cur != NULL) && (!xmlC14NIsVisible(ctx, cur, cur->parent))) {
990*7c568831SAndroid Build Coastguard Worker res = xmlHasNsProp(cur, name, ns);
991*7c568831SAndroid Build Coastguard Worker if(res != NULL) {
992*7c568831SAndroid Build Coastguard Worker return res;
993*7c568831SAndroid Build Coastguard Worker }
994*7c568831SAndroid Build Coastguard Worker
995*7c568831SAndroid Build Coastguard Worker cur = cur->parent;
996*7c568831SAndroid Build Coastguard Worker }
997*7c568831SAndroid Build Coastguard Worker
998*7c568831SAndroid Build Coastguard Worker return NULL;
999*7c568831SAndroid Build Coastguard Worker }
1000*7c568831SAndroid Build Coastguard Worker
1001*7c568831SAndroid Build Coastguard Worker /**
1002*7c568831SAndroid Build Coastguard Worker * xmlC14NFixupBaseAttr:
1003*7c568831SAndroid Build Coastguard Worker *
1004*7c568831SAndroid Build Coastguard Worker * Fixes up the xml:base attribute
1005*7c568831SAndroid Build Coastguard Worker *
1006*7c568831SAndroid Build Coastguard Worker * Returns the newly created attribute or NULL
1007*7c568831SAndroid Build Coastguard Worker */
1008*7c568831SAndroid Build Coastguard Worker static xmlAttrPtr
xmlC14NFixupBaseAttr(xmlC14NCtxPtr ctx,xmlAttrPtr xml_base_attr)1009*7c568831SAndroid Build Coastguard Worker xmlC14NFixupBaseAttr(xmlC14NCtxPtr ctx, xmlAttrPtr xml_base_attr)
1010*7c568831SAndroid Build Coastguard Worker {
1011*7c568831SAndroid Build Coastguard Worker xmlChar * res = NULL;
1012*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur;
1013*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attr;
1014*7c568831SAndroid Build Coastguard Worker xmlChar * tmp_str;
1015*7c568831SAndroid Build Coastguard Worker xmlChar * tmp_str2;
1016*7c568831SAndroid Build Coastguard Worker int tmp_str_len;
1017*7c568831SAndroid Build Coastguard Worker
1018*7c568831SAndroid Build Coastguard Worker if ((ctx == NULL) || (xml_base_attr == NULL) || (xml_base_attr->parent == NULL)) {
1019*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(ctx);
1020*7c568831SAndroid Build Coastguard Worker return (NULL);
1021*7c568831SAndroid Build Coastguard Worker }
1022*7c568831SAndroid Build Coastguard Worker
1023*7c568831SAndroid Build Coastguard Worker /* start from current value */
1024*7c568831SAndroid Build Coastguard Worker res = xmlNodeListGetString(ctx->doc, xml_base_attr->children, 1);
1025*7c568831SAndroid Build Coastguard Worker if(res == NULL) {
1026*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
1027*7c568831SAndroid Build Coastguard Worker return (NULL);
1028*7c568831SAndroid Build Coastguard Worker }
1029*7c568831SAndroid Build Coastguard Worker
1030*7c568831SAndroid Build Coastguard Worker /* go up the stack until we find a node that we rendered already */
1031*7c568831SAndroid Build Coastguard Worker cur = xml_base_attr->parent->parent;
1032*7c568831SAndroid Build Coastguard Worker while((cur != NULL) && (!xmlC14NIsVisible(ctx, cur, cur->parent))) {
1033*7c568831SAndroid Build Coastguard Worker int code;
1034*7c568831SAndroid Build Coastguard Worker
1035*7c568831SAndroid Build Coastguard Worker attr = xmlHasNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE);
1036*7c568831SAndroid Build Coastguard Worker if(attr != NULL) {
1037*7c568831SAndroid Build Coastguard Worker /* get attr value */
1038*7c568831SAndroid Build Coastguard Worker tmp_str = xmlNodeListGetString(ctx->doc, attr->children, 1);
1039*7c568831SAndroid Build Coastguard Worker if(tmp_str == NULL) {
1040*7c568831SAndroid Build Coastguard Worker xmlFree(res);
1041*7c568831SAndroid Build Coastguard Worker
1042*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
1043*7c568831SAndroid Build Coastguard Worker return (NULL);
1044*7c568831SAndroid Build Coastguard Worker }
1045*7c568831SAndroid Build Coastguard Worker
1046*7c568831SAndroid Build Coastguard Worker /* we need to add '/' if our current base uri ends with '..' or '.'
1047*7c568831SAndroid Build Coastguard Worker to ensure that we are forced to go "up" all the time */
1048*7c568831SAndroid Build Coastguard Worker tmp_str_len = xmlStrlen(tmp_str);
1049*7c568831SAndroid Build Coastguard Worker if(tmp_str_len > 1 && tmp_str[tmp_str_len - 2] == '.') {
1050*7c568831SAndroid Build Coastguard Worker tmp_str2 = xmlStrcat(tmp_str, BAD_CAST "/");
1051*7c568831SAndroid Build Coastguard Worker if(tmp_str2 == NULL) {
1052*7c568831SAndroid Build Coastguard Worker xmlFree(tmp_str);
1053*7c568831SAndroid Build Coastguard Worker xmlFree(res);
1054*7c568831SAndroid Build Coastguard Worker
1055*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
1056*7c568831SAndroid Build Coastguard Worker return (NULL);
1057*7c568831SAndroid Build Coastguard Worker }
1058*7c568831SAndroid Build Coastguard Worker
1059*7c568831SAndroid Build Coastguard Worker tmp_str = tmp_str2;
1060*7c568831SAndroid Build Coastguard Worker }
1061*7c568831SAndroid Build Coastguard Worker
1062*7c568831SAndroid Build Coastguard Worker /* build uri */
1063*7c568831SAndroid Build Coastguard Worker code = xmlBuildURISafe(res, tmp_str, &tmp_str2);
1064*7c568831SAndroid Build Coastguard Worker if (code != 0) {
1065*7c568831SAndroid Build Coastguard Worker xmlFree(tmp_str);
1066*7c568831SAndroid Build Coastguard Worker xmlFree(res);
1067*7c568831SAndroid Build Coastguard Worker
1068*7c568831SAndroid Build Coastguard Worker if (code < 0)
1069*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
1070*7c568831SAndroid Build Coastguard Worker else
1071*7c568831SAndroid Build Coastguard Worker xmlC14NErr(ctx, cur, XML_ERR_INVALID_URI,
1072*7c568831SAndroid Build Coastguard Worker "processing xml:base attribute - "
1073*7c568831SAndroid Build Coastguard Worker "can't construct uri");
1074*7c568831SAndroid Build Coastguard Worker return (NULL);
1075*7c568831SAndroid Build Coastguard Worker }
1076*7c568831SAndroid Build Coastguard Worker
1077*7c568831SAndroid Build Coastguard Worker /* cleanup and set the new res */
1078*7c568831SAndroid Build Coastguard Worker xmlFree(tmp_str);
1079*7c568831SAndroid Build Coastguard Worker xmlFree(res);
1080*7c568831SAndroid Build Coastguard Worker res = tmp_str2;
1081*7c568831SAndroid Build Coastguard Worker }
1082*7c568831SAndroid Build Coastguard Worker
1083*7c568831SAndroid Build Coastguard Worker /* next */
1084*7c568831SAndroid Build Coastguard Worker cur = cur->parent;
1085*7c568831SAndroid Build Coastguard Worker }
1086*7c568831SAndroid Build Coastguard Worker
1087*7c568831SAndroid Build Coastguard Worker /* check if result uri is empty or not */
1088*7c568831SAndroid Build Coastguard Worker if((res == NULL) || xmlStrEqual(res, BAD_CAST "")) {
1089*7c568831SAndroid Build Coastguard Worker xmlFree(res);
1090*7c568831SAndroid Build Coastguard Worker return (NULL);
1091*7c568831SAndroid Build Coastguard Worker }
1092*7c568831SAndroid Build Coastguard Worker
1093*7c568831SAndroid Build Coastguard Worker /* create and return the new attribute node */
1094*7c568831SAndroid Build Coastguard Worker attr = xmlNewNsProp(NULL, xml_base_attr->ns, BAD_CAST "base", res);
1095*7c568831SAndroid Build Coastguard Worker if(attr == NULL) {
1096*7c568831SAndroid Build Coastguard Worker xmlFree(res);
1097*7c568831SAndroid Build Coastguard Worker
1098*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
1099*7c568831SAndroid Build Coastguard Worker return (NULL);
1100*7c568831SAndroid Build Coastguard Worker }
1101*7c568831SAndroid Build Coastguard Worker
1102*7c568831SAndroid Build Coastguard Worker /* done */
1103*7c568831SAndroid Build Coastguard Worker xmlFree(res);
1104*7c568831SAndroid Build Coastguard Worker return (attr);
1105*7c568831SAndroid Build Coastguard Worker }
1106*7c568831SAndroid Build Coastguard Worker
1107*7c568831SAndroid Build Coastguard Worker /**
1108*7c568831SAndroid Build Coastguard Worker * xmlC14NProcessAttrsAxis:
1109*7c568831SAndroid Build Coastguard Worker * @ctx: the C14N context
1110*7c568831SAndroid Build Coastguard Worker * @cur: the current node
1111*7c568831SAndroid Build Coastguard Worker * @parent_visible: the visibility of parent node
1112*7c568831SAndroid Build Coastguard Worker * @all_parents_visible: the visibility of all parent nodes
1113*7c568831SAndroid Build Coastguard Worker *
1114*7c568831SAndroid Build Coastguard Worker * Prints out canonical attribute axis of the current node to the
1115*7c568831SAndroid Build Coastguard Worker * buffer from C14N context as follows
1116*7c568831SAndroid Build Coastguard Worker *
1117*7c568831SAndroid Build Coastguard Worker * Canonical XML v 1.0 (http://www.w3.org/TR/xml-c14n)
1118*7c568831SAndroid Build Coastguard Worker *
1119*7c568831SAndroid Build Coastguard Worker * Attribute Axis
1120*7c568831SAndroid Build Coastguard Worker * In lexicographic order (ascending), process each node that
1121*7c568831SAndroid Build Coastguard Worker * is in the element's attribute axis and in the node-set.
1122*7c568831SAndroid Build Coastguard Worker *
1123*7c568831SAndroid Build Coastguard Worker * The processing of an element node E MUST be modified slightly
1124*7c568831SAndroid Build Coastguard Worker * when an XPath node-set is given as input and the element's
1125*7c568831SAndroid Build Coastguard Worker * parent is omitted from the node-set.
1126*7c568831SAndroid Build Coastguard Worker *
1127*7c568831SAndroid Build Coastguard Worker *
1128*7c568831SAndroid Build Coastguard Worker * Exclusive XML Canonicalization v 1.0 (http://www.w3.org/TR/xml-exc-c14n)
1129*7c568831SAndroid Build Coastguard Worker *
1130*7c568831SAndroid Build Coastguard Worker * Canonical XML applied to a document subset requires the search of the
1131*7c568831SAndroid Build Coastguard Worker * ancestor nodes of each orphan element node for attributes in the xml
1132*7c568831SAndroid Build Coastguard Worker * namespace, such as xml:lang and xml:space. These are copied into the
1133*7c568831SAndroid Build Coastguard Worker * element node except if a declaration of the same attribute is already
1134*7c568831SAndroid Build Coastguard Worker * in the attribute axis of the element (whether or not it is included in
1135*7c568831SAndroid Build Coastguard Worker * the document subset). This search and copying are omitted from the
1136*7c568831SAndroid Build Coastguard Worker * Exclusive XML Canonicalization method.
1137*7c568831SAndroid Build Coastguard Worker *
1138*7c568831SAndroid Build Coastguard Worker * Returns 0 on success or -1 on fail.
1139*7c568831SAndroid Build Coastguard Worker */
1140*7c568831SAndroid Build Coastguard Worker static int
xmlC14NProcessAttrsAxis(xmlC14NCtxPtr ctx,xmlNodePtr cur,int parent_visible)1141*7c568831SAndroid Build Coastguard Worker xmlC14NProcessAttrsAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int parent_visible)
1142*7c568831SAndroid Build Coastguard Worker {
1143*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attr;
1144*7c568831SAndroid Build Coastguard Worker xmlListPtr list;
1145*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attrs_to_delete = NULL;
1146*7c568831SAndroid Build Coastguard Worker
1147*7c568831SAndroid Build Coastguard Worker /* special processing for 1.1 spec */
1148*7c568831SAndroid Build Coastguard Worker xmlAttrPtr xml_base_attr = NULL;
1149*7c568831SAndroid Build Coastguard Worker xmlAttrPtr xml_lang_attr = NULL;
1150*7c568831SAndroid Build Coastguard Worker xmlAttrPtr xml_space_attr = NULL;
1151*7c568831SAndroid Build Coastguard Worker
1152*7c568831SAndroid Build Coastguard Worker if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
1153*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(ctx);
1154*7c568831SAndroid Build Coastguard Worker return (-1);
1155*7c568831SAndroid Build Coastguard Worker }
1156*7c568831SAndroid Build Coastguard Worker
1157*7c568831SAndroid Build Coastguard Worker /*
1158*7c568831SAndroid Build Coastguard Worker * Create a sorted list to store element attributes
1159*7c568831SAndroid Build Coastguard Worker */
1160*7c568831SAndroid Build Coastguard Worker list = xmlListCreate(NULL, xmlC14NAttrsCompare);
1161*7c568831SAndroid Build Coastguard Worker if (list == NULL) {
1162*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
1163*7c568831SAndroid Build Coastguard Worker return (-1);
1164*7c568831SAndroid Build Coastguard Worker }
1165*7c568831SAndroid Build Coastguard Worker
1166*7c568831SAndroid Build Coastguard Worker switch(ctx->mode) {
1167*7c568831SAndroid Build Coastguard Worker case XML_C14N_1_0:
1168*7c568831SAndroid Build Coastguard Worker /* The processing of an element node E MUST be modified slightly when an XPath node-set is
1169*7c568831SAndroid Build Coastguard Worker * given as input and the element's parent is omitted from the node-set. The method for processing
1170*7c568831SAndroid Build Coastguard Worker * the attribute axis of an element E in the node-set is enhanced. All element nodes along E's
1171*7c568831SAndroid Build Coastguard Worker * ancestor axis are examined for nearest occurrences of attributes in the xml namespace, such
1172*7c568831SAndroid Build Coastguard Worker * as xml:lang and xml:space (whether or not they are in the node-set). From this list of attributes,
1173*7c568831SAndroid Build Coastguard Worker * remove any that are in E's attribute axis (whether or not they are in the node-set). Then,
1174*7c568831SAndroid Build Coastguard Worker * lexicographically merge this attribute list with the nodes of E's attribute axis that are in
1175*7c568831SAndroid Build Coastguard Worker * the node-set. The result of visiting the attribute axis is computed by processing the attribute
1176*7c568831SAndroid Build Coastguard Worker * nodes in this merged attribute list.
1177*7c568831SAndroid Build Coastguard Worker */
1178*7c568831SAndroid Build Coastguard Worker
1179*7c568831SAndroid Build Coastguard Worker /*
1180*7c568831SAndroid Build Coastguard Worker * Add all visible attributes from current node.
1181*7c568831SAndroid Build Coastguard Worker */
1182*7c568831SAndroid Build Coastguard Worker attr = cur->properties;
1183*7c568831SAndroid Build Coastguard Worker while (attr != NULL) {
1184*7c568831SAndroid Build Coastguard Worker /* check that attribute is visible */
1185*7c568831SAndroid Build Coastguard Worker if (xmlC14NIsVisible(ctx, attr, cur)) {
1186*7c568831SAndroid Build Coastguard Worker xmlListInsert(list, attr);
1187*7c568831SAndroid Build Coastguard Worker }
1188*7c568831SAndroid Build Coastguard Worker attr = attr->next;
1189*7c568831SAndroid Build Coastguard Worker }
1190*7c568831SAndroid Build Coastguard Worker
1191*7c568831SAndroid Build Coastguard Worker /*
1192*7c568831SAndroid Build Coastguard Worker * Handle xml attributes
1193*7c568831SAndroid Build Coastguard Worker */
1194*7c568831SAndroid Build Coastguard Worker if (parent_visible && (cur->parent != NULL) &&
1195*7c568831SAndroid Build Coastguard Worker (!xmlC14NIsVisible(ctx, cur->parent, cur->parent->parent)))
1196*7c568831SAndroid Build Coastguard Worker {
1197*7c568831SAndroid Build Coastguard Worker xmlNodePtr tmp;
1198*7c568831SAndroid Build Coastguard Worker
1199*7c568831SAndroid Build Coastguard Worker /*
1200*7c568831SAndroid Build Coastguard Worker * If XPath node-set is not specified then the parent is always
1201*7c568831SAndroid Build Coastguard Worker * visible!
1202*7c568831SAndroid Build Coastguard Worker */
1203*7c568831SAndroid Build Coastguard Worker tmp = cur->parent;
1204*7c568831SAndroid Build Coastguard Worker while (tmp != NULL) {
1205*7c568831SAndroid Build Coastguard Worker attr = tmp->properties;
1206*7c568831SAndroid Build Coastguard Worker while (attr != NULL) {
1207*7c568831SAndroid Build Coastguard Worker if (xmlC14NIsXmlAttr(attr) != 0) {
1208*7c568831SAndroid Build Coastguard Worker if (xmlListSearch(list, attr) == NULL) {
1209*7c568831SAndroid Build Coastguard Worker xmlListInsert(list, attr);
1210*7c568831SAndroid Build Coastguard Worker }
1211*7c568831SAndroid Build Coastguard Worker }
1212*7c568831SAndroid Build Coastguard Worker attr = attr->next;
1213*7c568831SAndroid Build Coastguard Worker }
1214*7c568831SAndroid Build Coastguard Worker tmp = tmp->parent;
1215*7c568831SAndroid Build Coastguard Worker }
1216*7c568831SAndroid Build Coastguard Worker }
1217*7c568831SAndroid Build Coastguard Worker
1218*7c568831SAndroid Build Coastguard Worker /* done */
1219*7c568831SAndroid Build Coastguard Worker break;
1220*7c568831SAndroid Build Coastguard Worker case XML_C14N_EXCLUSIVE_1_0:
1221*7c568831SAndroid Build Coastguard Worker /* attributes in the XML namespace, such as xml:lang and xml:space
1222*7c568831SAndroid Build Coastguard Worker * are not imported into orphan nodes of the document subset
1223*7c568831SAndroid Build Coastguard Worker */
1224*7c568831SAndroid Build Coastguard Worker
1225*7c568831SAndroid Build Coastguard Worker /*
1226*7c568831SAndroid Build Coastguard Worker * Add all visible attributes from current node.
1227*7c568831SAndroid Build Coastguard Worker */
1228*7c568831SAndroid Build Coastguard Worker attr = cur->properties;
1229*7c568831SAndroid Build Coastguard Worker while (attr != NULL) {
1230*7c568831SAndroid Build Coastguard Worker /* check that attribute is visible */
1231*7c568831SAndroid Build Coastguard Worker if (xmlC14NIsVisible(ctx, attr, cur)) {
1232*7c568831SAndroid Build Coastguard Worker xmlListInsert(list, attr);
1233*7c568831SAndroid Build Coastguard Worker }
1234*7c568831SAndroid Build Coastguard Worker attr = attr->next;
1235*7c568831SAndroid Build Coastguard Worker }
1236*7c568831SAndroid Build Coastguard Worker
1237*7c568831SAndroid Build Coastguard Worker /* do nothing special for xml attributes */
1238*7c568831SAndroid Build Coastguard Worker break;
1239*7c568831SAndroid Build Coastguard Worker case XML_C14N_1_1:
1240*7c568831SAndroid Build Coastguard Worker /* The processing of an element node E MUST be modified slightly when an XPath node-set is
1241*7c568831SAndroid Build Coastguard Worker * given as input and some of the element's ancestors are omitted from the node-set.
1242*7c568831SAndroid Build Coastguard Worker *
1243*7c568831SAndroid Build Coastguard Worker * Simple inheritable attributes are attributes that have a value that requires at most a simple
1244*7c568831SAndroid Build Coastguard Worker * redeclaration. This redeclaration is done by supplying a new value in the child axis. The
1245*7c568831SAndroid Build Coastguard Worker * redeclaration of a simple inheritable attribute A contained in one of E's ancestors is done
1246*7c568831SAndroid Build Coastguard Worker * by supplying a value to an attribute Ae inside E with the same name. Simple inheritable attributes
1247*7c568831SAndroid Build Coastguard Worker * are xml:lang and xml:space.
1248*7c568831SAndroid Build Coastguard Worker *
1249*7c568831SAndroid Build Coastguard Worker * The method for processing the attribute axis of an element E in the node-set is hence enhanced.
1250*7c568831SAndroid Build Coastguard Worker * All element nodes along E's ancestor axis are examined for the nearest occurrences of simple
1251*7c568831SAndroid Build Coastguard Worker * inheritable attributes in the xml namespace, such as xml:lang and xml:space (whether or not they
1252*7c568831SAndroid Build Coastguard Worker * are in the node-set). From this list of attributes, any simple inheritable attributes that are
1253*7c568831SAndroid Build Coastguard Worker * already in E's attribute axis (whether or not they are in the node-set) are removed. Then,
1254*7c568831SAndroid Build Coastguard Worker * lexicographically merge this attribute list with the nodes of E's attribute axis that are in
1255*7c568831SAndroid Build Coastguard Worker * the node-set. The result of visiting the attribute axis is computed by processing the attribute
1256*7c568831SAndroid Build Coastguard Worker * nodes in this merged attribute list.
1257*7c568831SAndroid Build Coastguard Worker *
1258*7c568831SAndroid Build Coastguard Worker * The xml:id attribute is not a simple inheritable attribute and no processing of these attributes is
1259*7c568831SAndroid Build Coastguard Worker * performed.
1260*7c568831SAndroid Build Coastguard Worker *
1261*7c568831SAndroid Build Coastguard Worker * The xml:base attribute is not a simple inheritable attribute and requires special processing beyond
1262*7c568831SAndroid Build Coastguard Worker * a simple redeclaration.
1263*7c568831SAndroid Build Coastguard Worker *
1264*7c568831SAndroid Build Coastguard Worker * Attributes in the XML namespace other than xml:base, xml:id, xml:lang, and xml:space MUST be processed
1265*7c568831SAndroid Build Coastguard Worker * as ordinary attributes.
1266*7c568831SAndroid Build Coastguard Worker */
1267*7c568831SAndroid Build Coastguard Worker
1268*7c568831SAndroid Build Coastguard Worker /*
1269*7c568831SAndroid Build Coastguard Worker * Add all visible attributes from current node.
1270*7c568831SAndroid Build Coastguard Worker */
1271*7c568831SAndroid Build Coastguard Worker attr = cur->properties;
1272*7c568831SAndroid Build Coastguard Worker while (attr != NULL) {
1273*7c568831SAndroid Build Coastguard Worker /* special processing for XML attribute kiks in only when we have invisible parents */
1274*7c568831SAndroid Build Coastguard Worker if ((!parent_visible) || (xmlC14NIsXmlAttr(attr) == 0)) {
1275*7c568831SAndroid Build Coastguard Worker /* check that attribute is visible */
1276*7c568831SAndroid Build Coastguard Worker if (xmlC14NIsVisible(ctx, attr, cur)) {
1277*7c568831SAndroid Build Coastguard Worker xmlListInsert(list, attr);
1278*7c568831SAndroid Build Coastguard Worker }
1279*7c568831SAndroid Build Coastguard Worker } else {
1280*7c568831SAndroid Build Coastguard Worker int matched = 0;
1281*7c568831SAndroid Build Coastguard Worker
1282*7c568831SAndroid Build Coastguard Worker /* check for simple inheritance attributes */
1283*7c568831SAndroid Build Coastguard Worker if((!matched) && (xml_lang_attr == NULL) && xmlStrEqual(attr->name, BAD_CAST "lang")) {
1284*7c568831SAndroid Build Coastguard Worker xml_lang_attr = attr;
1285*7c568831SAndroid Build Coastguard Worker matched = 1;
1286*7c568831SAndroid Build Coastguard Worker }
1287*7c568831SAndroid Build Coastguard Worker if((!matched) && (xml_space_attr == NULL) && xmlStrEqual(attr->name, BAD_CAST "space")) {
1288*7c568831SAndroid Build Coastguard Worker xml_space_attr = attr;
1289*7c568831SAndroid Build Coastguard Worker matched = 1;
1290*7c568831SAndroid Build Coastguard Worker }
1291*7c568831SAndroid Build Coastguard Worker
1292*7c568831SAndroid Build Coastguard Worker /* check for base attr */
1293*7c568831SAndroid Build Coastguard Worker if((!matched) && (xml_base_attr == NULL) && xmlStrEqual(attr->name, BAD_CAST "base")) {
1294*7c568831SAndroid Build Coastguard Worker xml_base_attr = attr;
1295*7c568831SAndroid Build Coastguard Worker matched = 1;
1296*7c568831SAndroid Build Coastguard Worker }
1297*7c568831SAndroid Build Coastguard Worker
1298*7c568831SAndroid Build Coastguard Worker /* otherwise, it is a normal attribute, so just check if it is visible */
1299*7c568831SAndroid Build Coastguard Worker if((!matched) && xmlC14NIsVisible(ctx, attr, cur)) {
1300*7c568831SAndroid Build Coastguard Worker xmlListInsert(list, attr);
1301*7c568831SAndroid Build Coastguard Worker }
1302*7c568831SAndroid Build Coastguard Worker }
1303*7c568831SAndroid Build Coastguard Worker
1304*7c568831SAndroid Build Coastguard Worker /* move to the next one */
1305*7c568831SAndroid Build Coastguard Worker attr = attr->next;
1306*7c568831SAndroid Build Coastguard Worker }
1307*7c568831SAndroid Build Coastguard Worker
1308*7c568831SAndroid Build Coastguard Worker /* special processing for XML attribute kiks in only when we have invisible parents */
1309*7c568831SAndroid Build Coastguard Worker if ((parent_visible)) {
1310*7c568831SAndroid Build Coastguard Worker
1311*7c568831SAndroid Build Coastguard Worker /* simple inheritance attributes - copy */
1312*7c568831SAndroid Build Coastguard Worker if(xml_lang_attr == NULL) {
1313*7c568831SAndroid Build Coastguard Worker xml_lang_attr = xmlC14NFindHiddenParentAttr(ctx, cur->parent, BAD_CAST "lang", XML_XML_NAMESPACE);
1314*7c568831SAndroid Build Coastguard Worker }
1315*7c568831SAndroid Build Coastguard Worker if(xml_lang_attr != NULL) {
1316*7c568831SAndroid Build Coastguard Worker xmlListInsert(list, xml_lang_attr);
1317*7c568831SAndroid Build Coastguard Worker }
1318*7c568831SAndroid Build Coastguard Worker if(xml_space_attr == NULL) {
1319*7c568831SAndroid Build Coastguard Worker xml_space_attr = xmlC14NFindHiddenParentAttr(ctx, cur->parent, BAD_CAST "space", XML_XML_NAMESPACE);
1320*7c568831SAndroid Build Coastguard Worker }
1321*7c568831SAndroid Build Coastguard Worker if(xml_space_attr != NULL) {
1322*7c568831SAndroid Build Coastguard Worker xmlListInsert(list, xml_space_attr);
1323*7c568831SAndroid Build Coastguard Worker }
1324*7c568831SAndroid Build Coastguard Worker
1325*7c568831SAndroid Build Coastguard Worker /* base uri attribute - fix up */
1326*7c568831SAndroid Build Coastguard Worker if(xml_base_attr == NULL) {
1327*7c568831SAndroid Build Coastguard Worker /* if we don't have base uri attribute, check if we have a "hidden" one above */
1328*7c568831SAndroid Build Coastguard Worker xml_base_attr = xmlC14NFindHiddenParentAttr(ctx, cur->parent, BAD_CAST "base", XML_XML_NAMESPACE);
1329*7c568831SAndroid Build Coastguard Worker }
1330*7c568831SAndroid Build Coastguard Worker if(xml_base_attr != NULL) {
1331*7c568831SAndroid Build Coastguard Worker xml_base_attr = xmlC14NFixupBaseAttr(ctx, xml_base_attr);
1332*7c568831SAndroid Build Coastguard Worker if(xml_base_attr != NULL) {
1333*7c568831SAndroid Build Coastguard Worker xmlListInsert(list, xml_base_attr);
1334*7c568831SAndroid Build Coastguard Worker
1335*7c568831SAndroid Build Coastguard Worker /* note that we MUST delete returned attr node ourselves! */
1336*7c568831SAndroid Build Coastguard Worker xml_base_attr->next = attrs_to_delete;
1337*7c568831SAndroid Build Coastguard Worker attrs_to_delete = xml_base_attr;
1338*7c568831SAndroid Build Coastguard Worker }
1339*7c568831SAndroid Build Coastguard Worker }
1340*7c568831SAndroid Build Coastguard Worker }
1341*7c568831SAndroid Build Coastguard Worker
1342*7c568831SAndroid Build Coastguard Worker /* done */
1343*7c568831SAndroid Build Coastguard Worker break;
1344*7c568831SAndroid Build Coastguard Worker }
1345*7c568831SAndroid Build Coastguard Worker
1346*7c568831SAndroid Build Coastguard Worker /*
1347*7c568831SAndroid Build Coastguard Worker * print out all elements from list
1348*7c568831SAndroid Build Coastguard Worker */
1349*7c568831SAndroid Build Coastguard Worker xmlListWalk(list, xmlC14NPrintAttrs, (void *) ctx);
1350*7c568831SAndroid Build Coastguard Worker
1351*7c568831SAndroid Build Coastguard Worker /*
1352*7c568831SAndroid Build Coastguard Worker * Cleanup
1353*7c568831SAndroid Build Coastguard Worker */
1354*7c568831SAndroid Build Coastguard Worker xmlFreePropList(attrs_to_delete);
1355*7c568831SAndroid Build Coastguard Worker xmlListDelete(list);
1356*7c568831SAndroid Build Coastguard Worker return (0);
1357*7c568831SAndroid Build Coastguard Worker }
1358*7c568831SAndroid Build Coastguard Worker
1359*7c568831SAndroid Build Coastguard Worker /**
1360*7c568831SAndroid Build Coastguard Worker * xmlC14NCheckForRelativeNamespaces:
1361*7c568831SAndroid Build Coastguard Worker * @ctx: the C14N context
1362*7c568831SAndroid Build Coastguard Worker * @cur: the current element node
1363*7c568831SAndroid Build Coastguard Worker *
1364*7c568831SAndroid Build Coastguard Worker * Checks that current element node has no relative namespaces defined
1365*7c568831SAndroid Build Coastguard Worker *
1366*7c568831SAndroid Build Coastguard Worker * Returns 0 if the node has no relative namespaces or -1 otherwise.
1367*7c568831SAndroid Build Coastguard Worker */
1368*7c568831SAndroid Build Coastguard Worker static int
xmlC14NCheckForRelativeNamespaces(xmlC14NCtxPtr ctx,xmlNodePtr cur)1369*7c568831SAndroid Build Coastguard Worker xmlC14NCheckForRelativeNamespaces(xmlC14NCtxPtr ctx, xmlNodePtr cur)
1370*7c568831SAndroid Build Coastguard Worker {
1371*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns;
1372*7c568831SAndroid Build Coastguard Worker
1373*7c568831SAndroid Build Coastguard Worker if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
1374*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(ctx);
1375*7c568831SAndroid Build Coastguard Worker return (-1);
1376*7c568831SAndroid Build Coastguard Worker }
1377*7c568831SAndroid Build Coastguard Worker
1378*7c568831SAndroid Build Coastguard Worker ns = cur->nsDef;
1379*7c568831SAndroid Build Coastguard Worker while (ns != NULL) {
1380*7c568831SAndroid Build Coastguard Worker if (xmlStrlen(ns->href) > 0) {
1381*7c568831SAndroid Build Coastguard Worker xmlURIPtr uri;
1382*7c568831SAndroid Build Coastguard Worker int code;
1383*7c568831SAndroid Build Coastguard Worker
1384*7c568831SAndroid Build Coastguard Worker code = xmlParseURISafe((const char *) ns->href, &uri);
1385*7c568831SAndroid Build Coastguard Worker if (uri == NULL) {
1386*7c568831SAndroid Build Coastguard Worker if (code < 0)
1387*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
1388*7c568831SAndroid Build Coastguard Worker else
1389*7c568831SAndroid Build Coastguard Worker xmlC14NErr(ctx, cur, XML_ERR_INVALID_URI,
1390*7c568831SAndroid Build Coastguard Worker "parsing namespace uri");
1391*7c568831SAndroid Build Coastguard Worker return (-1);
1392*7c568831SAndroid Build Coastguard Worker }
1393*7c568831SAndroid Build Coastguard Worker if (xmlStrlen((const xmlChar *) uri->scheme) == 0) {
1394*7c568831SAndroid Build Coastguard Worker xmlC14NErrRelativeNamespace(ctx, uri->scheme);
1395*7c568831SAndroid Build Coastguard Worker xmlFreeURI(uri);
1396*7c568831SAndroid Build Coastguard Worker return (-1);
1397*7c568831SAndroid Build Coastguard Worker }
1398*7c568831SAndroid Build Coastguard Worker xmlFreeURI(uri);
1399*7c568831SAndroid Build Coastguard Worker }
1400*7c568831SAndroid Build Coastguard Worker ns = ns->next;
1401*7c568831SAndroid Build Coastguard Worker }
1402*7c568831SAndroid Build Coastguard Worker return (0);
1403*7c568831SAndroid Build Coastguard Worker }
1404*7c568831SAndroid Build Coastguard Worker
1405*7c568831SAndroid Build Coastguard Worker /**
1406*7c568831SAndroid Build Coastguard Worker * xmlC14NProcessElementNode:
1407*7c568831SAndroid Build Coastguard Worker * @ctx: the pointer to C14N context object
1408*7c568831SAndroid Build Coastguard Worker * @cur: the node to process
1409*7c568831SAndroid Build Coastguard Worker * @visible: this node is visible
1410*7c568831SAndroid Build Coastguard Worker * @all_parents_visible: whether all the parents of this node are visible
1411*7c568831SAndroid Build Coastguard Worker *
1412*7c568831SAndroid Build Coastguard Worker * Canonical XML v 1.0 (http://www.w3.org/TR/xml-c14n)
1413*7c568831SAndroid Build Coastguard Worker *
1414*7c568831SAndroid Build Coastguard Worker * Element Nodes
1415*7c568831SAndroid Build Coastguard Worker * If the element is not in the node-set, then the result is obtained
1416*7c568831SAndroid Build Coastguard Worker * by processing the namespace axis, then the attribute axis, then
1417*7c568831SAndroid Build Coastguard Worker * processing the child nodes of the element that are in the node-set
1418*7c568831SAndroid Build Coastguard Worker * (in document order). If the element is in the node-set, then the result
1419*7c568831SAndroid Build Coastguard Worker * is an open angle bracket (<), the element QName, the result of
1420*7c568831SAndroid Build Coastguard Worker * processing the namespace axis, the result of processing the attribute
1421*7c568831SAndroid Build Coastguard Worker * axis, a close angle bracket (>), the result of processing the child
1422*7c568831SAndroid Build Coastguard Worker * nodes of the element that are in the node-set (in document order), an
1423*7c568831SAndroid Build Coastguard Worker * open angle bracket, a forward slash (/), the element QName, and a close
1424*7c568831SAndroid Build Coastguard Worker * angle bracket.
1425*7c568831SAndroid Build Coastguard Worker *
1426*7c568831SAndroid Build Coastguard Worker * Returns non-negative value on success or negative value on fail
1427*7c568831SAndroid Build Coastguard Worker */
1428*7c568831SAndroid Build Coastguard Worker static int
xmlC14NProcessElementNode(xmlC14NCtxPtr ctx,xmlNodePtr cur,int visible)1429*7c568831SAndroid Build Coastguard Worker xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
1430*7c568831SAndroid Build Coastguard Worker {
1431*7c568831SAndroid Build Coastguard Worker int ret;
1432*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStack state;
1433*7c568831SAndroid Build Coastguard Worker int parent_is_doc = 0;
1434*7c568831SAndroid Build Coastguard Worker
1435*7c568831SAndroid Build Coastguard Worker if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
1436*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(ctx);
1437*7c568831SAndroid Build Coastguard Worker return (-1);
1438*7c568831SAndroid Build Coastguard Worker }
1439*7c568831SAndroid Build Coastguard Worker
1440*7c568831SAndroid Build Coastguard Worker /*
1441*7c568831SAndroid Build Coastguard Worker * Check relative relative namespaces:
1442*7c568831SAndroid Build Coastguard Worker * implementations of XML canonicalization MUST report an operation
1443*7c568831SAndroid Build Coastguard Worker * failure on documents containing relative namespace URIs.
1444*7c568831SAndroid Build Coastguard Worker */
1445*7c568831SAndroid Build Coastguard Worker if (xmlC14NCheckForRelativeNamespaces(ctx, cur) < 0)
1446*7c568831SAndroid Build Coastguard Worker return (-1);
1447*7c568831SAndroid Build Coastguard Worker
1448*7c568831SAndroid Build Coastguard Worker /*
1449*7c568831SAndroid Build Coastguard Worker * Save ns_rendered stack position
1450*7c568831SAndroid Build Coastguard Worker */
1451*7c568831SAndroid Build Coastguard Worker memset(&state, 0, sizeof(state));
1452*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStackSave(ctx->ns_rendered, &state);
1453*7c568831SAndroid Build Coastguard Worker
1454*7c568831SAndroid Build Coastguard Worker if (visible) {
1455*7c568831SAndroid Build Coastguard Worker if (ctx->parent_is_doc) {
1456*7c568831SAndroid Build Coastguard Worker /* save this flag into the stack */
1457*7c568831SAndroid Build Coastguard Worker parent_is_doc = ctx->parent_is_doc;
1458*7c568831SAndroid Build Coastguard Worker ctx->parent_is_doc = 0;
1459*7c568831SAndroid Build Coastguard Worker ctx->pos = XMLC14N_INSIDE_DOCUMENT_ELEMENT;
1460*7c568831SAndroid Build Coastguard Worker }
1461*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, "<");
1462*7c568831SAndroid Build Coastguard Worker
1463*7c568831SAndroid Build Coastguard Worker if ((cur->ns != NULL) && (xmlStrlen(cur->ns->prefix) > 0)) {
1464*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf,
1465*7c568831SAndroid Build Coastguard Worker (const char *) cur->ns->prefix);
1466*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, ":");
1467*7c568831SAndroid Build Coastguard Worker }
1468*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, (const char *) cur->name);
1469*7c568831SAndroid Build Coastguard Worker }
1470*7c568831SAndroid Build Coastguard Worker
1471*7c568831SAndroid Build Coastguard Worker if (!xmlC14NIsExclusive(ctx)) {
1472*7c568831SAndroid Build Coastguard Worker ret = xmlC14NProcessNamespacesAxis(ctx, cur, visible);
1473*7c568831SAndroid Build Coastguard Worker } else {
1474*7c568831SAndroid Build Coastguard Worker ret = xmlExcC14NProcessNamespacesAxis(ctx, cur, visible);
1475*7c568831SAndroid Build Coastguard Worker }
1476*7c568831SAndroid Build Coastguard Worker if (ret < 0)
1477*7c568831SAndroid Build Coastguard Worker return (-1);
1478*7c568831SAndroid Build Coastguard Worker /* todo: shouldn't this go to "visible only"? */
1479*7c568831SAndroid Build Coastguard Worker if(visible) {
1480*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStackShift(ctx->ns_rendered);
1481*7c568831SAndroid Build Coastguard Worker }
1482*7c568831SAndroid Build Coastguard Worker
1483*7c568831SAndroid Build Coastguard Worker ret = xmlC14NProcessAttrsAxis(ctx, cur, visible);
1484*7c568831SAndroid Build Coastguard Worker if (ret < 0)
1485*7c568831SAndroid Build Coastguard Worker return (-1);
1486*7c568831SAndroid Build Coastguard Worker
1487*7c568831SAndroid Build Coastguard Worker if (visible) {
1488*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, ">");
1489*7c568831SAndroid Build Coastguard Worker }
1490*7c568831SAndroid Build Coastguard Worker if (cur->children != NULL) {
1491*7c568831SAndroid Build Coastguard Worker ret = xmlC14NProcessNodeList(ctx, cur->children);
1492*7c568831SAndroid Build Coastguard Worker if (ret < 0)
1493*7c568831SAndroid Build Coastguard Worker return (-1);
1494*7c568831SAndroid Build Coastguard Worker }
1495*7c568831SAndroid Build Coastguard Worker if (visible) {
1496*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, "</");
1497*7c568831SAndroid Build Coastguard Worker if ((cur->ns != NULL) && (xmlStrlen(cur->ns->prefix) > 0)) {
1498*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf,
1499*7c568831SAndroid Build Coastguard Worker (const char *) cur->ns->prefix);
1500*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, ":");
1501*7c568831SAndroid Build Coastguard Worker }
1502*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, (const char *) cur->name);
1503*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, ">");
1504*7c568831SAndroid Build Coastguard Worker if (parent_is_doc) {
1505*7c568831SAndroid Build Coastguard Worker /* restore this flag from the stack for next node */
1506*7c568831SAndroid Build Coastguard Worker ctx->parent_is_doc = parent_is_doc;
1507*7c568831SAndroid Build Coastguard Worker ctx->pos = XMLC14N_AFTER_DOCUMENT_ELEMENT;
1508*7c568831SAndroid Build Coastguard Worker }
1509*7c568831SAndroid Build Coastguard Worker }
1510*7c568831SAndroid Build Coastguard Worker
1511*7c568831SAndroid Build Coastguard Worker /*
1512*7c568831SAndroid Build Coastguard Worker * Restore ns_rendered stack position
1513*7c568831SAndroid Build Coastguard Worker */
1514*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStackRestore(ctx->ns_rendered, &state);
1515*7c568831SAndroid Build Coastguard Worker return (0);
1516*7c568831SAndroid Build Coastguard Worker }
1517*7c568831SAndroid Build Coastguard Worker
1518*7c568831SAndroid Build Coastguard Worker /**
1519*7c568831SAndroid Build Coastguard Worker * xmlC14NProcessNode:
1520*7c568831SAndroid Build Coastguard Worker * @ctx: the pointer to C14N context object
1521*7c568831SAndroid Build Coastguard Worker * @cur: the node to process
1522*7c568831SAndroid Build Coastguard Worker *
1523*7c568831SAndroid Build Coastguard Worker * Processes the given node
1524*7c568831SAndroid Build Coastguard Worker *
1525*7c568831SAndroid Build Coastguard Worker * Returns non-negative value on success or negative value on fail
1526*7c568831SAndroid Build Coastguard Worker */
1527*7c568831SAndroid Build Coastguard Worker static int
xmlC14NProcessNode(xmlC14NCtxPtr ctx,xmlNodePtr cur)1528*7c568831SAndroid Build Coastguard Worker xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur)
1529*7c568831SAndroid Build Coastguard Worker {
1530*7c568831SAndroid Build Coastguard Worker int ret = 0;
1531*7c568831SAndroid Build Coastguard Worker int visible;
1532*7c568831SAndroid Build Coastguard Worker
1533*7c568831SAndroid Build Coastguard Worker if ((ctx == NULL) || (cur == NULL)) {
1534*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(ctx);
1535*7c568831SAndroid Build Coastguard Worker return (-1);
1536*7c568831SAndroid Build Coastguard Worker }
1537*7c568831SAndroid Build Coastguard Worker
1538*7c568831SAndroid Build Coastguard Worker visible = xmlC14NIsVisible(ctx, cur, cur->parent);
1539*7c568831SAndroid Build Coastguard Worker switch (cur->type) {
1540*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
1541*7c568831SAndroid Build Coastguard Worker ret = xmlC14NProcessElementNode(ctx, cur, visible);
1542*7c568831SAndroid Build Coastguard Worker break;
1543*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
1544*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
1545*7c568831SAndroid Build Coastguard Worker /*
1546*7c568831SAndroid Build Coastguard Worker * Text Nodes
1547*7c568831SAndroid Build Coastguard Worker * the string value, except all ampersands are replaced
1548*7c568831SAndroid Build Coastguard Worker * by &, all open angle brackets (<) are replaced by <, all closing
1549*7c568831SAndroid Build Coastguard Worker * angle brackets (>) are replaced by >, and all #xD characters are
1550*7c568831SAndroid Build Coastguard Worker * replaced by 
.
1551*7c568831SAndroid Build Coastguard Worker */
1552*7c568831SAndroid Build Coastguard Worker /* cdata sections are processed as text nodes */
1553*7c568831SAndroid Build Coastguard Worker /* todo: verify that cdata sections are included in XPath nodes set */
1554*7c568831SAndroid Build Coastguard Worker if ((visible) && (cur->content != NULL)) {
1555*7c568831SAndroid Build Coastguard Worker xmlChar *buffer;
1556*7c568831SAndroid Build Coastguard Worker
1557*7c568831SAndroid Build Coastguard Worker buffer = xmlC11NNormalizeText(cur->content);
1558*7c568831SAndroid Build Coastguard Worker if (buffer != NULL) {
1559*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf,
1560*7c568831SAndroid Build Coastguard Worker (const char *) buffer);
1561*7c568831SAndroid Build Coastguard Worker xmlFree(buffer);
1562*7c568831SAndroid Build Coastguard Worker } else {
1563*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
1564*7c568831SAndroid Build Coastguard Worker return (-1);
1565*7c568831SAndroid Build Coastguard Worker }
1566*7c568831SAndroid Build Coastguard Worker }
1567*7c568831SAndroid Build Coastguard Worker break;
1568*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE:
1569*7c568831SAndroid Build Coastguard Worker /*
1570*7c568831SAndroid Build Coastguard Worker * Processing Instruction (PI) Nodes-
1571*7c568831SAndroid Build Coastguard Worker * The opening PI symbol (<?), the PI target name of the node,
1572*7c568831SAndroid Build Coastguard Worker * a leading space and the string value if it is not empty, and
1573*7c568831SAndroid Build Coastguard Worker * the closing PI symbol (?>). If the string value is empty,
1574*7c568831SAndroid Build Coastguard Worker * then the leading space is not added. Also, a trailing #xA is
1575*7c568831SAndroid Build Coastguard Worker * rendered after the closing PI symbol for PI children of the
1576*7c568831SAndroid Build Coastguard Worker * root node with a lesser document order than the document
1577*7c568831SAndroid Build Coastguard Worker * element, and a leading #xA is rendered before the opening PI
1578*7c568831SAndroid Build Coastguard Worker * symbol of PI children of the root node with a greater document
1579*7c568831SAndroid Build Coastguard Worker * order than the document element.
1580*7c568831SAndroid Build Coastguard Worker */
1581*7c568831SAndroid Build Coastguard Worker if (visible) {
1582*7c568831SAndroid Build Coastguard Worker if (ctx->pos == XMLC14N_AFTER_DOCUMENT_ELEMENT) {
1583*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, "\x0A<?");
1584*7c568831SAndroid Build Coastguard Worker } else {
1585*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, "<?");
1586*7c568831SAndroid Build Coastguard Worker }
1587*7c568831SAndroid Build Coastguard Worker
1588*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf,
1589*7c568831SAndroid Build Coastguard Worker (const char *) cur->name);
1590*7c568831SAndroid Build Coastguard Worker if ((cur->content != NULL) && (*(cur->content) != '\0')) {
1591*7c568831SAndroid Build Coastguard Worker xmlChar *buffer;
1592*7c568831SAndroid Build Coastguard Worker
1593*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, " ");
1594*7c568831SAndroid Build Coastguard Worker
1595*7c568831SAndroid Build Coastguard Worker /* todo: do we need to normalize pi? */
1596*7c568831SAndroid Build Coastguard Worker buffer = xmlC11NNormalizePI(cur->content);
1597*7c568831SAndroid Build Coastguard Worker if (buffer != NULL) {
1598*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf,
1599*7c568831SAndroid Build Coastguard Worker (const char *) buffer);
1600*7c568831SAndroid Build Coastguard Worker xmlFree(buffer);
1601*7c568831SAndroid Build Coastguard Worker } else {
1602*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
1603*7c568831SAndroid Build Coastguard Worker return (-1);
1604*7c568831SAndroid Build Coastguard Worker }
1605*7c568831SAndroid Build Coastguard Worker }
1606*7c568831SAndroid Build Coastguard Worker
1607*7c568831SAndroid Build Coastguard Worker if (ctx->pos == XMLC14N_BEFORE_DOCUMENT_ELEMENT) {
1608*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, "?>\x0A");
1609*7c568831SAndroid Build Coastguard Worker } else {
1610*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, "?>");
1611*7c568831SAndroid Build Coastguard Worker }
1612*7c568831SAndroid Build Coastguard Worker }
1613*7c568831SAndroid Build Coastguard Worker break;
1614*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
1615*7c568831SAndroid Build Coastguard Worker /*
1616*7c568831SAndroid Build Coastguard Worker * Comment Nodes
1617*7c568831SAndroid Build Coastguard Worker * Nothing if generating canonical XML without comments. For
1618*7c568831SAndroid Build Coastguard Worker * canonical XML with comments, generate the opening comment
1619*7c568831SAndroid Build Coastguard Worker * symbol (<!--), the string value of the node, and the
1620*7c568831SAndroid Build Coastguard Worker * closing comment symbol (-->). Also, a trailing #xA is rendered
1621*7c568831SAndroid Build Coastguard Worker * after the closing comment symbol for comment children of the
1622*7c568831SAndroid Build Coastguard Worker * root node with a lesser document order than the document
1623*7c568831SAndroid Build Coastguard Worker * element, and a leading #xA is rendered before the opening
1624*7c568831SAndroid Build Coastguard Worker * comment symbol of comment children of the root node with a
1625*7c568831SAndroid Build Coastguard Worker * greater document order than the document element. (Comment
1626*7c568831SAndroid Build Coastguard Worker * children of the root node represent comments outside of the
1627*7c568831SAndroid Build Coastguard Worker * top-level document element and outside of the document type
1628*7c568831SAndroid Build Coastguard Worker * declaration).
1629*7c568831SAndroid Build Coastguard Worker */
1630*7c568831SAndroid Build Coastguard Worker if (visible && ctx->with_comments) {
1631*7c568831SAndroid Build Coastguard Worker if (ctx->pos == XMLC14N_AFTER_DOCUMENT_ELEMENT) {
1632*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, "\x0A<!--");
1633*7c568831SAndroid Build Coastguard Worker } else {
1634*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, "<!--");
1635*7c568831SAndroid Build Coastguard Worker }
1636*7c568831SAndroid Build Coastguard Worker
1637*7c568831SAndroid Build Coastguard Worker if (cur->content != NULL) {
1638*7c568831SAndroid Build Coastguard Worker xmlChar *buffer;
1639*7c568831SAndroid Build Coastguard Worker
1640*7c568831SAndroid Build Coastguard Worker /* todo: do we need to normalize comment? */
1641*7c568831SAndroid Build Coastguard Worker buffer = xmlC11NNormalizeComment(cur->content);
1642*7c568831SAndroid Build Coastguard Worker if (buffer != NULL) {
1643*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf,
1644*7c568831SAndroid Build Coastguard Worker (const char *) buffer);
1645*7c568831SAndroid Build Coastguard Worker xmlFree(buffer);
1646*7c568831SAndroid Build Coastguard Worker } else {
1647*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
1648*7c568831SAndroid Build Coastguard Worker return (-1);
1649*7c568831SAndroid Build Coastguard Worker }
1650*7c568831SAndroid Build Coastguard Worker }
1651*7c568831SAndroid Build Coastguard Worker
1652*7c568831SAndroid Build Coastguard Worker if (ctx->pos == XMLC14N_BEFORE_DOCUMENT_ELEMENT) {
1653*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, "-->\x0A");
1654*7c568831SAndroid Build Coastguard Worker } else {
1655*7c568831SAndroid Build Coastguard Worker xmlOutputBufferWriteString(ctx->buf, "-->");
1656*7c568831SAndroid Build Coastguard Worker }
1657*7c568831SAndroid Build Coastguard Worker }
1658*7c568831SAndroid Build Coastguard Worker break;
1659*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
1660*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE: /* should be processed as document? */
1661*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_HTML_ENABLED
1662*7c568831SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE: /* should be processed as document? */
1663*7c568831SAndroid Build Coastguard Worker #endif
1664*7c568831SAndroid Build Coastguard Worker if (cur->children != NULL) {
1665*7c568831SAndroid Build Coastguard Worker ctx->pos = XMLC14N_BEFORE_DOCUMENT_ELEMENT;
1666*7c568831SAndroid Build Coastguard Worker ctx->parent_is_doc = 1;
1667*7c568831SAndroid Build Coastguard Worker ret = xmlC14NProcessNodeList(ctx, cur->children);
1668*7c568831SAndroid Build Coastguard Worker }
1669*7c568831SAndroid Build Coastguard Worker break;
1670*7c568831SAndroid Build Coastguard Worker
1671*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
1672*7c568831SAndroid Build Coastguard Worker xmlC14NErrInvalidNode(ctx, "XML_ATTRIBUTE_NODE", "processing node");
1673*7c568831SAndroid Build Coastguard Worker return (-1);
1674*7c568831SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
1675*7c568831SAndroid Build Coastguard Worker xmlC14NErrInvalidNode(ctx, "XML_NAMESPACE_DECL", "processing node");
1676*7c568831SAndroid Build Coastguard Worker return (-1);
1677*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
1678*7c568831SAndroid Build Coastguard Worker xmlC14NErrInvalidNode(ctx, "XML_ENTITY_REF_NODE", "processing node");
1679*7c568831SAndroid Build Coastguard Worker return (-1);
1680*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
1681*7c568831SAndroid Build Coastguard Worker xmlC14NErrInvalidNode(ctx, "XML_ENTITY_NODE", "processing node");
1682*7c568831SAndroid Build Coastguard Worker return (-1);
1683*7c568831SAndroid Build Coastguard Worker
1684*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_TYPE_NODE:
1685*7c568831SAndroid Build Coastguard Worker case XML_NOTATION_NODE:
1686*7c568831SAndroid Build Coastguard Worker case XML_DTD_NODE:
1687*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_DECL:
1688*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_DECL:
1689*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_DECL:
1690*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_XINCLUDE_ENABLED
1691*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
1692*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
1693*7c568831SAndroid Build Coastguard Worker #endif
1694*7c568831SAndroid Build Coastguard Worker /*
1695*7c568831SAndroid Build Coastguard Worker * should be ignored according to "W3C Canonical XML"
1696*7c568831SAndroid Build Coastguard Worker */
1697*7c568831SAndroid Build Coastguard Worker break;
1698*7c568831SAndroid Build Coastguard Worker default:
1699*7c568831SAndroid Build Coastguard Worker xmlC14NErrUnknownNode(ctx, cur->type, "processing node");
1700*7c568831SAndroid Build Coastguard Worker return (-1);
1701*7c568831SAndroid Build Coastguard Worker }
1702*7c568831SAndroid Build Coastguard Worker
1703*7c568831SAndroid Build Coastguard Worker return (ret);
1704*7c568831SAndroid Build Coastguard Worker }
1705*7c568831SAndroid Build Coastguard Worker
1706*7c568831SAndroid Build Coastguard Worker /**
1707*7c568831SAndroid Build Coastguard Worker * xmlC14NProcessNodeList:
1708*7c568831SAndroid Build Coastguard Worker * @ctx: the pointer to C14N context object
1709*7c568831SAndroid Build Coastguard Worker * @cur: the node to start from
1710*7c568831SAndroid Build Coastguard Worker *
1711*7c568831SAndroid Build Coastguard Worker * Processes all nodes in the row starting from cur.
1712*7c568831SAndroid Build Coastguard Worker *
1713*7c568831SAndroid Build Coastguard Worker * Returns non-negative value on success or negative value on fail
1714*7c568831SAndroid Build Coastguard Worker */
1715*7c568831SAndroid Build Coastguard Worker static int
xmlC14NProcessNodeList(xmlC14NCtxPtr ctx,xmlNodePtr cur)1716*7c568831SAndroid Build Coastguard Worker xmlC14NProcessNodeList(xmlC14NCtxPtr ctx, xmlNodePtr cur)
1717*7c568831SAndroid Build Coastguard Worker {
1718*7c568831SAndroid Build Coastguard Worker int ret;
1719*7c568831SAndroid Build Coastguard Worker
1720*7c568831SAndroid Build Coastguard Worker if (ctx == NULL) {
1721*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(ctx);
1722*7c568831SAndroid Build Coastguard Worker return (-1);
1723*7c568831SAndroid Build Coastguard Worker }
1724*7c568831SAndroid Build Coastguard Worker
1725*7c568831SAndroid Build Coastguard Worker for (ret = 0; cur != NULL && ret >= 0; cur = cur->next) {
1726*7c568831SAndroid Build Coastguard Worker ret = xmlC14NProcessNode(ctx, cur);
1727*7c568831SAndroid Build Coastguard Worker }
1728*7c568831SAndroid Build Coastguard Worker return (ret);
1729*7c568831SAndroid Build Coastguard Worker }
1730*7c568831SAndroid Build Coastguard Worker
1731*7c568831SAndroid Build Coastguard Worker
1732*7c568831SAndroid Build Coastguard Worker /**
1733*7c568831SAndroid Build Coastguard Worker * xmlC14NFreeCtx:
1734*7c568831SAndroid Build Coastguard Worker * @ctx: the pointer to C14N context object
1735*7c568831SAndroid Build Coastguard Worker *
1736*7c568831SAndroid Build Coastguard Worker * Cleanups the C14N context object.
1737*7c568831SAndroid Build Coastguard Worker */
1738*7c568831SAndroid Build Coastguard Worker
1739*7c568831SAndroid Build Coastguard Worker static void
xmlC14NFreeCtx(xmlC14NCtxPtr ctx)1740*7c568831SAndroid Build Coastguard Worker xmlC14NFreeCtx(xmlC14NCtxPtr ctx)
1741*7c568831SAndroid Build Coastguard Worker {
1742*7c568831SAndroid Build Coastguard Worker if (ctx == NULL) {
1743*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(ctx);
1744*7c568831SAndroid Build Coastguard Worker return;
1745*7c568831SAndroid Build Coastguard Worker }
1746*7c568831SAndroid Build Coastguard Worker
1747*7c568831SAndroid Build Coastguard Worker if (ctx->ns_rendered != NULL) {
1748*7c568831SAndroid Build Coastguard Worker xmlC14NVisibleNsStackDestroy(ctx->ns_rendered);
1749*7c568831SAndroid Build Coastguard Worker }
1750*7c568831SAndroid Build Coastguard Worker xmlFree(ctx);
1751*7c568831SAndroid Build Coastguard Worker }
1752*7c568831SAndroid Build Coastguard Worker
1753*7c568831SAndroid Build Coastguard Worker /**
1754*7c568831SAndroid Build Coastguard Worker * xmlC14NNewCtx:
1755*7c568831SAndroid Build Coastguard Worker * @doc: the XML document for canonization
1756*7c568831SAndroid Build Coastguard Worker * @is_visible_callback:the function to use to determine is node visible
1757*7c568831SAndroid Build Coastguard Worker * or not
1758*7c568831SAndroid Build Coastguard Worker * @user_data: the first parameter for @is_visible_callback function
1759*7c568831SAndroid Build Coastguard Worker * (in most cases, it is nodes set)
1760*7c568831SAndroid Build Coastguard Worker * @mode: the c14n mode (see @xmlC14NMode)
1761*7c568831SAndroid Build Coastguard Worker * @inclusive_ns_prefixe the list of inclusive namespace prefixes
1762*7c568831SAndroid Build Coastguard Worker * ended with a NULL or NULL if there is no
1763*7c568831SAndroid Build Coastguard Worker * inclusive namespaces (only for `
1764*7c568831SAndroid Build Coastguard Worker * canonicalization)
1765*7c568831SAndroid Build Coastguard Worker * @with_comments: include comments in the result (!=0) or not (==0)
1766*7c568831SAndroid Build Coastguard Worker * @buf: the output buffer to store canonical XML; this
1767*7c568831SAndroid Build Coastguard Worker * buffer MUST have encoder==NULL because C14N requires
1768*7c568831SAndroid Build Coastguard Worker * UTF-8 output
1769*7c568831SAndroid Build Coastguard Worker *
1770*7c568831SAndroid Build Coastguard Worker * Creates new C14N context object to store C14N parameters.
1771*7c568831SAndroid Build Coastguard Worker *
1772*7c568831SAndroid Build Coastguard Worker * Returns pointer to newly created object (success) or NULL (fail)
1773*7c568831SAndroid Build Coastguard Worker */
1774*7c568831SAndroid Build Coastguard Worker static xmlC14NCtxPtr
xmlC14NNewCtx(xmlDocPtr doc,xmlC14NIsVisibleCallback is_visible_callback,void * user_data,xmlC14NMode mode,xmlChar ** inclusive_ns_prefixes,int with_comments,xmlOutputBufferPtr buf)1775*7c568831SAndroid Build Coastguard Worker xmlC14NNewCtx(xmlDocPtr doc,
1776*7c568831SAndroid Build Coastguard Worker xmlC14NIsVisibleCallback is_visible_callback, void* user_data,
1777*7c568831SAndroid Build Coastguard Worker xmlC14NMode mode, xmlChar ** inclusive_ns_prefixes,
1778*7c568831SAndroid Build Coastguard Worker int with_comments, xmlOutputBufferPtr buf)
1779*7c568831SAndroid Build Coastguard Worker {
1780*7c568831SAndroid Build Coastguard Worker xmlC14NCtxPtr ctx = NULL;
1781*7c568831SAndroid Build Coastguard Worker
1782*7c568831SAndroid Build Coastguard Worker if ((doc == NULL) || (buf == NULL)) {
1783*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(ctx);
1784*7c568831SAndroid Build Coastguard Worker return (NULL);
1785*7c568831SAndroid Build Coastguard Worker }
1786*7c568831SAndroid Build Coastguard Worker
1787*7c568831SAndroid Build Coastguard Worker /*
1788*7c568831SAndroid Build Coastguard Worker * Validate the encoding output buffer encoding
1789*7c568831SAndroid Build Coastguard Worker */
1790*7c568831SAndroid Build Coastguard Worker if (buf->encoder != NULL) {
1791*7c568831SAndroid Build Coastguard Worker xmlC14NErr(ctx, (xmlNodePtr) doc, XML_C14N_REQUIRES_UTF8,
1792*7c568831SAndroid Build Coastguard Worker "xmlC14NNewCtx: output buffer encoder != NULL but C14N requires UTF8 output\n");
1793*7c568831SAndroid Build Coastguard Worker return (NULL);
1794*7c568831SAndroid Build Coastguard Worker }
1795*7c568831SAndroid Build Coastguard Worker
1796*7c568831SAndroid Build Coastguard Worker /*
1797*7c568831SAndroid Build Coastguard Worker * Allocate a new xmlC14NCtxPtr and fill the fields.
1798*7c568831SAndroid Build Coastguard Worker */
1799*7c568831SAndroid Build Coastguard Worker ctx = (xmlC14NCtxPtr) xmlMalloc(sizeof(xmlC14NCtx));
1800*7c568831SAndroid Build Coastguard Worker if (ctx == NULL) {
1801*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
1802*7c568831SAndroid Build Coastguard Worker return (NULL);
1803*7c568831SAndroid Build Coastguard Worker }
1804*7c568831SAndroid Build Coastguard Worker memset(ctx, 0, sizeof(xmlC14NCtx));
1805*7c568831SAndroid Build Coastguard Worker
1806*7c568831SAndroid Build Coastguard Worker /*
1807*7c568831SAndroid Build Coastguard Worker * initialize C14N context
1808*7c568831SAndroid Build Coastguard Worker */
1809*7c568831SAndroid Build Coastguard Worker ctx->doc = doc;
1810*7c568831SAndroid Build Coastguard Worker ctx->with_comments = with_comments;
1811*7c568831SAndroid Build Coastguard Worker ctx->is_visible_callback = is_visible_callback;
1812*7c568831SAndroid Build Coastguard Worker ctx->user_data = user_data;
1813*7c568831SAndroid Build Coastguard Worker ctx->buf = buf;
1814*7c568831SAndroid Build Coastguard Worker ctx->parent_is_doc = 1;
1815*7c568831SAndroid Build Coastguard Worker ctx->pos = XMLC14N_BEFORE_DOCUMENT_ELEMENT;
1816*7c568831SAndroid Build Coastguard Worker ctx->ns_rendered = xmlC14NVisibleNsStackCreate();
1817*7c568831SAndroid Build Coastguard Worker
1818*7c568831SAndroid Build Coastguard Worker if(ctx->ns_rendered == NULL) {
1819*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(ctx);
1820*7c568831SAndroid Build Coastguard Worker xmlC14NFreeCtx(ctx);
1821*7c568831SAndroid Build Coastguard Worker return (NULL);
1822*7c568831SAndroid Build Coastguard Worker }
1823*7c568831SAndroid Build Coastguard Worker
1824*7c568831SAndroid Build Coastguard Worker /*
1825*7c568831SAndroid Build Coastguard Worker * Set "mode" flag and remember list of inclusive prefixes
1826*7c568831SAndroid Build Coastguard Worker * for exclusive c14n
1827*7c568831SAndroid Build Coastguard Worker */
1828*7c568831SAndroid Build Coastguard Worker ctx->mode = mode;
1829*7c568831SAndroid Build Coastguard Worker if(xmlC14NIsExclusive(ctx)) {
1830*7c568831SAndroid Build Coastguard Worker ctx->inclusive_ns_prefixes = inclusive_ns_prefixes;
1831*7c568831SAndroid Build Coastguard Worker }
1832*7c568831SAndroid Build Coastguard Worker
1833*7c568831SAndroid Build Coastguard Worker return (ctx);
1834*7c568831SAndroid Build Coastguard Worker }
1835*7c568831SAndroid Build Coastguard Worker
1836*7c568831SAndroid Build Coastguard Worker /**
1837*7c568831SAndroid Build Coastguard Worker * xmlC14NExecute:
1838*7c568831SAndroid Build Coastguard Worker * @doc: the XML document for canonization
1839*7c568831SAndroid Build Coastguard Worker * @is_visible_callback:the function to use to determine is node visible
1840*7c568831SAndroid Build Coastguard Worker * or not
1841*7c568831SAndroid Build Coastguard Worker * @user_data: the first parameter for @is_visible_callback function
1842*7c568831SAndroid Build Coastguard Worker * (in most cases, it is nodes set)
1843*7c568831SAndroid Build Coastguard Worker * @mode: the c14n mode (see @xmlC14NMode)
1844*7c568831SAndroid Build Coastguard Worker * @inclusive_ns_prefixes: the list of inclusive namespace prefixes
1845*7c568831SAndroid Build Coastguard Worker * ended with a NULL or NULL if there is no
1846*7c568831SAndroid Build Coastguard Worker * inclusive namespaces (only for exclusive
1847*7c568831SAndroid Build Coastguard Worker * canonicalization, ignored otherwise)
1848*7c568831SAndroid Build Coastguard Worker * @with_comments: include comments in the result (!=0) or not (==0)
1849*7c568831SAndroid Build Coastguard Worker * @buf: the output buffer to store canonical XML; this
1850*7c568831SAndroid Build Coastguard Worker * buffer MUST have encoder==NULL because C14N requires
1851*7c568831SAndroid Build Coastguard Worker * UTF-8 output
1852*7c568831SAndroid Build Coastguard Worker *
1853*7c568831SAndroid Build Coastguard Worker * Dumps the canonized image of given XML document into the provided buffer.
1854*7c568831SAndroid Build Coastguard Worker * For details see "Canonical XML" (http://www.w3.org/TR/xml-c14n) or
1855*7c568831SAndroid Build Coastguard Worker * "Exclusive XML Canonicalization" (http://www.w3.org/TR/xml-exc-c14n)
1856*7c568831SAndroid Build Coastguard Worker *
1857*7c568831SAndroid Build Coastguard Worker * Returns non-negative value on success or a negative value on fail
1858*7c568831SAndroid Build Coastguard Worker */
1859*7c568831SAndroid Build Coastguard Worker int
xmlC14NExecute(xmlDocPtr doc,xmlC14NIsVisibleCallback is_visible_callback,void * user_data,int mode,xmlChar ** inclusive_ns_prefixes,int with_comments,xmlOutputBufferPtr buf)1860*7c568831SAndroid Build Coastguard Worker xmlC14NExecute(xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback,
1861*7c568831SAndroid Build Coastguard Worker void* user_data, int mode, xmlChar **inclusive_ns_prefixes,
1862*7c568831SAndroid Build Coastguard Worker int with_comments, xmlOutputBufferPtr buf) {
1863*7c568831SAndroid Build Coastguard Worker
1864*7c568831SAndroid Build Coastguard Worker xmlC14NCtxPtr ctx;
1865*7c568831SAndroid Build Coastguard Worker xmlC14NMode c14n_mode = XML_C14N_1_0;
1866*7c568831SAndroid Build Coastguard Worker int ret;
1867*7c568831SAndroid Build Coastguard Worker
1868*7c568831SAndroid Build Coastguard Worker if ((buf == NULL) || (doc == NULL)) {
1869*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(NULL);
1870*7c568831SAndroid Build Coastguard Worker return (-1);
1871*7c568831SAndroid Build Coastguard Worker }
1872*7c568831SAndroid Build Coastguard Worker
1873*7c568831SAndroid Build Coastguard Worker /* for backward compatibility, we have to have "mode" as "int"
1874*7c568831SAndroid Build Coastguard Worker and here we check that user gives valid value */
1875*7c568831SAndroid Build Coastguard Worker switch(mode) {
1876*7c568831SAndroid Build Coastguard Worker case XML_C14N_1_0:
1877*7c568831SAndroid Build Coastguard Worker case XML_C14N_EXCLUSIVE_1_0:
1878*7c568831SAndroid Build Coastguard Worker case XML_C14N_1_1:
1879*7c568831SAndroid Build Coastguard Worker c14n_mode = (xmlC14NMode)mode;
1880*7c568831SAndroid Build Coastguard Worker break;
1881*7c568831SAndroid Build Coastguard Worker default:
1882*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(NULL);
1883*7c568831SAndroid Build Coastguard Worker return (-1);
1884*7c568831SAndroid Build Coastguard Worker }
1885*7c568831SAndroid Build Coastguard Worker
1886*7c568831SAndroid Build Coastguard Worker /*
1887*7c568831SAndroid Build Coastguard Worker * Validate the encoding output buffer encoding
1888*7c568831SAndroid Build Coastguard Worker */
1889*7c568831SAndroid Build Coastguard Worker if (buf->encoder != NULL) {
1890*7c568831SAndroid Build Coastguard Worker xmlC14NErr(NULL, (xmlNodePtr) doc, XML_C14N_REQUIRES_UTF8,
1891*7c568831SAndroid Build Coastguard Worker "xmlC14NExecute: output buffer encoder != NULL but C14N requires UTF8 output\n");
1892*7c568831SAndroid Build Coastguard Worker return (-1);
1893*7c568831SAndroid Build Coastguard Worker }
1894*7c568831SAndroid Build Coastguard Worker
1895*7c568831SAndroid Build Coastguard Worker ctx = xmlC14NNewCtx(doc, is_visible_callback, user_data,
1896*7c568831SAndroid Build Coastguard Worker c14n_mode, inclusive_ns_prefixes,
1897*7c568831SAndroid Build Coastguard Worker with_comments, buf);
1898*7c568831SAndroid Build Coastguard Worker if (ctx == NULL) {
1899*7c568831SAndroid Build Coastguard Worker xmlC14NErr(NULL, (xmlNodePtr) doc, XML_C14N_CREATE_CTXT,
1900*7c568831SAndroid Build Coastguard Worker "xmlC14NExecute: unable to create C14N context\n");
1901*7c568831SAndroid Build Coastguard Worker return (-1);
1902*7c568831SAndroid Build Coastguard Worker }
1903*7c568831SAndroid Build Coastguard Worker
1904*7c568831SAndroid Build Coastguard Worker
1905*7c568831SAndroid Build Coastguard Worker
1906*7c568831SAndroid Build Coastguard Worker /*
1907*7c568831SAndroid Build Coastguard Worker * Root Node
1908*7c568831SAndroid Build Coastguard Worker * The root node is the parent of the top-level document element. The
1909*7c568831SAndroid Build Coastguard Worker * result of processing each of its child nodes that is in the node-set
1910*7c568831SAndroid Build Coastguard Worker * in document order. The root node does not generate a byte order mark,
1911*7c568831SAndroid Build Coastguard Worker * XML declaration, nor anything from within the document type
1912*7c568831SAndroid Build Coastguard Worker * declaration.
1913*7c568831SAndroid Build Coastguard Worker */
1914*7c568831SAndroid Build Coastguard Worker if (doc->children != NULL) {
1915*7c568831SAndroid Build Coastguard Worker ret = xmlC14NProcessNodeList(ctx, doc->children);
1916*7c568831SAndroid Build Coastguard Worker if (ret < 0) {
1917*7c568831SAndroid Build Coastguard Worker xmlC14NFreeCtx(ctx);
1918*7c568831SAndroid Build Coastguard Worker return (-1);
1919*7c568831SAndroid Build Coastguard Worker }
1920*7c568831SAndroid Build Coastguard Worker }
1921*7c568831SAndroid Build Coastguard Worker
1922*7c568831SAndroid Build Coastguard Worker /*
1923*7c568831SAndroid Build Coastguard Worker * Flush buffer to get number of bytes written
1924*7c568831SAndroid Build Coastguard Worker */
1925*7c568831SAndroid Build Coastguard Worker ret = xmlOutputBufferFlush(buf);
1926*7c568831SAndroid Build Coastguard Worker if (ret < 0) {
1927*7c568831SAndroid Build Coastguard Worker xmlC14NErr(ctx, NULL, buf->error, "flushing output buffer");
1928*7c568831SAndroid Build Coastguard Worker xmlC14NFreeCtx(ctx);
1929*7c568831SAndroid Build Coastguard Worker return (-1);
1930*7c568831SAndroid Build Coastguard Worker }
1931*7c568831SAndroid Build Coastguard Worker
1932*7c568831SAndroid Build Coastguard Worker /*
1933*7c568831SAndroid Build Coastguard Worker * Cleanup
1934*7c568831SAndroid Build Coastguard Worker */
1935*7c568831SAndroid Build Coastguard Worker xmlC14NFreeCtx(ctx);
1936*7c568831SAndroid Build Coastguard Worker return (ret);
1937*7c568831SAndroid Build Coastguard Worker }
1938*7c568831SAndroid Build Coastguard Worker
1939*7c568831SAndroid Build Coastguard Worker /**
1940*7c568831SAndroid Build Coastguard Worker * xmlC14NDocSaveTo:
1941*7c568831SAndroid Build Coastguard Worker * @doc: the XML document for canonization
1942*7c568831SAndroid Build Coastguard Worker * @nodes: the nodes set to be included in the canonized image
1943*7c568831SAndroid Build Coastguard Worker * or NULL if all document nodes should be included
1944*7c568831SAndroid Build Coastguard Worker * @mode: the c14n mode (see @xmlC14NMode)
1945*7c568831SAndroid Build Coastguard Worker * @inclusive_ns_prefixes: the list of inclusive namespace prefixes
1946*7c568831SAndroid Build Coastguard Worker * ended with a NULL or NULL if there is no
1947*7c568831SAndroid Build Coastguard Worker * inclusive namespaces (only for exclusive
1948*7c568831SAndroid Build Coastguard Worker * canonicalization, ignored otherwise)
1949*7c568831SAndroid Build Coastguard Worker * @with_comments: include comments in the result (!=0) or not (==0)
1950*7c568831SAndroid Build Coastguard Worker * @buf: the output buffer to store canonical XML; this
1951*7c568831SAndroid Build Coastguard Worker * buffer MUST have encoder==NULL because C14N requires
1952*7c568831SAndroid Build Coastguard Worker * UTF-8 output
1953*7c568831SAndroid Build Coastguard Worker *
1954*7c568831SAndroid Build Coastguard Worker * Dumps the canonized image of given XML document into the provided buffer.
1955*7c568831SAndroid Build Coastguard Worker * For details see "Canonical XML" (http://www.w3.org/TR/xml-c14n) or
1956*7c568831SAndroid Build Coastguard Worker * "Exclusive XML Canonicalization" (http://www.w3.org/TR/xml-exc-c14n)
1957*7c568831SAndroid Build Coastguard Worker *
1958*7c568831SAndroid Build Coastguard Worker * Returns non-negative value on success or a negative value on fail
1959*7c568831SAndroid Build Coastguard Worker */
1960*7c568831SAndroid Build Coastguard Worker int
xmlC14NDocSaveTo(xmlDocPtr doc,xmlNodeSetPtr nodes,int mode,xmlChar ** inclusive_ns_prefixes,int with_comments,xmlOutputBufferPtr buf)1961*7c568831SAndroid Build Coastguard Worker xmlC14NDocSaveTo(xmlDocPtr doc, xmlNodeSetPtr nodes,
1962*7c568831SAndroid Build Coastguard Worker int mode, xmlChar ** inclusive_ns_prefixes,
1963*7c568831SAndroid Build Coastguard Worker int with_comments, xmlOutputBufferPtr buf) {
1964*7c568831SAndroid Build Coastguard Worker return(xmlC14NExecute(doc,
1965*7c568831SAndroid Build Coastguard Worker xmlC14NIsNodeInNodeset,
1966*7c568831SAndroid Build Coastguard Worker nodes,
1967*7c568831SAndroid Build Coastguard Worker mode,
1968*7c568831SAndroid Build Coastguard Worker inclusive_ns_prefixes,
1969*7c568831SAndroid Build Coastguard Worker with_comments,
1970*7c568831SAndroid Build Coastguard Worker buf));
1971*7c568831SAndroid Build Coastguard Worker }
1972*7c568831SAndroid Build Coastguard Worker
1973*7c568831SAndroid Build Coastguard Worker
1974*7c568831SAndroid Build Coastguard Worker /**
1975*7c568831SAndroid Build Coastguard Worker * xmlC14NDocDumpMemory:
1976*7c568831SAndroid Build Coastguard Worker * @doc: the XML document for canonization
1977*7c568831SAndroid Build Coastguard Worker * @nodes: the nodes set to be included in the canonized image
1978*7c568831SAndroid Build Coastguard Worker * or NULL if all document nodes should be included
1979*7c568831SAndroid Build Coastguard Worker * @mode: the c14n mode (see @xmlC14NMode)
1980*7c568831SAndroid Build Coastguard Worker * @inclusive_ns_prefixes: the list of inclusive namespace prefixes
1981*7c568831SAndroid Build Coastguard Worker * ended with a NULL or NULL if there is no
1982*7c568831SAndroid Build Coastguard Worker * inclusive namespaces (only for exclusive
1983*7c568831SAndroid Build Coastguard Worker * canonicalization, ignored otherwise)
1984*7c568831SAndroid Build Coastguard Worker * @with_comments: include comments in the result (!=0) or not (==0)
1985*7c568831SAndroid Build Coastguard Worker * @doc_txt_ptr: the memory pointer for allocated canonical XML text;
1986*7c568831SAndroid Build Coastguard Worker * the caller of this functions is responsible for calling
1987*7c568831SAndroid Build Coastguard Worker * xmlFree() to free allocated memory
1988*7c568831SAndroid Build Coastguard Worker *
1989*7c568831SAndroid Build Coastguard Worker * Dumps the canonized image of given XML document into memory.
1990*7c568831SAndroid Build Coastguard Worker * For details see "Canonical XML" (http://www.w3.org/TR/xml-c14n) or
1991*7c568831SAndroid Build Coastguard Worker * "Exclusive XML Canonicalization" (http://www.w3.org/TR/xml-exc-c14n)
1992*7c568831SAndroid Build Coastguard Worker *
1993*7c568831SAndroid Build Coastguard Worker * Returns the number of bytes written on success or a negative value on fail
1994*7c568831SAndroid Build Coastguard Worker */
1995*7c568831SAndroid Build Coastguard Worker int
xmlC14NDocDumpMemory(xmlDocPtr doc,xmlNodeSetPtr nodes,int mode,xmlChar ** inclusive_ns_prefixes,int with_comments,xmlChar ** doc_txt_ptr)1996*7c568831SAndroid Build Coastguard Worker xmlC14NDocDumpMemory(xmlDocPtr doc, xmlNodeSetPtr nodes,
1997*7c568831SAndroid Build Coastguard Worker int mode, xmlChar ** inclusive_ns_prefixes,
1998*7c568831SAndroid Build Coastguard Worker int with_comments, xmlChar ** doc_txt_ptr)
1999*7c568831SAndroid Build Coastguard Worker {
2000*7c568831SAndroid Build Coastguard Worker int ret;
2001*7c568831SAndroid Build Coastguard Worker xmlOutputBufferPtr buf;
2002*7c568831SAndroid Build Coastguard Worker
2003*7c568831SAndroid Build Coastguard Worker if (doc_txt_ptr == NULL) {
2004*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(NULL);
2005*7c568831SAndroid Build Coastguard Worker return (-1);
2006*7c568831SAndroid Build Coastguard Worker }
2007*7c568831SAndroid Build Coastguard Worker
2008*7c568831SAndroid Build Coastguard Worker *doc_txt_ptr = NULL;
2009*7c568831SAndroid Build Coastguard Worker
2010*7c568831SAndroid Build Coastguard Worker /*
2011*7c568831SAndroid Build Coastguard Worker * create memory buffer with UTF8 (default) encoding
2012*7c568831SAndroid Build Coastguard Worker */
2013*7c568831SAndroid Build Coastguard Worker buf = xmlAllocOutputBuffer(NULL);
2014*7c568831SAndroid Build Coastguard Worker if (buf == NULL) {
2015*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(NULL);
2016*7c568831SAndroid Build Coastguard Worker return (-1);
2017*7c568831SAndroid Build Coastguard Worker }
2018*7c568831SAndroid Build Coastguard Worker
2019*7c568831SAndroid Build Coastguard Worker /*
2020*7c568831SAndroid Build Coastguard Worker * canonize document and write to buffer
2021*7c568831SAndroid Build Coastguard Worker */
2022*7c568831SAndroid Build Coastguard Worker ret = xmlC14NDocSaveTo(doc, nodes, mode, inclusive_ns_prefixes,
2023*7c568831SAndroid Build Coastguard Worker with_comments, buf);
2024*7c568831SAndroid Build Coastguard Worker if (ret < 0) {
2025*7c568831SAndroid Build Coastguard Worker (void) xmlOutputBufferClose(buf);
2026*7c568831SAndroid Build Coastguard Worker return (-1);
2027*7c568831SAndroid Build Coastguard Worker }
2028*7c568831SAndroid Build Coastguard Worker
2029*7c568831SAndroid Build Coastguard Worker ret = xmlBufUse(buf->buffer);
2030*7c568831SAndroid Build Coastguard Worker if (ret >= 0) {
2031*7c568831SAndroid Build Coastguard Worker *doc_txt_ptr = xmlStrndup(xmlBufContent(buf->buffer), ret);
2032*7c568831SAndroid Build Coastguard Worker }
2033*7c568831SAndroid Build Coastguard Worker (void) xmlOutputBufferClose(buf);
2034*7c568831SAndroid Build Coastguard Worker
2035*7c568831SAndroid Build Coastguard Worker if ((*doc_txt_ptr == NULL) && (ret >= 0)) {
2036*7c568831SAndroid Build Coastguard Worker xmlC14NErrMemory(NULL);
2037*7c568831SAndroid Build Coastguard Worker return (-1);
2038*7c568831SAndroid Build Coastguard Worker }
2039*7c568831SAndroid Build Coastguard Worker return (ret);
2040*7c568831SAndroid Build Coastguard Worker }
2041*7c568831SAndroid Build Coastguard Worker
2042*7c568831SAndroid Build Coastguard Worker /**
2043*7c568831SAndroid Build Coastguard Worker * xmlC14NDocSave:
2044*7c568831SAndroid Build Coastguard Worker * @doc: the XML document for canonization
2045*7c568831SAndroid Build Coastguard Worker * @nodes: the nodes set to be included in the canonized image
2046*7c568831SAndroid Build Coastguard Worker * or NULL if all document nodes should be included
2047*7c568831SAndroid Build Coastguard Worker * @mode: the c14n mode (see @xmlC14NMode)
2048*7c568831SAndroid Build Coastguard Worker * @inclusive_ns_prefixes: the list of inclusive namespace prefixes
2049*7c568831SAndroid Build Coastguard Worker * ended with a NULL or NULL if there is no
2050*7c568831SAndroid Build Coastguard Worker * inclusive namespaces (only for exclusive
2051*7c568831SAndroid Build Coastguard Worker * canonicalization, ignored otherwise)
2052*7c568831SAndroid Build Coastguard Worker * @with_comments: include comments in the result (!=0) or not (==0)
2053*7c568831SAndroid Build Coastguard Worker * @filename: the filename to store canonical XML image
2054*7c568831SAndroid Build Coastguard Worker * @compression: the compression level (zlib required):
2055*7c568831SAndroid Build Coastguard Worker * -1 - libxml default,
2056*7c568831SAndroid Build Coastguard Worker * 0 - uncompressed,
2057*7c568831SAndroid Build Coastguard Worker * >0 - compression level
2058*7c568831SAndroid Build Coastguard Worker *
2059*7c568831SAndroid Build Coastguard Worker * Dumps the canonized image of given XML document into the file.
2060*7c568831SAndroid Build Coastguard Worker * For details see "Canonical XML" (http://www.w3.org/TR/xml-c14n) or
2061*7c568831SAndroid Build Coastguard Worker * "Exclusive XML Canonicalization" (http://www.w3.org/TR/xml-exc-c14n)
2062*7c568831SAndroid Build Coastguard Worker *
2063*7c568831SAndroid Build Coastguard Worker * Returns the number of bytes written success or a negative value on fail
2064*7c568831SAndroid Build Coastguard Worker */
2065*7c568831SAndroid Build Coastguard Worker int
xmlC14NDocSave(xmlDocPtr doc,xmlNodeSetPtr nodes,int mode,xmlChar ** inclusive_ns_prefixes,int with_comments,const char * filename,int compression)2066*7c568831SAndroid Build Coastguard Worker xmlC14NDocSave(xmlDocPtr doc, xmlNodeSetPtr nodes,
2067*7c568831SAndroid Build Coastguard Worker int mode, xmlChar ** inclusive_ns_prefixes,
2068*7c568831SAndroid Build Coastguard Worker int with_comments, const char *filename, int compression)
2069*7c568831SAndroid Build Coastguard Worker {
2070*7c568831SAndroid Build Coastguard Worker xmlOutputBufferPtr buf;
2071*7c568831SAndroid Build Coastguard Worker int ret;
2072*7c568831SAndroid Build Coastguard Worker
2073*7c568831SAndroid Build Coastguard Worker if (filename == NULL) {
2074*7c568831SAndroid Build Coastguard Worker xmlC14NErrParam(NULL);
2075*7c568831SAndroid Build Coastguard Worker return (-1);
2076*7c568831SAndroid Build Coastguard Worker }
2077*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_ZLIB_ENABLED
2078*7c568831SAndroid Build Coastguard Worker if (compression < 0)
2079*7c568831SAndroid Build Coastguard Worker compression = xmlGetCompressMode();
2080*7c568831SAndroid Build Coastguard Worker #endif
2081*7c568831SAndroid Build Coastguard Worker
2082*7c568831SAndroid Build Coastguard Worker /*
2083*7c568831SAndroid Build Coastguard Worker * save the content to a temp buffer, use default UTF8 encoding.
2084*7c568831SAndroid Build Coastguard Worker */
2085*7c568831SAndroid Build Coastguard Worker buf = xmlOutputBufferCreateFilename(filename, NULL, compression);
2086*7c568831SAndroid Build Coastguard Worker if (buf == NULL) {
2087*7c568831SAndroid Build Coastguard Worker xmlC14NErr(NULL, NULL, XML_IO_UNKNOWN, "creating temporary filename");
2088*7c568831SAndroid Build Coastguard Worker return (-1);
2089*7c568831SAndroid Build Coastguard Worker }
2090*7c568831SAndroid Build Coastguard Worker
2091*7c568831SAndroid Build Coastguard Worker /*
2092*7c568831SAndroid Build Coastguard Worker * canonize document and write to buffer
2093*7c568831SAndroid Build Coastguard Worker */
2094*7c568831SAndroid Build Coastguard Worker ret = xmlC14NDocSaveTo(doc, nodes, mode, inclusive_ns_prefixes,
2095*7c568831SAndroid Build Coastguard Worker with_comments, buf);
2096*7c568831SAndroid Build Coastguard Worker if (ret < 0) {
2097*7c568831SAndroid Build Coastguard Worker (void) xmlOutputBufferClose(buf);
2098*7c568831SAndroid Build Coastguard Worker return (-1);
2099*7c568831SAndroid Build Coastguard Worker }
2100*7c568831SAndroid Build Coastguard Worker
2101*7c568831SAndroid Build Coastguard Worker /*
2102*7c568831SAndroid Build Coastguard Worker * get the numbers of bytes written
2103*7c568831SAndroid Build Coastguard Worker */
2104*7c568831SAndroid Build Coastguard Worker ret = xmlOutputBufferClose(buf);
2105*7c568831SAndroid Build Coastguard Worker return (ret);
2106*7c568831SAndroid Build Coastguard Worker }
2107*7c568831SAndroid Build Coastguard Worker
2108*7c568831SAndroid Build Coastguard Worker /**
2109*7c568831SAndroid Build Coastguard Worker * xmlC11NNormalizeString:
2110*7c568831SAndroid Build Coastguard Worker * @input: the input string
2111*7c568831SAndroid Build Coastguard Worker * @mode: the normalization mode (attribute, comment, PI or text)
2112*7c568831SAndroid Build Coastguard Worker *
2113*7c568831SAndroid Build Coastguard Worker * Converts a string to a canonical (normalized) format. The code is stolen
2114*7c568831SAndroid Build Coastguard Worker * from xmlEncodeEntitiesReentrant(). Added normalization of \x09, \x0a, \x0A
2115*7c568831SAndroid Build Coastguard Worker * and the @mode parameter
2116*7c568831SAndroid Build Coastguard Worker *
2117*7c568831SAndroid Build Coastguard Worker * Returns a normalized string (caller is responsible for calling xmlFree())
2118*7c568831SAndroid Build Coastguard Worker * or NULL if an error occurs
2119*7c568831SAndroid Build Coastguard Worker */
2120*7c568831SAndroid Build Coastguard Worker static xmlChar *
xmlC11NNormalizeString(const xmlChar * input,xmlC14NNormalizationMode mode)2121*7c568831SAndroid Build Coastguard Worker xmlC11NNormalizeString(const xmlChar * input,
2122*7c568831SAndroid Build Coastguard Worker xmlC14NNormalizationMode mode)
2123*7c568831SAndroid Build Coastguard Worker {
2124*7c568831SAndroid Build Coastguard Worker const xmlChar *cur = input;
2125*7c568831SAndroid Build Coastguard Worker xmlChar *buffer = NULL;
2126*7c568831SAndroid Build Coastguard Worker xmlChar *out = NULL;
2127*7c568831SAndroid Build Coastguard Worker int buffer_size = 0;
2128*7c568831SAndroid Build Coastguard Worker
2129*7c568831SAndroid Build Coastguard Worker if (input == NULL)
2130*7c568831SAndroid Build Coastguard Worker return (NULL);
2131*7c568831SAndroid Build Coastguard Worker
2132*7c568831SAndroid Build Coastguard Worker /*
2133*7c568831SAndroid Build Coastguard Worker * allocate an translation buffer.
2134*7c568831SAndroid Build Coastguard Worker */
2135*7c568831SAndroid Build Coastguard Worker buffer_size = 1000;
2136*7c568831SAndroid Build Coastguard Worker buffer = xmlMalloc(buffer_size);
2137*7c568831SAndroid Build Coastguard Worker if (buffer == NULL)
2138*7c568831SAndroid Build Coastguard Worker return (NULL);
2139*7c568831SAndroid Build Coastguard Worker out = buffer;
2140*7c568831SAndroid Build Coastguard Worker
2141*7c568831SAndroid Build Coastguard Worker while (*cur != '\0') {
2142*7c568831SAndroid Build Coastguard Worker if ((out - buffer) > (buffer_size - 10)) {
2143*7c568831SAndroid Build Coastguard Worker xmlChar *tmp;
2144*7c568831SAndroid Build Coastguard Worker int indx = out - buffer;
2145*7c568831SAndroid Build Coastguard Worker
2146*7c568831SAndroid Build Coastguard Worker buffer_size *= 2;
2147*7c568831SAndroid Build Coastguard Worker tmp = xmlRealloc(buffer, buffer_size);
2148*7c568831SAndroid Build Coastguard Worker if (tmp == NULL) {
2149*7c568831SAndroid Build Coastguard Worker xmlFree(buffer);
2150*7c568831SAndroid Build Coastguard Worker return(NULL);
2151*7c568831SAndroid Build Coastguard Worker }
2152*7c568831SAndroid Build Coastguard Worker buffer = tmp;
2153*7c568831SAndroid Build Coastguard Worker out = &buffer[indx];
2154*7c568831SAndroid Build Coastguard Worker }
2155*7c568831SAndroid Build Coastguard Worker
2156*7c568831SAndroid Build Coastguard Worker if ((*cur == '<') && ((mode == XMLC14N_NORMALIZE_ATTR) ||
2157*7c568831SAndroid Build Coastguard Worker (mode == XMLC14N_NORMALIZE_TEXT))) {
2158*7c568831SAndroid Build Coastguard Worker *out++ = '&';
2159*7c568831SAndroid Build Coastguard Worker *out++ = 'l';
2160*7c568831SAndroid Build Coastguard Worker *out++ = 't';
2161*7c568831SAndroid Build Coastguard Worker *out++ = ';';
2162*7c568831SAndroid Build Coastguard Worker } else if ((*cur == '>') && (mode == XMLC14N_NORMALIZE_TEXT)) {
2163*7c568831SAndroid Build Coastguard Worker *out++ = '&';
2164*7c568831SAndroid Build Coastguard Worker *out++ = 'g';
2165*7c568831SAndroid Build Coastguard Worker *out++ = 't';
2166*7c568831SAndroid Build Coastguard Worker *out++ = ';';
2167*7c568831SAndroid Build Coastguard Worker } else if ((*cur == '&') && ((mode == XMLC14N_NORMALIZE_ATTR) ||
2168*7c568831SAndroid Build Coastguard Worker (mode == XMLC14N_NORMALIZE_TEXT))) {
2169*7c568831SAndroid Build Coastguard Worker *out++ = '&';
2170*7c568831SAndroid Build Coastguard Worker *out++ = 'a';
2171*7c568831SAndroid Build Coastguard Worker *out++ = 'm';
2172*7c568831SAndroid Build Coastguard Worker *out++ = 'p';
2173*7c568831SAndroid Build Coastguard Worker *out++ = ';';
2174*7c568831SAndroid Build Coastguard Worker } else if ((*cur == '"') && (mode == XMLC14N_NORMALIZE_ATTR)) {
2175*7c568831SAndroid Build Coastguard Worker *out++ = '&';
2176*7c568831SAndroid Build Coastguard Worker *out++ = 'q';
2177*7c568831SAndroid Build Coastguard Worker *out++ = 'u';
2178*7c568831SAndroid Build Coastguard Worker *out++ = 'o';
2179*7c568831SAndroid Build Coastguard Worker *out++ = 't';
2180*7c568831SAndroid Build Coastguard Worker *out++ = ';';
2181*7c568831SAndroid Build Coastguard Worker } else if ((*cur == '\x09') && (mode == XMLC14N_NORMALIZE_ATTR)) {
2182*7c568831SAndroid Build Coastguard Worker *out++ = '&';
2183*7c568831SAndroid Build Coastguard Worker *out++ = '#';
2184*7c568831SAndroid Build Coastguard Worker *out++ = 'x';
2185*7c568831SAndroid Build Coastguard Worker *out++ = '9';
2186*7c568831SAndroid Build Coastguard Worker *out++ = ';';
2187*7c568831SAndroid Build Coastguard Worker } else if ((*cur == '\x0A') && (mode == XMLC14N_NORMALIZE_ATTR)) {
2188*7c568831SAndroid Build Coastguard Worker *out++ = '&';
2189*7c568831SAndroid Build Coastguard Worker *out++ = '#';
2190*7c568831SAndroid Build Coastguard Worker *out++ = 'x';
2191*7c568831SAndroid Build Coastguard Worker *out++ = 'A';
2192*7c568831SAndroid Build Coastguard Worker *out++ = ';';
2193*7c568831SAndroid Build Coastguard Worker } else if ((*cur == '\x0D') && ((mode == XMLC14N_NORMALIZE_ATTR) ||
2194*7c568831SAndroid Build Coastguard Worker (mode == XMLC14N_NORMALIZE_TEXT) ||
2195*7c568831SAndroid Build Coastguard Worker (mode == XMLC14N_NORMALIZE_COMMENT) ||
2196*7c568831SAndroid Build Coastguard Worker (mode == XMLC14N_NORMALIZE_PI))) {
2197*7c568831SAndroid Build Coastguard Worker *out++ = '&';
2198*7c568831SAndroid Build Coastguard Worker *out++ = '#';
2199*7c568831SAndroid Build Coastguard Worker *out++ = 'x';
2200*7c568831SAndroid Build Coastguard Worker *out++ = 'D';
2201*7c568831SAndroid Build Coastguard Worker *out++ = ';';
2202*7c568831SAndroid Build Coastguard Worker } else {
2203*7c568831SAndroid Build Coastguard Worker /*
2204*7c568831SAndroid Build Coastguard Worker * Works because on UTF-8, all extended sequences cannot
2205*7c568831SAndroid Build Coastguard Worker * result in bytes in the ASCII range.
2206*7c568831SAndroid Build Coastguard Worker */
2207*7c568831SAndroid Build Coastguard Worker *out++ = *cur;
2208*7c568831SAndroid Build Coastguard Worker }
2209*7c568831SAndroid Build Coastguard Worker cur++;
2210*7c568831SAndroid Build Coastguard Worker }
2211*7c568831SAndroid Build Coastguard Worker *out = 0;
2212*7c568831SAndroid Build Coastguard Worker return (buffer);
2213*7c568831SAndroid Build Coastguard Worker }
2214*7c568831SAndroid Build Coastguard Worker
2215*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_C14N_ENABLED */
2216