summaryrefslogtreecommitdiffstats
path: root/src/raptor_libxml.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/raptor_libxml.c')
-rw-r--r--src/raptor_libxml.c889
1 files changed, 889 insertions, 0 deletions
diff --git a/src/raptor_libxml.c b/src/raptor_libxml.c
new file mode 100644
index 0000000..538c2c8
--- /dev/null
+++ b/src/raptor_libxml.c
@@ -0,0 +1,889 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * raptor_libxml.c - Raptor libxml functions
+ *
+ * Copyright (C) 2000-2009, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2000-2004, University of Bristol, UK http://www.bristol.ac.uk/
+ *
+ * This package is Free Software and part of Redland http://librdf.org/
+ *
+ * It is licensed under the following three licenses as alternatives:
+ * 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ * 2. GNU General Public License (GPL) V2 or any newer version
+ * 3. Apache License, V2.0 or any newer version
+ *
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ *
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ *
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <raptor_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+/* Raptor includes */
+#include "raptor2.h"
+#include "raptor_internal.h"
+
+
+#ifdef RAPTOR_XML_LIBXML
+
+
+/* prototypes */
+static void raptor_libxml_warning(void* user_data, const char *msg, ...) RAPTOR_PRINTF_FORMAT(2, 3);
+static void raptor_libxml_error_common(void* user_data, const char *msg, va_list args, const char *prefix, int is_fatal) RAPTOR_PRINTF_FORMAT(2, 0);
+static void raptor_libxml_error(void *context, const char *msg, ...) RAPTOR_PRINTF_FORMAT(2, 3);
+static void raptor_libxml_fatal_error(void *context, const char *msg, ...) RAPTOR_PRINTF_FORMAT(2, 3);
+
+static void raptor_libxml_xmlStructuredError_handler_global(void *user_data, xmlErrorPtr err);
+static void raptor_libxml_xmlStructuredError_handler_parsing(void *user_data, xmlErrorPtr err);
+
+
+
+static const char* const xml_warning_prefix="XML parser warning - ";
+static const char* const xml_error_prefix="XML parser error - ";
+static const char* const xml_generic_error_prefix="XML error - ";
+static const char* const xml_fatal_error_prefix="XML parser fatal error - ";
+static const char* const xml_validation_error_prefix="XML parser validation error - ";
+static const char* const xml_validation_warning_prefix="XML parser validation warning - ";
+
+
+#ifdef HAVE_XMLSAX2INTERNALSUBSET
+/* SAX2 - 2.6.0 or later */
+#define libxml2_internalSubset xmlSAX2InternalSubset
+#define libxml2_externalSubset xmlSAX2ExternalSubset
+#define libxml2_isStandalone xmlSAX2IsStandalone
+#define libxml2_hasInternalSubset xmlSAX2HasInternalSubset
+#define libxml2_hasExternalSubset xmlSAX2HasExternalSubset
+#define libxml2_resolveEntity xmlSAX2ResolveEntity
+#define libxml2_getEntity xmlSAX2GetEntity
+#define libxml2_getParameterEntity xmlSAX2GetParameterEntity
+#define libxml2_entityDecl xmlSAX2EntityDecl
+#define libxml2_unparsedEntityDecl xmlSAX2UnparsedEntityDecl
+#define libxml2_startDocument xmlSAX2StartDocument
+#define libxml2_endDocument xmlSAX2EndDocument
+#else
+/* SAX1 - before libxml2 2.6.0 */
+#define libxml2_internalSubset internalSubset
+#define libxml2_externalSubset externalSubset
+#define libxml2_isStandalone isStandalone
+#define libxml2_hasInternalSubset hasInternalSubset
+#define libxml2_hasExternalSubset hasExternalSubset
+#define libxml2_resolveEntity resolveEntity
+#define libxml2_getEntity getEntity
+#define libxml2_getParameterEntity getParameterEntity
+#define libxml2_entityDecl entityDecl
+#define libxml2_unparsedEntityDecl unparsedEntityDecl
+#define libxml2_startDocument startDocument
+#define libxml2_endDocument endDocument
+#endif
+
+
+static void
+raptor_libxml_internalSubset(void* user_data, const xmlChar *name,
+ const xmlChar *ExternalID, const xmlChar *SystemID) {
+ raptor_sax2* sax2 = (raptor_sax2*)user_data;
+ libxml2_internalSubset(sax2->xc, name, ExternalID, SystemID);
+}
+
+
+#ifdef RAPTOR_LIBXML_XMLSAXHANDLER_EXTERNALSUBSET
+static void
+raptor_libxml_externalSubset(void* user_data, const xmlChar *name,
+ const xmlChar *ExternalID, const xmlChar *SystemID)
+{
+ raptor_sax2* sax2 = (raptor_sax2*)user_data;
+ libxml2_externalSubset(sax2->xc, name, ExternalID, SystemID);
+}
+#endif
+
+
+static int
+raptor_libxml_isStandalone (void* user_data)
+{
+ raptor_sax2* sax2 = (raptor_sax2*)user_data;
+ return libxml2_isStandalone(sax2->xc);
+}
+
+
+static int
+raptor_libxml_hasInternalSubset (void* user_data)
+{
+ raptor_sax2* sax2 = (raptor_sax2*)user_data;
+ return libxml2_hasInternalSubset(sax2->xc);
+}
+
+
+static int
+raptor_libxml_hasExternalSubset (void* user_data)
+{
+ raptor_sax2* sax2 = (raptor_sax2*)user_data;
+ return libxml2_hasExternalSubset(sax2->xc);
+}
+
+
+static xmlParserInputPtr
+raptor_libxml_resolveEntity(void* user_data,
+ const xmlChar *publicId, const xmlChar *systemId)
+{
+ raptor_sax2* sax2 = (raptor_sax2*)user_data;
+ xmlParserCtxtPtr ctxt = sax2->xc;
+ const unsigned char *uri_string = NULL;
+ xmlParserInputPtr entity_input = NULL;
+ int load_entity = 0;
+
+ if(ctxt->input)
+ uri_string = RAPTOR_GOOD_CAST(const unsigned char *, ctxt->input->filename);
+
+ if(!uri_string)
+ uri_string = RAPTOR_GOOD_CAST(const unsigned char *, ctxt->directory);
+
+ load_entity = RAPTOR_OPTIONS_GET_NUMERIC(sax2, RAPTOR_OPTION_LOAD_EXTERNAL_ENTITIES);
+ if(load_entity)
+ load_entity = raptor_sax2_check_load_uri_string(sax2, uri_string);
+
+ if(load_entity) {
+ entity_input = xmlLoadExternalEntity(RAPTOR_GOOD_CAST(const char*, uri_string),
+ RAPTOR_GOOD_CAST(const char*, publicId),
+ ctxt);
+ } else {
+ RAPTOR_DEBUG4("Not loading entity URI %s by policy for publicId '%s' systemId '%s'\n", uri_string, publicId, systemId);
+ }
+
+ return entity_input;
+}
+
+
+static xmlEntityPtr
+raptor_libxml_getEntity(void* user_data, const xmlChar *name)
+{
+ raptor_sax2* sax2 = (raptor_sax2*)user_data;
+ xmlParserCtxtPtr xc = sax2->xc;
+ xmlEntityPtr ret = NULL;
+
+ if(!xc)
+ return NULL;
+
+ if(!xc->inSubset) {
+ /* looks for hardcoded set of entity names - lt, gt etc. */
+ ret = xmlGetPredefinedEntity(name);
+ if(ret) {
+ RAPTOR_DEBUG2("Entity '%s' found in predefined set\n", name);
+ return ret;
+ }
+ }
+
+ /* This section uses xmlGetDocEntity which looks for entities in
+ * memory only, never from a file or URI
+ */
+ if(xc->myDoc && (xc->myDoc->standalone == 1)) {
+ RAPTOR_DEBUG2("Entity '%s' document is standalone\n", name);
+ /* Document is standalone: no entities are required to interpret doc */
+ if(xc->inSubset == 2) {
+ xc->myDoc->standalone = 0;
+ ret = xmlGetDocEntity(xc->myDoc, name);
+ xc->myDoc->standalone = 1;
+ } else {
+ ret = xmlGetDocEntity(xc->myDoc, name);
+ if(!ret) {
+ xc->myDoc->standalone = 0;
+ ret = xmlGetDocEntity(xc->myDoc, name);
+ xc->myDoc->standalone = 1;
+ }
+ }
+ } else {
+ ret = xmlGetDocEntity(xc->myDoc, name);
+ }
+
+ if(ret && !ret->children &&
+ (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
+ /* Entity is an external general parsed entity. It may be in a
+ * catalog file, user file or user URI
+ */
+ int val = 0;
+ xmlNodePtr children;
+ int load_entity = 0;
+
+ load_entity = RAPTOR_OPTIONS_GET_NUMERIC(sax2, RAPTOR_OPTION_LOAD_EXTERNAL_ENTITIES);
+ if(load_entity)
+ load_entity = raptor_sax2_check_load_uri_string(sax2, ret->URI);
+
+ if(!load_entity) {
+ RAPTOR_DEBUG2("Not getting entity URI %s by policy\n", ret->URI);
+ children = xmlNewText((const xmlChar*)"");
+ } else {
+ /* Disable SAX2 handlers so that the SAX2 events do not all get
+ * sent to callbacks during dealing with the entity parsing.
+ */
+ sax2->enabled = 0;
+ val = xmlParseCtxtExternalEntity(xc, ret->URI, ret->ExternalID, &children);
+ sax2->enabled = 1;
+ }
+
+ if(!val) {
+ xmlAddChildList((xmlNodePtr)ret, children);
+ } else {
+ xc->validate = 0;
+ return NULL;
+ }
+
+ ret->owner = 1;
+
+#if LIBXML_VERSION >= 20627
+ /* Checked field was released in 2.6.27 on 2006-10-25
+ * http://git.gnome.org/browse/libxml2/commit/?id=a37a6ad91a61d168ecc4b29263def3363fff4da6
+ *
+ */
+
+ /* Mark this entity as having been checked - never do this again */
+ if(!ret->checked)
+ ret->checked = 1;
+#endif
+ }
+
+ return ret;
+}
+
+
+static xmlEntityPtr
+raptor_libxml_getParameterEntity(void* user_data, const xmlChar *name) {
+ raptor_sax2* sax2 = (raptor_sax2*)user_data;
+ return libxml2_getParameterEntity(sax2->xc, name);
+}
+
+
+static void
+raptor_libxml_entityDecl(void* user_data, const xmlChar *name, int type,
+ const xmlChar *publicId, const xmlChar *systemId,
+ xmlChar *content) {
+ raptor_sax2* sax2 = (raptor_sax2*)user_data;
+ libxml2_entityDecl(sax2->xc, name, type, publicId, systemId, content);
+}
+
+
+static void
+raptor_libxml_unparsedEntityDecl(void* user_data, const xmlChar *name,
+ const xmlChar *publicId, const xmlChar *systemId,
+ const xmlChar *notationName) {
+ raptor_sax2* sax2 = (raptor_sax2*)user_data;
+ libxml2_unparsedEntityDecl(sax2->xc, name, publicId, systemId, notationName);
+}
+
+
+static void
+raptor_libxml_startDocument(void* user_data) {
+ raptor_sax2* sax2 = (raptor_sax2*)user_data;
+ libxml2_startDocument(sax2->xc);
+}
+
+
+static void
+raptor_libxml_endDocument(void* user_data) {
+ raptor_sax2* sax2 = (raptor_sax2*)user_data;
+ xmlParserCtxtPtr xc = sax2->xc;
+
+ libxml2_endDocument(sax2->xc);
+
+ if(xc->myDoc) {
+ xmlFreeDoc(xc->myDoc);
+ xc->myDoc = NULL;
+ }
+}
+
+
+
+static void
+raptor_libxml_set_document_locator(void* user_data, xmlSAXLocatorPtr loc)
+{
+ raptor_sax2* sax2 = (raptor_sax2*)user_data;
+ sax2->loc = loc;
+}
+
+
+void
+raptor_libxml_update_document_locator(raptor_sax2* sax2,
+ raptor_locator* locator)
+{
+ /* for storing error info */
+ xmlSAXLocatorPtr loc = sax2 ? sax2->loc : NULL;
+ xmlParserCtxtPtr xc= sax2 ? sax2->xc : NULL;
+
+ if(xc && xc->inSubset)
+ return;
+
+ if(!locator)
+ return;
+
+ locator->line= -1;
+ locator->column= -1;
+
+ if(!xc)
+ return;
+
+ if(loc) {
+ locator->line = loc->getLineNumber(xc);
+ /* Seems to be broken */
+ /* locator->column = loc->getColumnNumber(xc); */
+ }
+
+}
+
+
+static void
+raptor_libxml_warning(void* user_data, const char *msg, ...)
+{
+ raptor_sax2* sax2 = NULL;
+ va_list args;
+ int prefix_length = RAPTOR_BAD_CAST(int, strlen(xml_warning_prefix));
+ int length;
+ char *nmsg;
+ int msg_len;
+
+ /* Work around libxml2 bug - sometimes the sax2->error
+ * returns a ctx, sometimes the userdata
+ */
+ if(((raptor_sax2*)user_data)->magic == RAPTOR_LIBXML_MAGIC)
+ sax2 = (raptor_sax2*)user_data;
+ else
+ /* user_data is not userData */
+ sax2 = (raptor_sax2*)((xmlParserCtxtPtr)user_data)->userData;
+
+ va_start(args, msg);
+
+ raptor_libxml_update_document_locator(sax2, sax2->locator);
+
+ msg_len = RAPTOR_BAD_CAST(int, strlen(msg));
+ length = prefix_length + msg_len + 1;
+ nmsg = RAPTOR_MALLOC(char*, length);
+ if(nmsg) {
+ memcpy(nmsg, xml_warning_prefix, prefix_length); /* Do not copy NUL */
+ memcpy(nmsg + prefix_length, msg, msg_len + 1); /* Copy NUL */
+ if(nmsg[length-2] == '\n')
+ nmsg[length-2]='\0';
+ }
+
+ PRAGMA_IGNORE_WARNING_FORMAT_NONLITERAL_START
+ raptor_log_error_varargs(sax2->world,
+ RAPTOR_LOG_LEVEL_WARN,
+ sax2->locator,
+ nmsg ? nmsg : msg,
+ args);
+ PRAGMA_IGNORE_WARNING_END
+
+ if(nmsg)
+ RAPTOR_FREE(char*, nmsg);
+ va_end(args);
+}
+
+
+static void
+raptor_libxml_error_common(void* user_data, const char *msg, va_list args,
+ const char *prefix, int is_fatal)
+{
+ raptor_sax2* sax2 = NULL;
+ int prefix_length = RAPTOR_BAD_CAST(int, strlen(prefix));
+ int length;
+ char *nmsg;
+ int msg_len;
+ raptor_world* world = NULL;
+ raptor_locator* locator = NULL;
+ raptor_log_level l;
+
+ if(user_data) {
+ /* Work around libxml2 bug - sometimes the sax2->error
+ * returns a user_data, sometimes the userdata
+ */
+ if(((raptor_sax2*)user_data)->magic == RAPTOR_LIBXML_MAGIC)
+ sax2 = (raptor_sax2*)user_data;
+ else
+ /* user_data is not userData */
+ sax2 = (raptor_sax2*)((xmlParserCtxtPtr)user_data)->userData;
+ }
+
+ if(sax2) {
+ world = sax2->world;
+ locator = sax2->locator;
+
+ if(locator)
+ raptor_libxml_update_document_locator(sax2, sax2->locator);
+ }
+
+ msg_len = RAPTOR_BAD_CAST(int, strlen(msg));
+ length = prefix_length + msg_len + 1;
+ nmsg = RAPTOR_MALLOC(char*, length);
+ if(nmsg) {
+ memcpy(nmsg, prefix, prefix_length); /* Do not copy NUL */
+ memcpy(nmsg + prefix_length, msg, msg_len + 1); /* Copy NUL */
+ if(nmsg[length-1] == '\n')
+ nmsg[length-1]='\0';
+ }
+
+ l = (is_fatal) ? RAPTOR_LOG_LEVEL_FATAL: RAPTOR_LOG_LEVEL_ERROR;
+
+ PRAGMA_IGNORE_WARNING_FORMAT_NONLITERAL_START
+ raptor_log_error_varargs(world,
+ l,
+ locator,
+ nmsg ? nmsg : msg,
+ args);
+ PRAGMA_IGNORE_WARNING_END
+
+ if(nmsg)
+ RAPTOR_FREE(char*, nmsg);
+}
+
+
+static void
+raptor_libxml_error(void* user_data, const char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ raptor_libxml_error_common(user_data, msg, args, xml_error_prefix, 0);
+ va_end(args);
+}
+
+
+
+void
+raptor_libxml_generic_error(void* user_data, const char *msg, ...)
+{
+ raptor_world* world = (raptor_world*)user_data;
+ va_list args;
+ const char* prefix = xml_generic_error_prefix;
+ int prefix_length = RAPTOR_BAD_CAST(int, strlen(prefix));
+ int length;
+ char *nmsg;
+ int msg_len;
+
+ va_start(args, msg);
+
+ msg_len = RAPTOR_BAD_CAST(int, strlen(msg));
+ length = prefix_length + msg_len + 1;
+ nmsg = RAPTOR_MALLOC(char*, length);
+ if(nmsg) {
+ memcpy(nmsg, prefix, prefix_length); /* Do not copy NUL */
+ memcpy(nmsg + prefix_length, msg, msg_len + 1); /* Copy NUL */
+ if(nmsg[length-1] == '\n')
+ nmsg[length-1]='\0';
+ }
+
+ PRAGMA_IGNORE_WARNING_FORMAT_NONLITERAL_START
+ raptor_log_error_varargs(world, RAPTOR_LOG_LEVEL_ERROR,
+ /* locator */ NULL,
+ nmsg ? nmsg : msg,
+ args);
+ PRAGMA_IGNORE_WARNING_END
+
+ if(nmsg)
+ RAPTOR_FREE(char*, nmsg);
+
+ va_end(args);
+}
+
+
+static void
+raptor_libxml_fatal_error(void* user_data, const char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ raptor_libxml_error_common(user_data, msg, args, xml_fatal_error_prefix, 1);
+ va_end(args);
+}
+
+
+void
+raptor_libxml_validation_error(void* user_data, const char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ raptor_libxml_error_common(user_data, msg, args,
+ xml_validation_error_prefix, 1);
+ va_end(args);
+}
+
+
+void
+raptor_libxml_validation_warning(void* user_data, const char *msg, ...)
+{
+ va_list args;
+ raptor_sax2* sax2 = (raptor_sax2*)user_data;
+ int prefix_length = RAPTOR_GOOD_CAST(int, strlen(xml_validation_warning_prefix));
+ int length;
+ char *nmsg;
+ int msg_len;
+
+ va_start(args, msg);
+
+ raptor_libxml_update_document_locator(sax2, sax2->locator);
+
+ msg_len = RAPTOR_BAD_CAST(int, strlen(msg));
+ length = prefix_length + msg_len + 1;
+ nmsg = RAPTOR_MALLOC(char*, length);
+ if(nmsg) {
+ memcpy(nmsg, xml_validation_warning_prefix, prefix_length); /* Do not copy NUL */
+ memcpy(nmsg + prefix_length, msg, msg_len + 1); /* Copy NUL */
+ if(nmsg[length-2] == '\n')
+ nmsg[length-2]='\0';
+ }
+
+ PRAGMA_IGNORE_WARNING_FORMAT_NONLITERAL_START
+ raptor_log_error_varargs(sax2->world,
+ RAPTOR_LOG_LEVEL_WARN,
+ sax2->locator,
+ nmsg ? nmsg : msg,
+ args);
+ PRAGMA_IGNORE_WARNING_END
+
+ if(nmsg)
+ RAPTOR_FREE(char*, nmsg);
+ va_end(args);
+}
+
+
+/*
+ * Initialise libxml for a particular SAX2 setup
+*/
+void
+raptor_libxml_sax_init(raptor_sax2* sax2)
+{
+ xmlSAXHandler *sax = &sax2->sax;
+
+ sax->internalSubset = raptor_libxml_internalSubset;
+ sax->isStandalone = raptor_libxml_isStandalone;
+ sax->hasInternalSubset = raptor_libxml_hasInternalSubset;
+ sax->hasExternalSubset = raptor_libxml_hasExternalSubset;
+ sax->resolveEntity = raptor_libxml_resolveEntity;
+ sax->getEntity = raptor_libxml_getEntity;
+ sax->getParameterEntity = raptor_libxml_getParameterEntity;
+ sax->entityDecl = raptor_libxml_entityDecl;
+ sax->attributeDecl = NULL; /* attributeDecl */
+ sax->elementDecl = NULL; /* elementDecl */
+ sax->notationDecl = NULL; /* notationDecl */
+ sax->unparsedEntityDecl = raptor_libxml_unparsedEntityDecl;
+ sax->setDocumentLocator = raptor_libxml_set_document_locator;
+ sax->startDocument = raptor_libxml_startDocument;
+ sax->endDocument = raptor_libxml_endDocument;
+ sax->startElement= raptor_sax2_start_element;
+ sax->endElement= raptor_sax2_end_element;
+ sax->reference = NULL; /* reference */
+ sax->characters= raptor_sax2_characters;
+ sax->cdataBlock= raptor_sax2_cdata; /* like <![CDATA[...]> */
+ sax->ignorableWhitespace= raptor_sax2_cdata;
+ sax->processingInstruction = NULL; /* processingInstruction */
+ sax->comment = raptor_sax2_comment; /* comment */
+ sax->warning = (warningSAXFunc)raptor_libxml_warning;
+ sax->error = (errorSAXFunc)raptor_libxml_error;
+ sax->fatalError = (fatalErrorSAXFunc)raptor_libxml_fatal_error;
+ sax->serror = (xmlStructuredErrorFunc)raptor_libxml_xmlStructuredError_handler_parsing;
+
+#ifdef RAPTOR_LIBXML_XMLSAXHANDLER_EXTERNALSUBSET
+ sax->externalSubset = raptor_libxml_externalSubset;
+#endif
+
+#ifdef RAPTOR_LIBXML_XMLSAXHANDLER_INITIALIZED
+ sax->initialized = 1;
+#endif
+}
+
+
+void
+raptor_libxml_free(xmlParserCtxtPtr xc) {
+ libxml2_endDocument(xc);
+
+ if(xc->myDoc) {
+ xmlFreeDoc(xc->myDoc);
+ xc->myDoc = NULL;
+ }
+
+ xmlFreeParserCtxt(xc);
+}
+
+
+int
+raptor_libxml_init(raptor_world* world)
+{
+ xmlInitParser();
+
+ if(world->libxml_flags & RAPTOR_WORLD_FLAG_LIBXML_STRUCTURED_ERROR_SAVE) {
+ world->libxml_saved_structured_error_context = xmlGenericErrorContext;
+ world->libxml_saved_structured_error_handler = xmlStructuredError;
+ /* sets xmlGenericErrorContext and xmlStructuredError */
+ xmlSetStructuredErrorFunc(world,
+ (xmlStructuredErrorFunc)raptor_libxml_xmlStructuredError_handler_global);
+ }
+
+ if(world->libxml_flags & RAPTOR_WORLD_FLAG_LIBXML_GENERIC_ERROR_SAVE) {
+ world->libxml_saved_generic_error_context = xmlGenericErrorContext;
+ world->libxml_saved_generic_error_handler = xmlGenericError;
+ /* sets xmlGenericErrorContext and xmlGenericError */
+ xmlSetGenericErrorFunc(world,
+ (xmlGenericErrorFunc)raptor_libxml_generic_error);
+ }
+
+ return 0;
+}
+
+
+void
+raptor_libxml_finish(raptor_world* world)
+{
+ if(world->libxml_flags & RAPTOR_WORLD_FLAG_LIBXML_STRUCTURED_ERROR_SAVE)
+ xmlSetStructuredErrorFunc(world->libxml_saved_structured_error_context,
+ world->libxml_saved_structured_error_handler);
+
+ if(world->libxml_flags & RAPTOR_WORLD_FLAG_LIBXML_GENERIC_ERROR_SAVE)
+ xmlSetGenericErrorFunc(world->libxml_saved_generic_error_context,
+ world->libxml_saved_generic_error_handler);
+
+ xmlCleanupParser();
+}
+
+
+#if LIBXML_VERSION >= 20632
+#define XML_LAST_DL XML_FROM_SCHEMATRONV
+#else
+#if LIBXML_VERSION >= 20621
+#define XML_LAST_DL XML_FROM_I18N
+#else
+#if LIBXML_VERSION >= 20617
+#define XML_LAST_DL XML_FROM_WRITER
+#else
+#if LIBXML_VERSION >= 20616
+#define XML_LAST_DL XML_FROM_CHECK
+#else
+#if LIBXML_VERSION >= 20615
+#define XML_LAST_DL XML_FROM_VALID
+#else
+#define XML_LAST_DL XML_FROM_XSLT
+#endif
+#endif
+#endif
+#endif
+#endif
+
+/* All other symbols not specifically below noted were added during
+ * the period 2-10 October 2003 which is before the minimum libxml2
+ * version 2.6.8 release date of Mar 23 2004.
+ *
+ * When the minimum libxml2 version goes up, the #ifdefs for
+ * older versions can be removed.
+ */
+static const char* const raptor_libxml_domain_labels[XML_LAST_DL+2]= {
+ NULL, /* XML_FROM_NONE */
+ "parser", /* XML_FROM_PARSER */
+ "tree", /* XML_FROM_TREE */
+ "namespace", /* XML_FROM_NAMESPACE */
+ "validity", /* XML_FROM_DTD */
+ "HTML parser", /* XML_FROM_HTML */
+ "memory", /* XML_FROM_MEMORY */
+ "output", /* XML_FROM_OUTPUT */
+ "I/O" , /* XML_FROM_IO */
+ "FTP", /* XML_FROM_FTP */
+#if LIBXML_VERSION >= 20618
+ /* 2005-02-13 - v2.6.18 */
+ "HTTP", /* XML_FROM_HTTP */
+#endif
+ "XInclude", /* XML_FROM_XINCLUDE */
+ "XPath", /* XML_FROM_XPATH */
+ "parser", /* XML_FROM_XPOINTER */
+ "regexp", /* XML_FROM_REGEXP */
+ "Schemas datatype", /* XML_FROM_DATATYPE */
+ "Schemas parser", /* XML_FROM_SCHEMASP */
+ "Schemas validity", /* XML_FROM_SCHEMASV */
+ "Relax-NG parser", /* XML_FROM_RELAXNGP */
+ "Relax-NG validity", /* XML_FROM_RELAXNGV */
+ "Catalog", /* XML_FROM_CATALOG */
+ "C14", /* XML_FROM_C14N */
+ "XSLT", /* XML_FROM_XSLT */
+#if LIBXML_VERSION >= 20615
+ /* 2004-10-07 - v2.6.15 */
+ "validity", /* XML_FROM_VALID */
+#endif
+#if LIBXML_VERSION >= 20616
+ /* 2004-11-04 - v2.6.16 */
+ "checking", /* XML_FROM_CHECK */
+#endif
+#if LIBXML_VERSION >= 20617
+ /* 2005-01-04 - v2.6.17 */
+ "writer", /* XML_FROM_WRITER */
+#endif
+#if LIBXML_VERSION >= 20621
+ /* 2005-08-24 - v2.6.21 */
+ "module", /* XML_FROM_MODULE */
+ "encoding", /* XML_FROM_I18N */
+#endif
+#if LIBXML_VERSION >= 20632
+ /* 2008-04-08 - v2.6.32 */
+ "schematronv", /* XML_FROM_SCHEMATRONV */
+#endif
+ NULL
+};
+
+
+static void
+raptor_libxml_xmlStructuredError_handler_common(raptor_world *world,
+ raptor_locator *locator,
+ xmlErrorPtr err)
+{
+ raptor_stringbuffer* sb;
+ char *nmsg;
+ raptor_log_level level = RAPTOR_LOG_LEVEL_ERROR;
+
+ if(err == NULL || err->code == XML_ERR_OK || err->level == XML_ERR_NONE)
+ return;
+
+ /* Do not warn about things with no location */
+ if(err->level == XML_ERR_WARNING && !err->file)
+ return;
+
+ /* XML fatal errors never cause an abort */
+ if(err->level == XML_ERR_FATAL)
+ err->level = XML_ERR_ERROR;
+
+
+ sb = raptor_new_stringbuffer();
+ if(err->domain != XML_FROM_HTML)
+ raptor_stringbuffer_append_counted_string(sb, (const unsigned char*)"XML ",
+ 4, 1);
+
+ if(err->domain != XML_FROM_NONE && err->domain < XML_LAST_DL) {
+ const unsigned char* label;
+ label = (const unsigned char*)raptor_libxml_domain_labels[(int)err->domain];
+ raptor_stringbuffer_append_string(sb, label, 1);
+ raptor_stringbuffer_append_counted_string(sb,
+ (const unsigned char*)" ", 1, 1);
+ }
+
+ if(err->level == XML_ERR_WARNING)
+ raptor_stringbuffer_append_counted_string(sb,
+ (const unsigned char*)"warning: ",
+ 9, 1);
+ else /* XML_ERR_ERROR or XML_ERR_FATAL */
+ raptor_stringbuffer_append_counted_string(sb, (const unsigned char*)"error: ",
+ 7, 1);
+
+ if(err->message) {
+ unsigned char* msg;
+ size_t len;
+ msg = (unsigned char*)err->message;
+ len= strlen((const char*)msg);
+ if(len && msg[len-1] == '\n')
+ msg[--len]='\0';
+
+ raptor_stringbuffer_append_counted_string(sb, msg, len, 1);
+ }
+
+#if LIBXML_VERSION >= 20618
+ /* 2005-02-13 - v2.6.18 */
+
+ /* str1 has the detailed HTTP error */
+ if(err->domain == XML_FROM_HTTP && err->str1) {
+ unsigned char* msg;
+ size_t len;
+ msg = (unsigned char*)err->str1;
+ len= strlen((const char*)msg);
+ if(len && msg[len-1] == '\n')
+ msg[--len]='\0';
+
+ raptor_stringbuffer_append_counted_string(sb, (const unsigned char*)" - ",
+ 3, 1);
+ raptor_stringbuffer_append_counted_string(sb, msg, len, 1);
+ }
+#endif
+
+ /* When err->domain == XML_FROM_XPATH then err->int1 is
+ * the offset into err->str1, the line with the error
+ */
+ if(err->domain == XML_FROM_XPATH && err->str1) {
+ raptor_stringbuffer_append_counted_string(sb, (const unsigned char*)" in ",
+ 4, 1);
+ raptor_stringbuffer_append_string(sb, (const unsigned char*)err->str1, 1);
+ }
+
+ nmsg = (char*)raptor_stringbuffer_as_string(sb);
+ if(err->level == XML_ERR_FATAL)
+ level = RAPTOR_LOG_LEVEL_FATAL;
+ else if(err->level == XML_ERR_ERROR)
+ level = RAPTOR_LOG_LEVEL_ERROR;
+ else
+ level = RAPTOR_LOG_LEVEL_WARN;
+
+ raptor_log_error(world, level, locator, nmsg);
+
+ raptor_free_stringbuffer(sb);
+}
+
+
+/* user_data is a raptor_world* */
+static void
+raptor_libxml_xmlStructuredError_handler_global(void *user_data,
+ xmlErrorPtr err)
+{
+ raptor_world *world = NULL;
+
+ /* user_data may point to a raptor_world* */
+ if(user_data) {
+ world = (raptor_world*)user_data;
+ if(world->magic != RAPTOR2_WORLD_MAGIC)
+ world = NULL;
+ }
+
+ raptor_libxml_xmlStructuredError_handler_common(world, NULL, err);
+}
+
+
+/* user_data may be a raptor_sax2; err->ctxt->userData may point to a
+ * raptor_sax2* */
+static void
+raptor_libxml_xmlStructuredError_handler_parsing(void *user_data,
+ xmlErrorPtr err)
+{
+ raptor_sax2* sax2 = NULL;
+
+ /* user_data may point to a raptor_sax2* */
+ if(user_data) {
+ sax2 = (raptor_sax2*)user_data;
+ if(sax2->magic != RAPTOR_LIBXML_MAGIC)
+ sax2 = NULL;
+ }
+
+ /* err->ctxt->userData may point to a raptor_sax2* */
+ if(err && err->ctxt) {
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr)err->ctxt;
+ if(ctxt->userData) {
+ sax2 = (raptor_sax2*)ctxt->userData;
+ if(sax2->magic != RAPTOR_LIBXML_MAGIC)
+ sax2 = NULL;
+ }
+ }
+
+ if(sax2)
+ raptor_libxml_xmlStructuredError_handler_common(sax2->world, sax2->locator,
+ err);
+ else
+ raptor_libxml_xmlStructuredError_handler_common(NULL, NULL, err);
+}
+
+
+/* end if RAPTOR_XML_LIBXML */
+#endif