~ubuntu-branches/ubuntu/utopic/libxml2/utopic

« back to all changes in this revision

Viewing changes to .pc/0005-properly-quote-the-namespace-uris-written-out-during.patch/c14n.c

  • Committer: Package Import Robot
  • Author(s): Aron Xu, Christian Svensson, Daniel Schepler, Helmut Grohne, Adam Conrad, Matthias Klose, Aron Xu
  • Date: 2014-07-09 05:40:15 UTC
  • mto: This revision was merged to the branch mainline in revision 75.
  • Revision ID: package-import@ubuntu.com-20140709054015-rdnfjxrf3zvmw6l7
[ Christian Svensson ]
* Do not build-depend on readline (Closes: #742350)

[ Daniel Schepler ]
* Patch to bootstrap without python (Closes: #738080)

[ Helmut Grohne ]
* Drop unneeded B-D on perl and binutils (Closes: #753005)

[ Adam Conrad ]
* Actually run dh_autoreconf, which the old/new mixed rules file misses.

[ Matthias Klose ]
* Add patch to fix python multiarch issue
* Allow the package to cross-build by tweaking B-Ds on python
* Set PYTHON_LIBS for cross builds

[ Aron Xu ]
* Use correct $CC
* Configure udeb without python
* New round of cherry-picking upstream fixes
  - Includes fixes for CVE-2014-0191 (Closes: #747309).
* Call prename with -vf
* Require python-all-dev (>= 2.7.5-5~)
* Bump std-ver: 3.9.4 -> 3.9.5, no change

Show diffs side-by-side

added added

removed removed

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