added support and APIs needed for the catalog PI cleanup Daniel
* include/libxml/catalog.h include/libxml/parser.h
include/libxml/xmlerror.h catalog.c parser.c parserInternals.c
xmlIO.c: added support and APIs needed for the catalog PI
* include/libxml/xmlIO.h: cleanup
Daniel
diff --git a/ChangeLog b/ChangeLog
index 01b5081..cbc24aa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Wed Aug 22 16:27:03 CEST 2001 Daniel Veillard <daniel@veillard.com>
+
+ * include/libxml/catalog.h include/libxml/parser.h
+ include/libxml/xmlerror.h catalog.c parser.c parserInternals.c
+ xmlIO.c: added support and APIs needed for the catalog PI
+ * include/libxml/xmlIO.h: cleanup
+
Wed Aug 22 02:03:31 CEST 2001 Daniel Veillard <daniel@veillard.com>
* catalog.c parser.c xmlIO.c xmlcatalog.c xmllint.c
diff --git a/catalog.c b/catalog.c
index 2ea69db..06b2b53 100644
--- a/catalog.c
+++ b/catalog.c
@@ -93,10 +93,11 @@
xmlCatalogPrefer prefer;
};
+static xmlCatalogAllow xmlCatalogDefaultAllow = XML_CATA_ALLOW_ALL;
+static xmlCatalogPrefer xmlCatalogDefaultPrefer = XML_CATA_PREFER_SYSTEM;
static xmlHashTablePtr xmlDefaultCatalog;
static xmlCatalogEntryPtr xmlDefaultXMLCatalogList = NULL;
static int xmlCatalogInitialized = 0;
-static xmlCatalogPrefer xmlCatalogDefaultPrefer = XML_CATA_PREFER_SYSTEM;
/* Catalog stack */
@@ -1562,7 +1563,17 @@
*/
static const xmlChar *
xmlCatalogSGMLResolve(const xmlChar *pubID, const xmlChar *sysID) {
- TODO
+ const xmlChar *ret = NULL;
+
+ if (xmlDefaultCatalog == NULL)
+ return(NULL);
+
+ if (pubID != NULL)
+ ret = xmlCatalogGetSGMLPublic(xmlDefaultCatalog, pubID);
+ if (ret != NULL)
+ return(ret);
+ if (sysID != NULL)
+ ret = xmlCatalogGetSGMLSystem(xmlDefaultCatalog, sysID);
return(NULL);
}
@@ -2011,11 +2022,58 @@
}
/**
+ * xmlCatalogGetDefaults:
+ *
+ * Used to get the user preference w.r.t. to what catalogs should
+ * be accepted
+ *
+ * Returns the current xmlCatalogAllow value
+ */
+xmlCatalogAllow
+xmlCatalogGetDefaults(void) {
+ return(xmlCatalogDefaultAllow);
+}
+
+/**
+ * xmlCatalogSetDefaults:
+ *
+ * Used to set the user preference w.r.t. to what catalogs should
+ * be accepted
+ */
+void
+xmlCatalogSetDefaults(xmlCatalogAllow allow) {
+ if (!xmlCatalogInitialized)
+ xmlInitializeCatalog();
+ if (xmlDebugCatalogs) {
+ switch (allow) {
+ case XML_CATA_ALLOW_NONE:
+ xmlGenericError(xmlGenericErrorContext,
+ "Disabling catalog usage\n");
+ break;
+ case XML_CATA_ALLOW_GLOBAL:
+ xmlGenericError(xmlGenericErrorContext,
+ "Allowing only global catalogs\n");
+ break;
+ case XML_CATA_ALLOW_DOCUMENT:
+ xmlGenericError(xmlGenericErrorContext,
+ "Allowing only catalogs from the document\n");
+ break;
+ case XML_CATA_ALLOW_ALL:
+ xmlGenericError(xmlGenericErrorContext,
+ "Allowing all catalogs\n");
+ break;
+ }
+ }
+ xmlCatalogDefaultAllow = allow;
+}
+
+/**
* xmlCatalogSetDefaultPrefer:
* @prefer: the default preference for delegation
*
* Allows to set the preference between public and system for deletion
* in XML Catalog resolution. C.f. section 4.1.1 of the spec
+ * Values accepted are XML_CATA_PREFER_PUBLIC or XML_CATA_PREFER_SYSTEM
*
* Returns the previous value of the default preference for delegation
*/
@@ -2023,6 +2081,25 @@
xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer) {
xmlCatalogPrefer ret = xmlCatalogDefaultPrefer;
+ if (!xmlCatalogInitialized)
+ xmlInitializeCatalog();
+ if (prefer == XML_CATA_PREFER_NONE)
+ return(ret);
+
+ if (xmlDebugCatalogs) {
+ switch (prefer) {
+ case XML_CATA_PREFER_PUBLIC:
+ xmlGenericError(xmlGenericErrorContext,
+ "Setting catalog preference to PUBLIC\n");
+ break;
+ case XML_CATA_PREFER_SYSTEM:
+ xmlGenericError(xmlGenericErrorContext,
+ "Setting catalog preference to SYSTEM\n");
+ break;
+ case XML_CATA_PREFER_NONE:
+ break;
+ }
+ }
xmlCatalogDefaultPrefer = prefer;
return(ret);
}
@@ -2046,4 +2123,83 @@
xmlDebugCatalogs = level;
return(ret);
}
+
+/**
+ * xmlCatalogFreeLocal:
+ * @catalogs: a document's list of catalogs
+ *
+ * Free up the memory associated to the catalog list
+ */
+void
+xmlCatalogFreeLocal(void *catalogs) {
+ xmlCatalogEntryPtr catal;
+
+ catal = (xmlCatalogEntryPtr) catalogs;
+ if (catal != NULL)
+ xmlFreeCatalogEntryList(catal);
+}
+
+
+/**
+ * xmlCatalogAddLocal:
+ * @catalogs: a document's list of catalogs
+ * @URL: the URL to a new local catalog
+ *
+ * Add the new entry to the catalog list
+ *
+ * Returns the updated list
+ */
+void *
+xmlCatalogAddLocal(void *catalogs, const xmlChar *URL) {
+ xmlCatalogEntryPtr catal, add;
+
+ if (!xmlCatalogInitialized)
+ xmlInitializeCatalog();
+ if (URL == NULL)
+ return(catalogs);
+
+ if (xmlDebugCatalogs)
+ xmlGenericError(xmlGenericErrorContext,
+ "Adding document catalog %s\n", URL);
+
+ add = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, URL,
+ xmlCatalogDefaultPrefer);
+ if (add == NULL)
+ return(catalogs);
+
+ catal = (xmlCatalogEntryPtr) catalogs;
+ if (catal == NULL)
+ return((void *) add);
+
+ while (catal->next != NULL)
+ catal = catal->next;
+ catal->next = add;
+ return(catalogs);
+}
+
+/**
+ * xmlCatalogLocalResolve:
+ * @catalogs: a document's list of catalogs
+ * @pubId: the public ID string
+ * @sysId: the system ID string
+ *
+ * Do a complete resolution lookup of an External Identifier using a
+ * document's private catalog list
+ *
+ * Returns the URI of the resource or NULL if not found, it must be freed
+ * by the caller.
+ */
+xmlChar *
+xmlCatalogLocalResolve(void *catalogs, const xmlChar *pubID,
+ const xmlChar *sysID) {
+ xmlCatalogEntryPtr catal;
+
+ if (!xmlCatalogInitialized)
+ xmlInitializeCatalog();
+ catal = (xmlCatalogEntryPtr) catalogs;
+ if (catal == NULL)
+ return(NULL);
+ return(xmlCatalogListXMLResolve(catal, pubID, sysID));
+}
+
#endif /* LIBXML_CATALOG_ENABLED */
diff --git a/include/libxml/catalog.h b/include/libxml/catalog.h
index 7693996..d39fb60 100644
--- a/include/libxml/catalog.h
+++ b/include/libxml/catalog.h
@@ -33,8 +33,10 @@
*
* The namespace for the XML Catalogs elements
*/
-#define XML_CATALOGS_NAMESPACE \
+#define XML_CATALOGS_NAMESPACE \
(const xmlChar *) "urn:oasis:names:tc:entity:xmlns:xml:catalog"
+#define XML_CATALOG_PI \
+ (const xmlChar *) "oasis-xml-catalog"
/*
* The API is voluntarily limited to general cataloging
@@ -45,6 +47,13 @@
XML_CATA_PREFER_SYSTEM
} xmlCatalogPrefer;
+typedef enum {
+ XML_CATA_ALLOW_NONE = 0,
+ XML_CATA_ALLOW_GLOBAL = 1,
+ XML_CATA_ALLOW_DOCUMENT = 2,
+ XML_CATA_ALLOW_ALL = 3
+} xmlCatalogAllow;
+
void xmlInitializeCatalog (void);
int xmlLoadCatalog (const char *filename);
void xmlLoadCatalogs (const char *paths);
@@ -58,8 +67,24 @@
const xmlChar *orig,
const xmlChar *replace);
int xmlCatalogRemove (const xmlChar *value);
+
+/*
+ * Strictly minimal interfaces for per-document catalogs used
+ * by the parser.
+ */
+void xmlCatalogFreeLocal (void *catalogs);
+void * xmlCatalogAddLocal (void *catalogs,
+ const xmlChar *URL);
+xmlChar * xmlCatalogLocalResolve (void *catalogs,
+ const xmlChar *pubID,
+ const xmlChar *sysID);
+/*
+ * Preference settings
+ */
int xmlCatalogSetDebug (int level);
xmlCatalogPrefer xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer);
+void xmlCatalogSetDefaults (xmlCatalogAllow allow);
+xmlCatalogAllow xmlCatalogGetDefaults (void);
/* DEPRECATED interfaces */
const xmlChar * xmlCatalogGetSystem (const xmlChar *sysID);
diff --git a/include/libxml/parser.h b/include/libxml/parser.h
index de0bebb..1cf7f52 100644
--- a/include/libxml/parser.h
+++ b/include/libxml/parser.h
@@ -217,6 +217,7 @@
int loadsubset; /* should the external subset be loaded */
int linenumbers; /* set line number in element content */
+ void *catalogs; /* document's own catalog */
};
/**
diff --git a/include/libxml/xmlIO.h b/include/libxml/xmlIO.h
index 9f248d1..0bdf6a5 100644
--- a/include/libxml/xmlIO.h
+++ b/include/libxml/xmlIO.h
@@ -165,7 +165,7 @@
#ifdef LIBXML_HTTP_ENABLED
void * xmlIOHTTPOpenW (const char * post_uri,
int compression );
-void xmlRegisterHTTPPostCallbacksI (void );
+void xmlRegisterHTTPPostCallbacks (void );
#endif
/*
diff --git a/include/libxml/xmlerror.h b/include/libxml/xmlerror.h
index 53c5751..88daeff 100644
--- a/include/libxml/xmlerror.h
+++ b/include/libxml/xmlerror.h
@@ -132,7 +132,8 @@
XML_ERR_ENTITY_LOOP, /* 89 */
XML_ERR_ENTITY_BOUNDARY, /* 90 */
XML_ERR_INVALID_URI, /* 91 */
- XML_ERR_URI_FRAGMENT /* 92 */
+ XML_ERR_URI_FRAGMENT, /* 92 */
+ XML_WAR_CATALOG_PI /* 93 */
}xmlParserErrors;
/*
diff --git a/parser.c b/parser.c
index ee68b62..ca96696 100644
--- a/parser.c
+++ b/parser.c
@@ -50,6 +50,9 @@
#include <libxml/encoding.h>
#include <libxml/xmlIO.h>
#include <libxml/uri.h>
+#ifdef LIBXML_CATALOG_ENABLED
+#include <libxml/catalog.h>
+#endif
#ifdef HAVE_CTYPE_H
#include <ctype.h>
@@ -2941,6 +2944,69 @@
return(name);
}
+#ifdef LIBXML_CATALOG_ENABLED
+/**
+ * xmlParseCatalogPI:
+ * @ctxt: an XML parser context
+ * @catalog: the PI value string
+ *
+ * parse an XML Catalog Processing Instruction.
+ *
+ * <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
+ *
+ * Occurs only if allowed by the user and if happening in the Misc
+ * part of the document before any doctype informations
+ * This will add the given catalog to the parsing context in order
+ * to be used if there is a resolution need further down in the document
+ */
+
+static void
+xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
+ xmlChar *URL = NULL;
+ const xmlChar *tmp, *base;
+ xmlChar marker;
+
+ tmp = catalog;
+ while (IS_BLANK(*tmp)) tmp++;
+ if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
+ goto error;
+ tmp += 7;
+ while (IS_BLANK(*tmp)) tmp++;
+ if (*tmp != '=') {
+ return;
+ }
+ tmp++;
+ while (IS_BLANK(*tmp)) tmp++;
+ marker = *tmp;
+ if ((marker != '\'') && (marker != '"'))
+ goto error;
+ tmp++;
+ base = tmp;
+ while ((*tmp != 0) && (*tmp != marker)) tmp++;
+ if (*tmp == 0)
+ goto error;
+ URL = xmlStrndup(base, tmp - base);
+ tmp++;
+ while (IS_BLANK(*tmp)) tmp++;
+ if (*tmp != 0)
+ goto error;
+
+ if (URL != NULL) {
+ ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
+ xmlFree(URL);
+ }
+ return;
+
+error:
+ ctxt->errNo = XML_WAR_CATALOG_PI;
+ if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+ ctxt->sax->warning(ctxt->userData,
+ "Catalog PI syntax error: %s\n", catalog);
+ if (URL != NULL)
+ xmlFree(URL);
+}
+#endif
+
/**
* xmlParsePI:
* @ctxt: an XML parser context
@@ -3063,6 +3129,18 @@
}
SKIP(2);
+#ifdef LIBXML_CATALOG_ENABLED
+ if (((state == XML_PARSER_MISC) ||
+ (state == XML_PARSER_START)) &&
+ (xmlStrEqual(target, XML_CATALOG_PI))) {
+ xmlCatalogAllow allow = xmlCatalogGetDefaults();
+ if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
+ (allow == XML_CATA_ALLOW_ALL))
+ xmlParseCatalogPI(ctxt, buf);
+ }
+#endif
+
+
/*
* SAX: PI detected.
*/
@@ -5324,7 +5402,7 @@
ctxt->disableSAX = 1;
} else {
ctxt->errNo = XML_WAR_UNDECLARED_ENTITY;
- if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+ if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Entity '%s' not defined\n", name);
}
diff --git a/parserInternals.c b/parserInternals.c
index e31e6f2..8e652b3 100644
--- a/parserInternals.c
+++ b/parserInternals.c
@@ -46,6 +46,9 @@
#include <libxml/valid.h>
#include <libxml/xmlIO.h>
#include <libxml/uri.h>
+#ifdef LIBXML_CATALOG_ENABLED
+#include <libxml/catalog.h>
+#endif
void xmlUpgradeOldNs(xmlDocPtr doc);
@@ -2270,6 +2273,7 @@
ctxt->errNo = XML_ERR_OK;
ctxt->depth = 0;
ctxt->charset = XML_CHAR_ENCODING_UTF8;
+ ctxt->catalogs = NULL;
xmlInitNodeInfoSeq(&ctxt->node_seq);
}
@@ -2308,6 +2312,10 @@
xmlFree(ctxt->sax);
if (ctxt->directory != NULL) xmlFree((char *) ctxt->directory);
if (ctxt->vctxt.nodeTab != NULL) xmlFree(ctxt->vctxt.nodeTab);
+#ifdef LIBXML_CATALOG_ENABLED
+ if (ctxt->catalogs != NULL)
+ xmlCatalogFreeLocal(ctxt->catalogs);
+#endif
xmlFree(ctxt);
}
diff --git a/xmlIO.c b/xmlIO.c
index 1cfefce..bff4479 100644
--- a/xmlIO.c
+++ b/xmlIO.c
@@ -2374,6 +2374,7 @@
xmlChar *resource = NULL;
#ifdef LIBXML_CATALOG_ENABLED
struct stat info;
+ xmlCatalogAllow pref;
#endif
#ifdef DEBUG_EXTERNAL_ENTITIES
@@ -2385,11 +2386,40 @@
* If the resource doesn't exists as a file,
* try to load it from the resource pointed in the catalog
*/
+ pref = xmlCatalogGetDefaults();
+
+ if ((pref != XML_CATA_ALLOW_NONE)
#ifdef HAVE_STAT
- if ((URL == NULL) || (stat(URL, &info) < 0))
+ && ((URL == NULL) || (stat(URL, &info) < 0))
#endif
- resource = xmlCatalogResolve((const xmlChar *)ID,
- (const xmlChar *)URL);
+ ) {
+ /*
+ * Do a local lookup
+ */
+ if ((ctxt->catalogs != NULL) &&
+ ((pref == XML_CATA_ALLOW_ALL) ||
+ (pref == XML_CATA_ALLOW_DOCUMENT))) {
+ resource = xmlCatalogLocalResolve(ctxt->catalogs,
+ (const xmlChar *)ID,
+ (const xmlChar *)URL);
+ }
+ /*
+ * Do a global lookup
+ */
+ if (((resource == NULL)
+#ifdef HAVE_STAT
+ || (stat((const char *) resource, &info) < 0)
+#endif
+ ) && ((pref == XML_CATA_ALLOW_ALL) ||
+ (pref == XML_CATA_ALLOW_GLOBAL))) {
+
+ resource = xmlCatalogResolve((const xmlChar *)ID,
+ (const xmlChar *)URL);
+ }
+ /*
+ * TODO: do an URI lookup on the reference
+ */
+ }
#endif
if (resource == NULL)