15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Canonical XML implementation test program
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (http://www.w3.org/TR/2001/REC-xml-c14n-20010315)
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See Copyright for the status of this software.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Author: Aleksey Sanin <aleksey@aleksey.com>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "libxml.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(LIBXML_C14N_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_UNISTD_H
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_STDLIB_H
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xmlmemory.h>
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/parser.h>
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xpath.h>
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xpathInternals.h>
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/c14n.h>
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void usage(const char *name) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	"Usage: %s <mode> <xml-file> [<xpath-expr>] [<inclusive-ns-list>]\n",
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    name);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr, "where <mode> is one of following:\n");
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	"--with-comments       \t XML file canonicalization v1.0 w comments \n");
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	"--without-comments    \t XML file canonicalization v1.0 w/o comments\n");
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	"--1-1-with-comments       \t XML file canonicalization v1.1 w comments\n");
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	"--1-1-without-comments    \t XML file canonicalization v1.1 w/o comments\n");
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "--exc-with-comments   \t Exclusive XML file canonicalization v1.0 w comments\n");
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "--exc-without-comments\t Exclusive XML file canonicalization v1.0 w/o comments\n");
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlXPathObjectPtr
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)load_xpath_expr (xmlDocPtr parent_doc, const char* filename);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlChar **parse_list(xmlChar *str);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static void print_xpath_nodes(xmlNodeSetPtr nodes); */
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)test_c14n(const char* xml_filename, int with_comments, int mode,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	const char* xpath_filename, xmlChar **inclusive_namespaces) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDocPtr doc;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathObjectPtr xpath = NULL;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *result = NULL;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ret;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * build an XML tree from a the file; we need to add default
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * attributes and resolve all character and entities references
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlSubstituteEntitiesDefault(1);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    doc = xmlReadFile(xml_filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (doc == NULL) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(-1);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Check the document is of the right kind
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if(xmlDocGetRootElement(doc) == NULL) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFreeDoc(doc);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(-1);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * load xpath file if specified
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if(xpath_filename) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xpath = load_xpath_expr(doc, xpath_filename);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(xpath == NULL) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    fprintf(stderr,"Error: unable to evaluate xpath expression\n");
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlFreeDoc(doc);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return(-1);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Canonical form
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = xmlC14NDocDumpMemory(doc,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (xpath) ? xpath->nodesetval : NULL,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    mode, inclusive_namespaces,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    with_comments, &result);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if(ret >= 0) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(result != NULL) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    write(1, result, ret);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlFree(result);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(result != NULL) xmlFree(result);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFreeDoc(doc);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(-1);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Cleanup
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if(xpath != NULL) xmlXPathFreeObject(xpath);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFreeDoc(doc);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(ret);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, char **argv) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ret = -1;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Init libxml
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlInitParser();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LIBXML_TEST_VERSION
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Parse command line and process file
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( argc < 3 ) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fprintf(stderr, "Error: wrong number of arguments.\n");
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	usage(argv[0]);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if(strcmp(argv[1], "--with-comments") == 0) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ret = test_c14n(argv[2], 1, XML_C14N_1_0, (argc > 3) ? argv[3] : NULL, NULL);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if(strcmp(argv[1], "--without-comments") == 0) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ret = test_c14n(argv[2], 0, XML_C14N_1_0, (argc > 3) ? argv[3] : NULL, NULL);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if(strcmp(argv[1], "--1-1-with-comments") == 0) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ret = test_c14n(argv[2], 1, XML_C14N_1_1, (argc > 3) ? argv[3] : NULL, NULL);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if(strcmp(argv[1], "--1-1-without-comments") == 0) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ret = test_c14n(argv[2], 0, XML_C14N_1_1, (argc > 3) ? argv[3] : NULL, NULL);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if(strcmp(argv[1], "--exc-with-comments") == 0) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlChar **list;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* load exclusive namespace from command line */
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	list = (argc > 4) ? parse_list((xmlChar *)argv[4]) : NULL;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ret = test_c14n(argv[2], 1, XML_C14N_EXCLUSIVE_1_0, (argc > 3) ? argv[3] : NULL, list);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(list != NULL) xmlFree(list);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if(strcmp(argv[1], "--exc-without-comments") == 0) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlChar **list;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* load exclusive namespace from command line */
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	list = (argc > 4) ? parse_list((xmlChar *)argv[4]) : NULL;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ret = test_c14n(argv[2], 0, XML_C14N_EXCLUSIVE_1_0, (argc > 3) ? argv[3] : NULL, list);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(list != NULL) xmlFree(list);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fprintf(stderr, "Error: bad option.\n");
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	usage(argv[0]);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Shutdown libxml
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlCleanupParser();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlMemoryDump();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return((ret >= 0) ? 0 : 1);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Macro used to grow the current buffer.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define growBufferReentrant() {						\
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_size *= 2;							\
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer = (xmlChar **)						\
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xmlRealloc(buffer, buffer_size * sizeof(xmlChar*));	\
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (buffer == NULL) {						\
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	perror("realloc failed");					\
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(NULL);							\
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }									\
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlChar **
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)parse_list(xmlChar *str) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar **buffer;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar **out = NULL;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int buffer_size = 0;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int len;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if(str == NULL) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(NULL);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len = xmlStrlen(str);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if((str[0] == '\'') && (str[len - 1] == '\'')) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	str[len - 1] = '\0';
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	str++;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * allocate an translation buffer.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_size = 1000;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (buffer == NULL) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	perror("malloc failed");
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(NULL);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out = buffer;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while(*str != '\0') {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (out - buffer > buffer_size - 10) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    int indx = out - buffer;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    growBufferReentrant();
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    out = &buffer[indx];
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(*out++) = str;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while(*str != ',' && *str != '\0') ++str;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(*str == ',') *(str++) = '\0';
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*out) = NULL;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return buffer;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlXPathObjectPtr
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathObjectPtr xpath;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDocPtr doc;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *expr;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathContextPtr ctx;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlNodePtr node;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlNsPtr ns;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * load XPath expr as a file
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlSubstituteEntitiesDefault(1);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    doc = xmlReadFile(filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (doc == NULL) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(NULL);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Check the document is of the right kind
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if(xmlDocGetRootElement(doc) == NULL) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFreeDoc(doc);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(NULL);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    node = doc->children;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	node = node->next;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if(node == NULL) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fprintf(stderr,"Error: XPath element expected in the file  \"%s\"\n", filename);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFreeDoc(doc);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(NULL);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    expr = xmlNodeGetContent(node);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if(expr == NULL) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFreeDoc(doc);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(NULL);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ctx = xmlXPathNewContext(parent_doc);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if(ctx == NULL) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fprintf(stderr,"Error: unable to create new context\n");
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlFree(expr);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlFreeDoc(doc);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(NULL);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Register namespaces
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ns = node->nsDef;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while(ns != NULL) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	    xmlFree(expr);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathFreeContext(ctx);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlFreeDoc(doc);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return(NULL);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ns = ns->next;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Evaluate xpath
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xpath = xmlXPathEvalExpression(expr, ctx);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if(xpath == NULL) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	xmlFree(expr);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlXPathFreeContext(ctx);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlFreeDoc(doc);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(NULL);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* print_xpath_nodes(xpath->nodesetval); */
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFree(expr);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathFreeContext(ctx);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFreeDoc(doc);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(xpath);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)print_xpath_nodes(xmlNodeSetPtr nodes) {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlNodePtr cur;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if(nodes == NULL ){
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fprintf(stderr, "Error: no nodes set defined\n");
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr, "Nodes Set:\n-----\n");
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i = 0; i < nodes->nodeNr; ++i) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlNsPtr ns;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ns = (xmlNsPtr)nodes->nodeTab[i];
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cur = (xmlNodePtr)ns->next;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    fprintf(stderr, "namespace \"%s\"=\"%s\" for node %s:%s\n",
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    ns->prefix, ns->href,
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    (cur->ns) ? cur->ns->prefix : BAD_CAST "", cur->name);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else if(nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cur = nodes->nodeTab[i];
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    fprintf(stderr, "element node \"%s:%s\"\n",
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    (cur->ns) ? cur->ns->prefix : BAD_CAST "", cur->name);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cur = nodes->nodeTab[i];
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    fprintf(stderr, "node \"%s\": type %d\n", cur->name, cur->type);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printf("%s : XPath/Canonicalization and output support not compiled in\n", argv[0]);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(0);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* LIBXML_C14N_ENABLED */
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365