pocxxeci 0.30.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pocxxeci might be problematic. Click here for more details.

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