Annotation of embedaddon/libxml2/c14n.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>