summaryrefslogtreecommitdiff
path: root/catalog.c
diff options
context:
space:
mode:
authorDaniel Veillard <veillard@src.gnome.org>2001-10-11 18:59:45 +0000
committerDaniel Veillard <veillard@src.gnome.org>2001-10-11 18:59:45 +0000
commit75b96824bccaeadd9e71eba9be7fab1bd88ac814 (patch)
tree6a1ba4a7540b9666ccf4db98c9763a0c399ec21a /catalog.c
parent78d12097086486ac73292f3ca13bc1cf8505285c (diff)
downloadlibxml2-75b96824bccaeadd9e71eba9be7fab1bd88ac814.tar.gz
very serious cleanup, isolating unportable code and as much as possible
* catalog.c include/libxml/catalog.h: very serious cleanup, isolating unportable code and as much as possible the accesses to the global shared catalog. May need more testing ! Daniel
Diffstat (limited to 'catalog.c')
-rw-r--r--catalog.c1648
1 files changed, 1058 insertions, 590 deletions
diff --git a/catalog.c b/catalog.c
index 55c20a6e..1b7bd8da 100644
--- a/catalog.c
+++ b/catalog.c
@@ -52,9 +52,14 @@
#define XML_URN_PUBID "urn:publicid:"
#define XML_CATAL_BREAK ((xmlChar *) -1)
-#ifndef XML_DEFAULT_CATALOG
-#define XML_DEFAULT_CATALOG "/etc/xml/catalog"
+#ifndef XML_XML_DEFAULT_CATALOG
+#define XML_XML_DEFAULT_CATALOG "/etc/xml/catalog"
#endif
+#ifndef XML_SGML_DEFAULT_CATALOG
+#define XML_SGML_DEFAULT_CATALOG "/etc/sgml/catalog"
+#endif
+
+int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename);
/************************************************************************
* *
@@ -102,27 +107,78 @@ struct _xmlCatalogEntry {
int dealloc;
};
+typedef enum {
+ XML_XML_CATALOG_TYPE = 1,
+ XML_SGML_CATALOG_TYPE
+} xmlCatalogType;
+
+#define XML_MAX_SGML_CATA_DEPTH 10
+struct _xmlCatalog {
+ xmlCatalogType type; /* either XML or SGML */
+
+ /*
+ * SGML Catalogs are stored as a simple hash table of catalog entries
+ * Catalog stack to check against overflows when building the
+ * SGML catalog
+ */
+ char *catalTab[XML_MAX_SGML_CATA_DEPTH]; /* stack of catals */
+ int catalNr; /* Number of current catal streams */
+ int catalMax; /* Max number of catal streams */
+ xmlHashTablePtr sgml;
+
+ /*
+ * XML Catalogs are stored as a tree of Catalog entries
+ */
+ xmlCatalogPrefer prefer;
+ xmlCatalogEntryPtr xml;
+};
+
+/************************************************************************
+ * *
+ * Global variables *
+ * *
+ ************************************************************************/
+
static xmlCatalogAllow xmlCatalogDefaultAllow = XML_CATA_ALLOW_ALL;
static xmlCatalogPrefer xmlCatalogDefaultPrefer = XML_CATA_PREFER_PUBLIC;
-static xmlHashTablePtr xmlDefaultCatalog;
+
+/*
+ * Hash table containing all the trees of XML catalogs parsed by
+ * the application.
+ */
static xmlHashTablePtr xmlCatalogXMLFiles = NULL;
-static xmlCatalogEntryPtr xmlDefaultXMLCatalogList = NULL;
-static int xmlCatalogInitialized = 0;
+/*
+ * The default catalog in use by the application
+ */
+static xmlCatalogPtr xmlDefaultCatalog = NULL;
+
+/*
+ * Whether the catalog support was initialized.
+ */
+static int xmlCatalogInitialized = 0;
-/* Catalog stack */
-static const char * catalTab[10]; /* stack of catals */
-static int catalNr = 0; /* Number of current catal streams */
-static int catalMax = 10; /* Max number of catal streams */
static int xmlDebugCatalogs = 0; /* used for debugging */
/************************************************************************
* *
- * alloc or dealloc *
+ * Allocation and Freeing *
* *
************************************************************************/
+/**
+ * xmlNewCatalogEntry:
+ * @type: type of entry
+ * @name: name of the entry
+ * @value: value of the entry
+ * @prefer: the PUBLIC vs. SYSTEM current preference value
+ *
+ * create a new Catalog entry, this type is shared both by XML and
+ * SGML catalogs, but the acceptable types values differs.
+ *
+ * Returns the xmlCatalogEntryPtr or NULL in case of error
+ */
static xmlCatalogEntryPtr
xmlNewCatalogEntry(xmlCatalogEntryType type, const xmlChar *name,
const xmlChar *value, xmlCatalogPrefer prefer) {
@@ -154,6 +210,12 @@ xmlNewCatalogEntry(xmlCatalogEntryType type, const xmlChar *name,
static void
xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret);
+/**
+ * xmlFreeCatalogEntry:
+ * @ret: a Catalog entry
+ *
+ * Free the memory allocated to a Catalog entry
+ */
static void
xmlFreeCatalogEntry(xmlCatalogEntryPtr ret) {
if (ret == NULL)
@@ -167,6 +229,12 @@ xmlFreeCatalogEntry(xmlCatalogEntryPtr ret) {
xmlFree(ret);
}
+/**
+ * xmlFreeCatalogEntryList:
+ * @ret: a Catalog entry list
+ *
+ * Free the memory allocated to a full chained list of Catalog entries
+ */
static void
xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret) {
xmlCatalogEntryPtr next;
@@ -179,11 +247,63 @@ xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret) {
}
/**
+ * xmlNewCatalog:
+ * @type: type of catalog
+ * @prefer: the PUBLIC vs. SYSTEM current preference value
+ *
+ * create a new Catalog, this type is shared both by XML and
+ * SGML catalogs, but the acceptable types values differs.
+ *
+ * Returns the xmlCatalogPtr or NULL in case of error
+ */
+static xmlCatalogPtr
+xmlNewCatalog(xmlCatalogType type, xmlCatalogPrefer prefer) {
+ xmlCatalogPtr ret;
+
+ ret = (xmlCatalogPtr) xmlMalloc(sizeof(xmlCatalog));
+ if (ret == NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "malloc of %d byte failed\n", sizeof(xmlCatalog));
+ return(NULL);
+ }
+ memset(ret, 0, sizeof(xmlCatalog));
+ ret->type = type;
+ ret->catalNr = 0;
+ ret->catalMax = XML_MAX_SGML_CATA_DEPTH;
+ ret->prefer = prefer;
+ return(ret);
+}
+
+/**
+ * xmlFreeCatalog:
+ * @catal: a Catalog entry
+ *
+ * Free the memory allocated to a Catalog
+ */
+void
+xmlFreeCatalog(xmlCatalogPtr catal) {
+ if (catal == NULL)
+ return;
+ if (catal->xml != NULL)
+ xmlFreeCatalogEntryList(catal->xml);
+ if (catal->sgml != NULL)
+ xmlHashFree(catal->sgml,
+ (xmlHashDeallocator) xmlFreeCatalogEntry);
+ xmlFree(catal);
+}
+
+/************************************************************************
+ * *
+ * Serializing Catalogs *
+ * *
+ ************************************************************************/
+
+/**
* xmlCatalogDumpEntry:
* @entry: the
* @out: the file.
*
- * Free up all the memory associated with catalogs
+ * Serialize an SGML Catalog entry
*/
static void
xmlCatalogDumpEntry(xmlCatalogEntryPtr entry, FILE *out) {
@@ -251,16 +371,162 @@ xmlCatalogDumpEntry(xmlCatalogEntryPtr entry, FILE *out) {
fprintf(out, "\n");
}
+static int
+xmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) {
+ int ret;
+ xmlDocPtr doc;
+ xmlNsPtr ns;
+ xmlDtdPtr dtd;
+ xmlNodePtr node, catalog;
+ xmlOutputBufferPtr buf;
+ xmlCatalogEntryPtr cur;
+
+ /*
+ * Rebuild a catalog
+ */
+ doc = xmlNewDoc(NULL);
+ if (doc == NULL)
+ return(-1);
+ dtd = xmlNewDtd(doc, BAD_CAST "catalog",
+ BAD_CAST "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN",
+BAD_CAST "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd");
+
+ xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd);
+
+ ns = xmlNewNs(NULL, XML_CATALOGS_NAMESPACE, NULL);
+ if (ns == NULL) {
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ catalog = xmlNewDocNode(doc, ns, BAD_CAST "catalog", NULL);
+ if (catalog == NULL) {
+ xmlFreeNs(ns);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ catalog->nsDef = ns;
+ xmlAddChild((xmlNodePtr) doc, catalog);
+
+ /*
+ * add all the catalog entries
+ */
+ cur = catal;
+ while (cur != NULL) {
+ switch (cur->type) {
+ case XML_CATA_BROKEN_CATALOG:
+ case XML_CATA_CATALOG:
+ if (cur == catal) {
+ cur = cur->children;
+ continue;
+ }
+ break;
+ case XML_CATA_NEXT_CATALOG:
+ node = xmlNewDocNode(doc, ns, BAD_CAST "nextCatalog", NULL);
+ xmlSetProp(node, BAD_CAST "catalog", cur->value);
+ xmlAddChild(catalog, node);
+ break;
+ case XML_CATA_NONE:
+ break;
+ case XML_CATA_PUBLIC:
+ node = xmlNewDocNode(doc, ns, BAD_CAST "public", NULL);
+ xmlSetProp(node, BAD_CAST "publicId", cur->name);
+ xmlSetProp(node, BAD_CAST "uri", cur->value);
+ xmlAddChild(catalog, node);
+ break;
+ case XML_CATA_SYSTEM:
+ node = xmlNewDocNode(doc, ns, BAD_CAST "system", NULL);
+ xmlSetProp(node, BAD_CAST "systemId", cur->name);
+ xmlSetProp(node, BAD_CAST "uri", cur->value);
+ xmlAddChild(catalog, node);
+ break;
+ case XML_CATA_REWRITE_SYSTEM:
+ node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteSystem", NULL);
+ xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
+ xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
+ xmlAddChild(catalog, node);
+ break;
+ case XML_CATA_DELEGATE_PUBLIC:
+ node = xmlNewDocNode(doc, ns, BAD_CAST "delegatePublic", NULL);
+ xmlSetProp(node, BAD_CAST "publicIdStartString", cur->name);
+ xmlSetProp(node, BAD_CAST "catalog", cur->value);
+ xmlAddChild(catalog, node);
+ break;
+ case XML_CATA_DELEGATE_SYSTEM:
+ node = xmlNewDocNode(doc, ns, BAD_CAST "delegateSystem", NULL);
+ xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
+ xmlSetProp(node, BAD_CAST "catalog", cur->value);
+ xmlAddChild(catalog, node);
+ break;
+ case XML_CATA_URI:
+ node = xmlNewDocNode(doc, ns, BAD_CAST "uri", NULL);
+ xmlSetProp(node, BAD_CAST "name", cur->name);
+ xmlSetProp(node, BAD_CAST "uri", cur->value);
+ xmlAddChild(catalog, node);
+ break;
+ case XML_CATA_REWRITE_URI:
+ node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteURI", NULL);
+ xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
+ xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
+ xmlAddChild(catalog, node);
+ break;
+ case XML_CATA_DELEGATE_URI:
+ node = xmlNewDocNode(doc, ns, BAD_CAST "delegateURI", NULL);
+ xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
+ xmlSetProp(node, BAD_CAST "catalog", cur->value);
+ xmlAddChild(catalog, node);
+ break;
+ case SGML_CATA_SYSTEM:
+ case SGML_CATA_PUBLIC:
+ case SGML_CATA_ENTITY:
+ case SGML_CATA_PENTITY:
+ case SGML_CATA_DOCTYPE:
+ case SGML_CATA_LINKTYPE:
+ case SGML_CATA_NOTATION:
+ case SGML_CATA_DELEGATE:
+ case SGML_CATA_BASE:
+ case SGML_CATA_CATALOG:
+ case SGML_CATA_DOCUMENT:
+ case SGML_CATA_SGMLDECL:
+ break;
+ }
+ cur = cur->next;
+ }
+
+ /*
+ * reserialize it
+ */
+ buf = xmlOutputBufferCreateFile(out, NULL);
+ if (buf == NULL) {
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ ret = xmlSaveFormatFileTo(buf, doc, NULL, 1);
+
+ /*
+ * Free it
+ */
+ xmlFreeDoc(doc);
+
+ return(ret);
+}
+
+/************************************************************************
+ * *
+ * Converting SGML Catalogs to XML *
+ * *
+ ************************************************************************/
+
/**
* xmlCatalogConvertEntry:
* @entry: the entry
- * @res: pointer to te number converted
+ * @catal: pointer to the catalog being converted
*
- * Free up all the memory associated with catalogs
+ * Convert one entry from the catalog
*/
static void
-xmlCatalogConvertEntry(xmlCatalogEntryPtr entry, int *res) {
- if ((entry == NULL) || (xmlDefaultXMLCatalogList == NULL))
+xmlCatalogConvertEntry(xmlCatalogEntryPtr entry, xmlCatalogPtr catal) {
+ if ((entry == NULL) || (catal == NULL) || (catal->sgml == NULL) ||
+ (catal->xml == NULL))
return;
switch (entry->type) {
case SGML_CATA_ENTITY:
@@ -291,7 +557,7 @@ xmlCatalogConvertEntry(xmlCatalogEntryPtr entry, int *res) {
entry->type = XML_CATA_CATALOG;
break;
default:
- xmlHashRemoveEntry(xmlDefaultCatalog, entry->name,
+ xmlHashRemoveEntry(catal->sgml, entry->name,
(xmlHashDeallocator) xmlFreeCatalogEntry);
return;
}
@@ -299,21 +565,43 @@ xmlCatalogConvertEntry(xmlCatalogEntryPtr entry, int *res) {
* Conversion successful, remove from the SGML catalog
* and add it to the default XML one
*/
- xmlHashRemoveEntry(xmlDefaultCatalog, entry->name, NULL);
- entry->parent = xmlDefaultXMLCatalogList;
+ xmlHashRemoveEntry(catal->sgml, entry->name, NULL);
+ entry->parent = catal->xml;
entry->next = NULL;
- if (xmlDefaultXMLCatalogList->children == NULL)
- xmlDefaultXMLCatalogList->children = entry;
+ if (catal->xml->children == NULL)
+ catal->xml->children = entry;
else {
xmlCatalogEntryPtr prev;
- prev = xmlDefaultXMLCatalogList->children;
+ prev = catal->xml->children;
while (prev->next != NULL)
prev = prev->next;
prev->next = entry;
}
- if (res != NULL)
- (*res)++;
+}
+
+/**
+ * xmlConvertSGMLCatalog:
+ * @catal: the catalog
+ *
+ * Convert all the SGML catalog entries as XML ones
+ *
+ * Returns the number of entries converted if successful, -1 otherwise
+ */
+int
+xmlConvertSGMLCatalog(xmlCatalogPtr catal) {
+
+ if ((catal == NULL) || (catal->type != XML_SGML_CATALOG_TYPE))
+ return(-1);
+
+ if (xmlDebugCatalogs) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Converting SGML catalog to XML\n");
+ }
+ xmlHashScan(catal->sgml,
+ (xmlHashScanner) xmlCatalogConvertEntry,
+ &catal);
+ return(0);
}
/************************************************************************
@@ -456,6 +744,78 @@ xmlParseCatalogFile(const char *filename) {
return(ret);
}
+/**
+ * xmlLoadFileContent:
+ * @filename: a file path
+ *
+ * Load a file content into memory.
+ *
+ * Returns a pointer to the 0 terminated string or NULL in case of error
+ */
+static xmlChar *
+xmlLoadFileContent(const char *filename)
+{
+#ifdef HAVE_STAT
+ int fd;
+#else
+ FILE *fd;
+#endif
+ int len;
+ long size;
+
+#ifdef HAVE_STAT
+ struct stat info;
+#endif
+ xmlChar *content;
+
+ if (filename == NULL)
+ return (NULL);
+
+#ifdef HAVE_STAT
+ if (stat(filename, &info) < 0)
+ return (NULL);
+#endif
+
+#ifdef HAVE_STAT
+ if ((fd = open(filename, O_RDONLY)) < 0) {
+#else
+ if ((fd = fopen(filename, "rb")) == NULL) {
+#endif
+ return (NULL);
+ }
+#ifdef HAVE_STAT
+ size = info.st_size;
+#else
+ if (fseek(fd, 0, SEEK_END) || (size = ftell(fd)) == EOF || fseek(fd, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */
+ fclose(fd);
+ return (NULL);
+ }
+#endif
+ content = xmlMalloc(size + 10);
+ if (content == NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "malloc of %d byte failed\n", size + 10);
+ return (NULL);
+ }
+#ifdef HAVE_STAT
+ len = read(fd, content, size);
+#else
+ len = fread(content, 1, size, fd);
+#endif
+ if (len < 0) {
+ xmlFree(content);
+ return (NULL);
+ }
+#ifdef HAVE_STAT
+ close(fd);
+#else
+ fclose(fd);
+#endif
+ content[len] = 0;
+
+ return(content);
+}
+
/************************************************************************
* *
* The XML Catalog parser *
@@ -477,6 +837,14 @@ static xmlChar *
xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI);
+/**
+ * xmlGetXMLCatalogEntryType:
+ * @name: the name
+ *
+ * lookup the internal type associated to an XML catalog entry name
+ *
+ * Returns the type associate with that name
+ */
static xmlCatalogEntryType
xmlGetXMLCatalogEntryType(const xmlChar *name) {
xmlCatalogEntryType type = XML_CATA_NONE;
@@ -503,6 +871,20 @@ xmlGetXMLCatalogEntryType(const xmlChar *name) {
return(type);
}
+/**
+ * xmlParseXMLCatalogOneNode:
+ * @cur: the XML node
+ * @type: the type of Catalog entry
+ * @name: the name of the node
+ * @attrName: the attribute holding the value
+ * @uriAttrName: the attribute holding the URI-Reference
+ * @prefer: the PUBLIC vs. SYSTEM current preference value
+ *
+ * Finishes the examination of an XML tree node of a catalog and build
+ * a Catalog entry from it.
+ *
+ * Returns the new Catalog entry node or NULL in case of error.
+ */
static xmlCatalogEntryPtr
xmlParseXMLCatalogOneNode(xmlNodePtr cur, xmlCatalogEntryType type,
const xmlChar *name, const xmlChar *attrName,
@@ -563,6 +945,16 @@ xmlParseXMLCatalogOneNode(xmlNodePtr cur, xmlCatalogEntryType type,
return(ret);
}
+/**
+ * xmlParseXMLCatalogNode:
+ * @cur: the XML node
+ * @prefer: the PUBLIC vs. SYSTEM current preference value
+ * @parent: the parent Catalog entry
+ *
+ * Examines an XML tree node of a catalog and build
+ * a Catalog entry from it adding it to its parent. The examination can
+ * be recursive.
+ */
static void
xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer,
xmlCatalogEntryPtr parent)
@@ -650,6 +1042,16 @@ xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer,
xmlFree(URL);
}
+/**
+ * xmlParseXMLCatalogNodeList:
+ * @cur: the XML node list of siblings
+ * @prefer: the PUBLIC vs. SYSTEM current preference value
+ * @parent: the parent Catalog entry
+ *
+ * Examines a list of XML sibling nodes of a catalog and build
+ * a list of Catalog entry from it adding it to the parent.
+ * The examination will recurse to examine node subtrees.
+ */
static void
xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
xmlCatalogEntryPtr parent) {
@@ -663,6 +1065,17 @@ xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
/* TODO: sort the list according to REWRITE lengths and prefer value */
}
+/**
+ * xmlParseXMLCatalog:
+ * @value: the content in-memory of the catalog serialization
+ * @prefer: the PUBLIC vs. SYSTEM current preference value
+ * @file: the filename for the catalog
+ *
+ * Parses the catalog content to extract the XML tree and then analyze the
+ * tree to build a list of Catalog entries corresponding to this catalog
+ *
+ * Returns the resulting Catalog entries list
+ */
static xmlCatalogEntryPtr
xmlParseXMLCatalog(const xmlChar *value, xmlCatalogPrefer prefer,
const char *file) {
@@ -720,6 +1133,16 @@ xmlParseXMLCatalog(const xmlChar *value, xmlCatalogPrefer prefer,
return(parent);
}
+/**
+ * xmlParseXMLCatalogFile:
+ * @prefer: the PUBLIC vs. SYSTEM current preference value
+ * @filename: the filename for the catalog
+ *
+ * Parses the catalog file to extract the XML tree and then analyze the
+ * tree to build a list of Catalog entries corresponding to this catalog
+ *
+ * Returns the resulting Catalog entries list
+ */
static xmlCatalogEntryPtr
xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename) {
xmlDocPtr doc;
@@ -810,7 +1233,9 @@ xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) {
}
/*
- * Fetch and parse
+ * Fetch and parse. Note that xmlParseXMLCatalogFile does not
+ * use the existing catalog, there is no recusivity allowed at
+ * that level.
*/
doc = xmlParseXMLCatalogFile(catal->prefer, catal->value);
if (doc == NULL) {
@@ -847,144 +1272,11 @@ xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) {
return(0);
}
-static int
-xmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) {
- int ret;
- xmlDocPtr doc;
- xmlNsPtr ns;
- xmlDtdPtr dtd;
- xmlNodePtr node, catalog;
- xmlOutputBufferPtr buf;
- xmlCatalogEntryPtr cur;
-
- /*
- * Rebuild a catalog
- */
- doc = xmlNewDoc(NULL);
- if (doc == NULL)
- return(-1);
- dtd = xmlNewDtd(doc, BAD_CAST "catalog",
- BAD_CAST "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN",
-BAD_CAST "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd");
-
- xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd);
-
- ns = xmlNewNs(NULL, XML_CATALOGS_NAMESPACE, NULL);
- if (ns == NULL) {
- xmlFreeDoc(doc);
- return(-1);
- }
- catalog = xmlNewDocNode(doc, ns, BAD_CAST "catalog", NULL);
- if (catalog == NULL) {
- xmlFreeNs(ns);
- xmlFreeDoc(doc);
- return(-1);
- }
- catalog->nsDef = ns;
- xmlAddChild((xmlNodePtr) doc, catalog);
-
- /*
- * add all the catalog entries
- */
- cur = catal;
- while (cur != NULL) {
- switch (cur->type) {
- case XML_CATA_BROKEN_CATALOG:
- case XML_CATA_CATALOG:
- if (cur == catal) {
- cur = cur->children;
- continue;
- }
- break;
- case XML_CATA_NEXT_CATALOG:
- node = xmlNewDocNode(doc, ns, BAD_CAST "nextCatalog", NULL);
- xmlSetProp(node, BAD_CAST "catalog", cur->value);
- xmlAddChild(catalog, node);
- break;
- case XML_CATA_NONE:
- break;
- case XML_CATA_PUBLIC:
- node = xmlNewDocNode(doc, ns, BAD_CAST "public", NULL);
- xmlSetProp(node, BAD_CAST "publicId", cur->name);
- xmlSetProp(node, BAD_CAST "uri", cur->value);
- xmlAddChild(catalog, node);
- break;
- case XML_CATA_SYSTEM:
- node = xmlNewDocNode(doc, ns, BAD_CAST "system", NULL);
- xmlSetProp(node, BAD_CAST "systemId", cur->name);
- xmlSetProp(node, BAD_CAST "uri", cur->value);
- xmlAddChild(catalog, node);
- break;
- case XML_CATA_REWRITE_SYSTEM:
- node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteSystem", NULL);
- xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
- xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
- xmlAddChild(catalog, node);
- break;
- case XML_CATA_DELEGATE_PUBLIC:
- node = xmlNewDocNode(doc, ns, BAD_CAST "delegatePublic", NULL);
- xmlSetProp(node, BAD_CAST "publicIdStartString", cur->name);
- xmlSetProp(node, BAD_CAST "catalog", cur->value);
- xmlAddChild(catalog, node);
- break;
- case XML_CATA_DELEGATE_SYSTEM:
- node = xmlNewDocNode(doc, ns, BAD_CAST "delegateSystem", NULL);
- xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
- xmlSetProp(node, BAD_CAST "catalog", cur->value);
- xmlAddChild(catalog, node);
- break;
- case XML_CATA_URI:
- node = xmlNewDocNode(doc, ns, BAD_CAST "uri", NULL);
- xmlSetProp(node, BAD_CAST "name", cur->name);
- xmlSetProp(node, BAD_CAST "uri", cur->value);
- xmlAddChild(catalog, node);
- break;
- case XML_CATA_REWRITE_URI:
- node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteURI", NULL);
- xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
- xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
- xmlAddChild(catalog, node);
- break;
- case XML_CATA_DELEGATE_URI:
- node = xmlNewDocNode(doc, ns, BAD_CAST "delegateURI", NULL);
- xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
- xmlSetProp(node, BAD_CAST "catalog", cur->value);
- xmlAddChild(catalog, node);
- break;
- case SGML_CATA_SYSTEM:
- case SGML_CATA_PUBLIC:
- case SGML_CATA_ENTITY:
- case SGML_CATA_PENTITY:
- case SGML_CATA_DOCTYPE:
- case SGML_CATA_LINKTYPE:
- case SGML_CATA_NOTATION:
- case SGML_CATA_DELEGATE:
- case SGML_CATA_BASE:
- case SGML_CATA_CATALOG:
- case SGML_CATA_DOCUMENT:
- case SGML_CATA_SGMLDECL:
- break;
- }
- cur = cur->next;
- }
-
- /*
- * reserialize it
- */
- buf = xmlOutputBufferCreateFile(out, NULL);
- if (buf == NULL) {
- xmlFreeDoc(doc);
- return(-1);
- }
- ret = xmlSaveFormatFileTo(buf, doc, NULL, 1);
-
- /*
- * Free it
- */
- xmlFreeDoc(doc);
-
- return(ret);
-}
+/************************************************************************
+ * *
+ * XML Catalog handling *
+ * *
+ ************************************************************************/
/**
* xmlAddXMLCatalog:
@@ -1586,6 +1878,14 @@ xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
#define SKIP_BLANKS while (IS_BLANK(*cur)) NEXT;
+/**
+ * xmlParseSGMLCatalogComment:
+ * @cur: the current character
+ *
+ * Skip a comment in an SGML catalog
+ *
+ * Returns new current character
+ */
static const xmlChar *
xmlParseSGMLCatalogComment(const xmlChar *cur) {
if ((cur[0] != '-') || (cur[1] != '-'))
@@ -1599,6 +1899,15 @@ xmlParseSGMLCatalogComment(const xmlChar *cur) {
return(cur + 2);
}
+/**
+ * xmlParseSGMLCatalogPubid:
+ * @cur: the current character
+ * @id: the return location
+ *
+ * Parse an SGML catalog ID
+ *
+ * Returns new current character and store the value in @id
+ */
static const xmlChar *
xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) {
xmlChar *buf = NULL;
@@ -1659,6 +1968,15 @@ xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) {
return(cur);
}
+/**
+ * xmlParseSGMLCatalogName:
+ * @cur: the current character
+ * @name: the return location
+ *
+ * Parse an SGML catalog name
+ *
+ * Returns new current character and store the value in @name
+ */
static const xmlChar *
xmlParseSGMLCatalogName(const xmlChar *cur, xmlChar **name) {
xmlChar buf[XML_MAX_NAMELEN + 5];
@@ -1688,6 +2006,14 @@ xmlParseSGMLCatalogName(const xmlChar *cur, xmlChar **name) {
return(cur);
}
+/**
+ * xmlGetSGMLCatalogEntryType:
+ * @name: the entry name
+ *
+ * Get the Catalog entry type for a given SGML Catalog name
+ *
+ * Returns Catalog entry type
+ */
static xmlCatalogEntryType
xmlGetSGMLCatalogEntryType(const xmlChar *name) {
xmlCatalogEntryType type = XML_CATA_NONE;
@@ -1718,8 +2044,22 @@ xmlGetSGMLCatalogEntryType(const xmlChar *name) {
return(type);
}
+/**
+ * xmlParseSGMLCatalog:
+ * @catal: the SGML Catalog
+ * @value: the content of the SGML Catalog serialization
+ * @file: the filepath for the catalog
+ * @super: should this be handled as a Super Catalog in which case
+ * parsing is not recursive
+ *
+ * Parse an SGML catalog content and fill up the @catal hash table with
+ * the new entries found.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
static int
-xmlParseSGMLCatalog(const xmlChar *value, const char *file, int super) {
+xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value,
+ const char *file, int super) {
const xmlChar *cur = value;
xmlChar *base = NULL;
int res;
@@ -1866,7 +2206,7 @@ xmlParseSGMLCatalog(const xmlChar *value, const char *file, int super) {
entry = xmlNewCatalogEntry(type, name, filename,
XML_CATA_PREFER_NONE);
- res = xmlHashAddEntry(xmlDefaultCatalog, name, entry);
+ res = xmlHashAddEntry(catal->sgml, name, entry);
if (res < 0) {
xmlFreeCatalogEntry(entry);
}
@@ -1879,7 +2219,7 @@ xmlParseSGMLCatalog(const xmlChar *value, const char *file, int super) {
entry = xmlNewCatalogEntry(type, sysid, NULL,
XML_CATA_PREFER_NONE);
- res = xmlHashAddEntry(xmlDefaultCatalog, sysid, entry);
+ res = xmlHashAddEntry(catal->sgml, sysid, entry);
if (res < 0) {
xmlFreeCatalogEntry(entry);
}
@@ -1888,7 +2228,7 @@ xmlParseSGMLCatalog(const xmlChar *value, const char *file, int super) {
filename = xmlBuildURI(sysid, base);
if (filename != NULL) {
- xmlLoadCatalog((const char *)filename);
+ xmlExpandCatalog(catal, (const char *)filename);
xmlFree(filename);
}
}
@@ -1909,6 +2249,12 @@ xmlParseSGMLCatalog(const xmlChar *value, const char *file, int super) {
return(0);
}
+/************************************************************************
+ * *
+ * SGML Catalog handling *
+ * *
+ ************************************************************************/
+
/**
* xmlCatalogGetSGMLPublic:
* @catal: an SGML catalog hash
@@ -1959,6 +2305,7 @@ xmlCatalogGetSGMLSystem(xmlHashTablePtr catal, const xmlChar *sysID) {
/**
* xmlCatalogSGMLResolve:
+ * @catal: the SGML catalog
* @pubId: the public ID string
* @sysId: the system ID string
*
@@ -1967,140 +2314,445 @@ xmlCatalogGetSGMLSystem(xmlHashTablePtr catal, const xmlChar *sysID) {
* Returns the URI of the resource or NULL if not found
*/
static const xmlChar *
-xmlCatalogSGMLResolve(const xmlChar *pubID, const xmlChar *sysID) {
+xmlCatalogSGMLResolve(xmlCatalogPtr catal, const xmlChar *pubID,
+ const xmlChar *sysID) {
const xmlChar *ret = NULL;
- if (xmlDefaultCatalog == NULL)
+ if (catal->sgml == NULL)
return(NULL);
if (pubID != NULL)
- ret = xmlCatalogGetSGMLPublic(xmlDefaultCatalog, pubID);
+ ret = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
if (ret != NULL)
return(ret);
if (sysID != NULL)
- ret = xmlCatalogGetSGMLSystem(xmlDefaultCatalog, sysID);
+ ret = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
return(NULL);
}
/************************************************************************
* *
- * Public interfaces *
+ * Specific Public interfaces *
* *
************************************************************************/
/**
- * xmlInitializeCatalog:
+ * xmlLoadSGMLSuperCatalog:
+ * @filename: a file path
*
- * Do the catalog initialization.
- * TODO: this function is not thread safe, catalog initialization should
- * preferably be done once at startup
+ * Load an SGML super catalog. It won't expand CATALOG or DELEGATE
+ * references. This is only needed for manipulating SGML Super Catalogs
+ * like adding and removing CATALOG or DELEGATE entries.
+ *
+ * Returns the catalog parsed or NULL in case of error
*/
-void
-xmlInitializeCatalog(void) {
- const char *catalogs;
+xmlCatalogPtr
+xmlLoadSGMLSuperCatalog(const char *filename)
+{
+ xmlChar *content;
+ xmlCatalogPtr catal;
+ int ret;
- if (xmlCatalogInitialized != 0)
- return;
+ content = xmlLoadFileContent(filename);
+ if (content == NULL)
+ return(NULL);
- if (getenv("XML_DEBUG_CATALOG"))
- xmlDebugCatalogs = 1;
- if ((xmlDefaultXMLCatalogList == NULL) && (xmlDefaultCatalog == NULL)) {
- catalogs = getenv("XML_CATALOG_FILES");
- if (catalogs == NULL)
- catalogs = XML_DEFAULT_CATALOG;
- xmlDefaultXMLCatalogList = xmlNewCatalogEntry(XML_CATA_CATALOG,
- NULL, BAD_CAST catalogs, xmlCatalogDefaultPrefer);
+ catal = xmlNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
+ if (catal == NULL) {
+ xmlFree(content);
+ return(NULL);
}
- xmlCatalogInitialized = 1;
+ ret = xmlParseSGMLCatalog(catal, content, filename, 1);
+ xmlFree(content);
+ if (ret < 0) {
+ xmlFreeCatalog(catal);
+ return(NULL);
+ }
+ return (catal);
}
/**
- * xmlLoadSGMLSuperCatalog:
+ * xmlLoadACatalog:
* @filename: a file path
*
- * Load an SGML super catalog. It won't expand CATALOG or DELEGATE
- * references. This is only needed for manipulating SGML Super Catalogs
- * like adding and removing CATALOG or DELEGATE entries.
+ * Load the catalog and build the associated data structures.
+ * This can be either an XML Catalog or an SGML Catalog
+ * It will recurse in SGML CATALOG entries. On the other hand XML
+ * Catalogs are not handled recursively.
*
- * Returns 0 in case of success -1 in case of error
+ * Returns the catalog parsed or NULL in case of error
*/
-int
-xmlLoadSGMLSuperCatalog(const char *filename)
+xmlCatalogPtr
+xmlLoadACatalog(const char *filename)
{
-#ifdef HAVE_STAT
- int fd;
-#else
- FILE *fd;
-#endif
- int len, ret;
- long size;
+ xmlChar *content;
+ xmlChar *first;
+ xmlCatalogPtr catal;
+ int ret;
-#ifdef HAVE_STAT
- struct stat info;
-#endif
+ content = xmlLoadFileContent(filename);
+ if (content == NULL)
+ return(NULL);
+
+
+ first = content;
+
+ while ((*first != 0) && (*first != '-') && (*first != '<') &&
+ (!(((*first >= 'A') && (*first <= 'Z')) ||
+ ((*first >= 'a') && (*first <= 'z')))))
+ first++;
+
+ if (*first != '<') {
+ catal = xmlNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
+ if (catal == NULL) {
+ xmlFree(content);
+ return(NULL);
+ }
+ ret = xmlParseSGMLCatalog(catal, content, filename, 0);
+ if (ret < 0) {
+ xmlFreeCatalog(catal);
+ xmlFree(content);
+ return(NULL);
+ }
+ } else {
+ catal = xmlNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
+ if (catal == NULL) {
+ xmlFree(content);
+ return(NULL);
+ }
+ catal->xml =
+ xmlParseXMLCatalog(content, XML_CATA_PREFER_PUBLIC, filename);
+ }
+ xmlFree(content);
+ return (catal);
+}
+
+/**
+ * xmlExpandCatalog:
+ * @catal: a catalog
+ * @filename: a file path
+ *
+ * Load the catalog and expand the existing catal structure.
+ * This can be either an XML Catalog or an SGML Catalog
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+int
+xmlExpandCatalog(xmlCatalogPtr catal, const char *filename)
+{
xmlChar *content;
+ int ret;
- if (filename == NULL)
- return (-1);
+ if ((catal == NULL) || (filename == NULL))
+ return(-1);
- if (xmlDefaultCatalog == NULL)
- xmlDefaultCatalog = xmlHashCreate(20);
- if (xmlDefaultCatalog == NULL)
- return (-1);
+ content = xmlLoadFileContent(filename);
+ if (content == NULL)
+ return(-1);
-#ifdef HAVE_STAT
- if (stat(filename, &info) < 0)
- return (-1);
-#endif
-#ifdef HAVE_STAT
- if ((fd = open(filename, O_RDONLY)) < 0) {
-#else
- if ((fd = fopen(filename, "rb")) == NULL) {
-#endif
- catalNr--;
- return (-1);
+ if (catal->type == XML_SGML_CATALOG_TYPE) {
+ ret = xmlParseSGMLCatalog(catal, content, filename, 0);
+ if (ret < 0) {
+ xmlFree(content);
+ return(-1);
+ }
+ } else {
+ xmlCatalogEntryPtr tmp, cur;
+ tmp = xmlParseXMLCatalog(content, XML_CATA_PREFER_PUBLIC, filename);
+
+ /* @@ THREADING LOCK catal @@ */
+ cur = catal->xml;
+ if (cur == NULL) {
+ catal->xml = tmp;
+ } else {
+ while (cur->next != NULL) cur = cur->next;
+ cur->next = tmp;
+ }
+ /* @@ THREADING RELEASE catal @@ */
}
-#ifdef HAVE_STAT
- size = info.st_size;
-#else
- if (fseek(fd, 0, SEEK_END) || (size = ftell(fd)) == EOF || fseek(fd, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */
- fclose(fd);
- return (-1);
+ xmlFree(content);
+ return (0);
+}
+
+/**
+ * xmlACatalogResolveSystem:
+ * @catal: a Catalog
+ * @sysId: the public ID string
+ *
+ * Try to lookup the catalog resource for a system ID
+ *
+ * Returns the system ID if found or NULL otherwise, the value returned
+ * must be freed by the caller.
+ */
+xmlChar *
+xmlACatalogResolveSystem(xmlCatalogPtr catal, const xmlChar *sysID) {
+ xmlChar *ret = NULL;
+
+ if ((sysID == NULL) || (catal == NULL))
+ return(NULL);
+
+ if (xmlDebugCatalogs)
+ xmlGenericError(xmlGenericErrorContext,
+ "Resolve sysID %s\n", sysID);
+
+ if (catal->type == XML_XML_CATALOG_TYPE) {
+ ret = xmlCatalogListXMLResolve(catal->xml, NULL, sysID);
+ if (ret == XML_CATAL_BREAK)
+ ret = NULL;
+ } else {
+ const xmlChar *sgml;
+
+ sgml = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
+ if (sgml != NULL)
+ ret = xmlStrdup(sgml);
}
-#endif
- content = xmlMalloc(size + 10);
- if (content == NULL) {
- xmlGenericError(xmlGenericErrorContext,
- "realloc of %d byte failed\n", size + 10);
- catalNr--;
- return (-1);
+ return(ret);
+}
+
+/**
+ * xmlACatalogResolvePublic:
+ * @catal: a Catalog
+ * @pubId: the public ID string
+ *
+ * Try to lookup the system ID associated to a public ID in that catalog
+ *
+ * Returns the system ID if found or NULL otherwise, the value returned
+ * must be freed by the caller.
+ */
+xmlChar *
+xmlACatalogResolvePublic(xmlCatalogPtr catal, const xmlChar *pubID) {
+ xmlChar *ret = NULL;
+
+ if ((pubID == NULL) || (catal == NULL))
+ return(NULL);
+
+ if (xmlDebugCatalogs)
+ xmlGenericError(xmlGenericErrorContext,
+ "Resolve pubID %s\n", pubID);
+
+ if (catal->type == XML_XML_CATALOG_TYPE) {
+ ret = xmlCatalogListXMLResolve(catal->xml, pubID, NULL);
+ if (ret == XML_CATAL_BREAK)
+ ret = NULL;
+ } else {
+ const xmlChar *sgml;
+
+ sgml = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
+ if (sgml != NULL)
+ ret = xmlStrdup(sgml);
}
-#ifdef HAVE_STAT
- len = read(fd, content, size);
-#else
- len = fread(content, 1, size, fd);
-#endif
- if (len < 0) {
- xmlFree(content);
- catalNr--;
- return (-1);
+ return(ret);
+}
+
+/**
+ * xmlACatalogResolve:
+ * @catal: a Catalog
+ * @pubId: the public ID string
+ * @sysId: the system ID string
+ *
+ * Do a complete resolution lookup of an External Identifier
+ *
+ * Returns the URI of the resource or NULL if not found, it must be freed
+ * by the caller.
+ */
+xmlChar *
+xmlACatalogResolve(xmlCatalogPtr catal, const xmlChar * pubID,
+ const xmlChar * sysID)
+{
+ xmlChar *ret = NULL;
+
+ if (((pubID == NULL) && (sysID == NULL)) || (catal == NULL))
+ return (NULL);
+
+ if (xmlDebugCatalogs) {
+ if (pubID != NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Resolve: pubID %s\n", pubID);
+ } else {
+ xmlGenericError(xmlGenericErrorContext,
+ "Resolve: sysID %s\n", sysID);
+ }
}
- content[len] = 0;
-#ifdef HAVE_STAT
- close(fd);
-#else
- fclose(fd);
-#endif
- ret = xmlParseSGMLCatalog(content, filename, 1);
+ if (catal->type == XML_XML_CATALOG_TYPE) {
+ ret = xmlCatalogListXMLResolve(catal->xml, pubID, sysID);
+ if (ret == XML_CATAL_BREAK)
+ ret = NULL;
+ } else {
+ const xmlChar *sgml;
- xmlFree(content);
+ sgml = xmlCatalogSGMLResolve(catal, pubID, sysID);
+ if (sgml != NULL)
+ ret = xmlStrdup(sgml);
+ }
return (ret);
}
/**
+ * xmlACatalogResolveURI:
+ * @catal: a Catalog
+ * @pubId: the URI
+ *
+ * Do a complete resolution lookup of an URI
+ *
+ * Returns the URI of the resource or NULL if not found, it must be freed
+ * by the caller.
+ */
+xmlChar *
+xmlACatalogResolveURI(xmlCatalogPtr catal, const xmlChar *URI) {
+ xmlChar *ret = NULL;
+
+ if ((URI == NULL) || (catal == NULL))
+ return(NULL);
+
+ if (catal->type == XML_XML_CATALOG_TYPE)
+ xmlGenericError(xmlGenericErrorContext,
+ "Resolve URI %s\n", URI);
+
+ if (catal->type == XML_XML_CATALOG_TYPE) {
+ ret = xmlCatalogListXMLResolveURI(catal->xml, URI);
+ if (ret == XML_CATAL_BREAK)
+ ret = NULL;
+ } else {
+ const xmlChar *sgml;
+
+ sgml = xmlCatalogSGMLResolve(catal, NULL, URI);
+ if (sgml != NULL)
+ sgml = xmlStrdup(sgml);
+ }
+ return(ret);
+}
+
+/**
+ * xmlACatalogDump:
+ * @catal: a Catalog
+ * @out: the file.
+ *
+ * Free up all the memory associated with catalogs
+ */
+void
+xmlACatalogDump(xmlCatalogPtr catal, FILE *out) {
+ if (out == NULL)
+ return;
+
+ if (catal->type == XML_XML_CATALOG_TYPE) {
+ xmlDumpXMLCatalog(out, catal->xml);
+ } else {
+ xmlHashScan(catal->sgml,
+ (xmlHashScanner) xmlCatalogDumpEntry, out);
+ }
+}
+
+/**
+ * xmlACatalogAdd:
+ * @catal: a Catalog
+ * @type: the type of record to add to the catalog
+ * @orig: the system, public or prefix to match
+ * @replace: the replacement value for the match
+ *
+ * Add an entry in the catalog, it may overwrite existing but
+ * different entries.
+ *
+ * Returns 0 if successful, -1 otherwise
+ */
+int
+xmlACatalogAdd(xmlCatalogPtr catal, const xmlChar * type,
+ const xmlChar * orig, const xmlChar * replace)
+{
+ int res = -1;
+
+ if (catal == NULL)
+ return(-1);
+
+ if (catal->type == XML_XML_CATALOG_TYPE) {
+ res = xmlAddXMLCatalog(catal->xml, type, orig, replace);
+ } else {
+ xmlCatalogEntryType cattype;
+
+ cattype = xmlGetSGMLCatalogEntryType(type);
+ if (cattype != XML_CATA_NONE) {
+ xmlCatalogEntryPtr entry;
+
+ entry = xmlNewCatalogEntry(cattype, orig, replace,
+ XML_CATA_PREFER_NONE);
+ res = xmlHashAddEntry(catal->sgml, orig, entry);
+ }
+ }
+ return (res);
+}
+
+/**
+ * xmlACatalogRemove:
+ * @catal: a Catalog
+ * @value: the value to remove
+ *
+ * Remove an entry from the catalog
+ *
+ * Returns the number of entries removed if successful, -1 otherwise
+ */
+int
+xmlACatalogRemove(xmlCatalogPtr catal, const xmlChar *value) {
+ int res = -1;
+
+ if ((catal == NULL) || (value == NULL))
+ return(-1);
+
+ if (catal->type == XML_XML_CATALOG_TYPE) {
+ res = xmlDelXMLCatalog(catal->xml, value);
+ } else {
+ res = xmlHashRemoveEntry(catal->sgml, value,
+ (xmlHashDeallocator) xmlFreeCatalogEntry);
+ if (res == 0)
+ res = 1;
+ }
+ return(res);
+}
+
+/************************************************************************
+ * *
+ * Public interfaces manipulating the global shared default catalog *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlInitializeCatalog:
+ *
+ * Do the catalog initialization.
+ * TODO: this function is not thread safe, catalog initialization should
+ * preferably be done once at startup
+ */
+void
+xmlInitializeCatalog(void) {
+ if (xmlCatalogInitialized != 0)
+ return;
+
+ if (getenv("XML_DEBUG_CATALOG"))
+ xmlDebugCatalogs = 1;
+ if (xmlDefaultCatalog == NULL) {
+ const char *catalogs;
+ xmlCatalogPtr catal;
+
+ catalogs = getenv("XML_CATALOG_FILES");
+ if (catalogs == NULL)
+ catalogs = XML_XML_DEFAULT_CATALOG;
+
+ catal = xmlNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
+ if (catal == NULL)
+ return;
+
+ catal->xml = xmlNewCatalogEntry(XML_CATA_CATALOG,
+ NULL, BAD_CAST catalogs, xmlCatalogDefaultPrefer);
+
+ xmlDefaultCatalog = catal;
+ }
+
+ xmlCatalogInitialized = 1;
+}
+
+
+/**
* xmlLoadCatalog:
* @filename: a file path
*
@@ -2114,124 +2766,26 @@ xmlLoadSGMLSuperCatalog(const char *filename)
int
xmlLoadCatalog(const char *filename)
{
-#ifdef HAVE_STAT
- int fd;
-#else
- FILE *fd;
-#endif
- int len, ret, i;
- long size;
-
-#ifdef HAVE_STAT
- struct stat info;
-#endif
- xmlChar *content;
-
- if (filename == NULL)
- return (-1);
-
- if (xmlDefaultCatalog == NULL)
- xmlDefaultCatalog = xmlHashCreate(20);
- if (xmlDefaultCatalog == NULL)
- return (-1);
-
- /*
- * Need to be done after ...
- */
- if (!xmlCatalogInitialized)
- xmlInitializeCatalog();
+ int ret;
+ xmlCatalogPtr catal;
-#ifdef HAVE_STAT
- if (stat(filename, &info) < 0)
- return (-1);
-#endif
+ if (xmlDefaultCatalog == NULL) {
+ catal = xmlLoadACatalog(filename);
+ if (catal == NULL)
+ return(-1);
- /*
- * Prevent loops
- */
- for (i = 0; i < catalNr; i++) {
- if (xmlStrEqual((const xmlChar *) catalTab[i],
- (const xmlChar *) filename)) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlLoadCatalog: %s seems to induce a loop\n",
- filename);
- return (-1);
- }
- }
- if (catalNr >= catalMax) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlLoadCatalog: %s catalog list too deep\n",
- filename);
- return (-1);
- }
- catalTab[catalNr++] = filename;
+ xmlDefaultCatalog = catal;
-#ifdef HAVE_STAT
- if ((fd = open(filename, O_RDONLY)) < 0) {
-#else
- if ((fd = fopen(filename, "rb")) == NULL) {
-#endif
- catalNr--;
- return (-1);
- }
-#ifdef HAVE_STAT
- size = info.st_size;
-#else
- if (fseek(fd, 0, SEEK_END) || (size = ftell(fd)) == EOF || fseek(fd, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */
- fclose(fd);
- return (-1);
- }
-#endif
- content = xmlMalloc(size + 10);
- if (content == NULL) {
- xmlGenericError(xmlGenericErrorContext,
- "realloc of %d byte failed\n", size + 10);
- catalNr--;
- return (-1);
- }
-#ifdef HAVE_STAT
- len = read(fd, content, size);
-#else
- len = fread(content, 1, size, fd);
-#endif
- if (len < 0) {
- xmlFree(content);
- catalNr--;
- return (-1);
+ /*
+ * Need to be done after ...
+ */
+ if (!xmlCatalogInitialized)
+ xmlInitializeCatalog();
+ return(0);
}
- content[len] = 0;
-#ifdef HAVE_STAT
- close(fd);
-#else
- fclose(fd);
-#endif
- if ((content[0] == ' ') || (content[0] == '-') ||
- ((content[0] >= 'A') && (content[0] <= 'Z')) ||
- ((content[0] >= 'a') && (content[0] <= 'z')))
- ret = xmlParseSGMLCatalog(content, filename, 0);
- else {
- xmlCatalogEntryPtr catal, tmp;
-
- /* TODO: allow to switch the default preference */
- catal =
- xmlParseXMLCatalog(content, XML_CATA_PREFER_PUBLIC, filename);
- if (catal != NULL) {
- if (xmlDefaultXMLCatalogList == NULL)
- xmlDefaultXMLCatalogList = catal;
- else {
- tmp = xmlDefaultXMLCatalogList;
- while (tmp->next != NULL)
- tmp = tmp->next;
- tmp->next = catal;
- }
- ret = 0;
- } else
- ret = -1;
- }
- xmlFree(content);
- catalNr--;
- return (ret);
+ ret = xmlExpandCatalog(xmlDefaultCatalog, filename);
+ return(ret);
}
/**
@@ -2283,56 +2837,14 @@ xmlCatalogCleanup(void) {
if (xmlCatalogXMLFiles != NULL)
xmlHashFree(xmlCatalogXMLFiles, NULL);
xmlCatalogXMLFiles = NULL;
- if (xmlDefaultXMLCatalogList != NULL)
- xmlFreeCatalogEntryList(xmlDefaultXMLCatalogList);
- xmlDefaultXMLCatalogList = NULL;
if (xmlDefaultCatalog != NULL)
- xmlHashFree(xmlDefaultCatalog,
- (xmlHashDeallocator) xmlFreeCatalogEntry);
+ xmlFreeCatalog(xmlDefaultCatalog);
xmlDefaultCatalog = NULL;
xmlDebugCatalogs = 0;
- xmlDefaultCatalog = NULL;
xmlCatalogInitialized = 0;
}
/**
- * xmlCatalogGetSystem:
- * @pubId: the public ID string
- *
- * Try to lookup the system ID associated to a public ID
- * DEPRECATED, use xmlCatalogResolveSystem()
- *
- * Returns the system ID if found or NULL otherwise.
- */
-const xmlChar *
-xmlCatalogGetSystem(const xmlChar *sysID) {
- xmlChar *ret;
- static xmlChar result[1000];
-
- if (sysID == NULL)
- return(NULL);
-
- if (!xmlCatalogInitialized)
- xmlInitializeCatalog();
-
- /*
- * Check first the XML catalogs
- */
- if (xmlDefaultXMLCatalogList != NULL) {
- ret = xmlCatalogListXMLResolve(xmlDefaultXMLCatalogList, NULL, sysID);
- if (ret != NULL) {
- snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
- result[sizeof(result) - 1] = 0;
- return(result);
- }
- }
-
- if (xmlDefaultCatalog != NULL)
- return(xmlCatalogGetSGMLSystem(xmlDefaultCatalog, sysID));
- return(NULL);
-}
-
-/**
* xmlCatalogResolveSystem:
* @sysId: the public ID string
*
@@ -2343,69 +2855,13 @@ xmlCatalogGetSystem(const xmlChar *sysID) {
*/
xmlChar *
xmlCatalogResolveSystem(const xmlChar *sysID) {
- xmlCatalogEntryPtr catal;
xmlChar *ret;
- const xmlChar *sgml;
- if (sysID == NULL)
- return(NULL);
-
if (!xmlCatalogInitialized)
xmlInitializeCatalog();
- /*
- * Check first the XML catalogs
- */
- catal = xmlDefaultXMLCatalogList;
- if (catal != NULL) {
- ret = xmlCatalogListXMLResolve(xmlDefaultXMLCatalogList, NULL, sysID);
- if ((ret != NULL) && (ret != XML_CATAL_BREAK))
- return(ret);
- }
-
- if (xmlDefaultCatalog != NULL) {
- sgml = xmlCatalogGetSGMLSystem(xmlDefaultCatalog, sysID);
- if (sgml != NULL)
- return(xmlStrdup(sgml));
- }
- return(NULL);
-}
-
-/**
- * xmlCatalogGetPublic:
- * @pubId: the public ID string
- *
- * Try to lookup the system ID associated to a public ID
- * DEPRECATED, use xmlCatalogResolvePublic()
- *
- * Returns the system ID if found or NULL otherwise.
- */
-const xmlChar *
-xmlCatalogGetPublic(const xmlChar *pubID) {
- xmlChar *ret;
- static xmlChar result[1000];
-
- if (pubID == NULL)
- return(NULL);
-
- if (!xmlCatalogInitialized)
- xmlInitializeCatalog();
-
- /*
- * Check first the XML catalogs
- */
- if (xmlDefaultXMLCatalogList != NULL) {
- ret = xmlCatalogListXMLResolve(xmlDefaultXMLCatalogList, pubID, NULL);
- if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
- snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
- result[sizeof(result) - 1] = 0;
- return(result);
- }
- }
-
- if (xmlDefaultCatalog != NULL)
- return(xmlCatalogGetSGMLPublic(xmlDefaultCatalog, pubID));
- return(NULL);
+ ret = xmlACatalogResolveSystem(xmlDefaultCatalog, sysID);
+ return(ret);
}
/**
@@ -2419,32 +2875,13 @@ xmlCatalogGetPublic(const xmlChar *pubID) {
*/
xmlChar *
xmlCatalogResolvePublic(const xmlChar *pubID) {
- xmlCatalogEntryPtr catal;
xmlChar *ret;
- const xmlChar *sgml;
- if (pubID == NULL)
- return(NULL);
-
if (!xmlCatalogInitialized)
xmlInitializeCatalog();
- /*
- * Check first the XML catalogs
- */
- catal = xmlDefaultXMLCatalogList;
- if (catal != NULL) {
- ret = xmlCatalogListXMLResolve(xmlDefaultXMLCatalogList, pubID, NULL);
- if ((ret != NULL) && (ret != XML_CATAL_BREAK))
- return(ret);
- }
-
- if (xmlDefaultCatalog != NULL) {
- sgml = xmlCatalogGetSGMLPublic(xmlDefaultCatalog, pubID);
- if (sgml != NULL)
- return(xmlStrdup(sgml));
- }
- return(NULL);
+ ret = xmlACatalogResolvePublic(xmlDefaultCatalog, pubID);
+ return(ret);
}
/**
@@ -2459,35 +2896,13 @@ xmlCatalogResolvePublic(const xmlChar *pubID) {
*/
xmlChar *
xmlCatalogResolve(const xmlChar *pubID, const xmlChar *sysID) {
- if ((pubID == NULL) && (sysID == NULL))
- return(NULL);
+ xmlChar *ret;
if (!xmlCatalogInitialized)
xmlInitializeCatalog();
- if (xmlDebugCatalogs) {
- if (pubID != NULL) {
- xmlGenericError(xmlGenericErrorContext,
- "Resolve: pubID %s\n", pubID);
- } else {
- xmlGenericError(xmlGenericErrorContext,
- "Resolve: sysID %s\n", sysID);
- }
- }
-
- if (xmlDefaultXMLCatalogList != NULL) {
- xmlChar *ret;
- ret = xmlCatalogListXMLResolve(xmlDefaultXMLCatalogList, pubID, sysID);
- if ((ret != NULL) && (ret != XML_CATAL_BREAK))
- return(ret);
- } else {
- const xmlChar *ret;
-
- ret = xmlCatalogSGMLResolve(pubID, sysID);
- if (ret != NULL)
- return(xmlStrdup(ret));
- }
- return(NULL);
+ ret = xmlACatalogResolve(xmlDefaultCatalog, pubID, sysID);
+ return(ret);
}
/**
@@ -2501,30 +2916,13 @@ xmlCatalogResolve(const xmlChar *pubID, const xmlChar *sysID) {
*/
xmlChar *
xmlCatalogResolveURI(const xmlChar *URI) {
+ xmlChar *ret;
+
if (!xmlCatalogInitialized)
xmlInitializeCatalog();
- if (URI == NULL)
- return(NULL);
-
- if (xmlDebugCatalogs)
- xmlGenericError(xmlGenericErrorContext,
- "Resolve URI %s\n", URI);
-
- if (xmlDefaultXMLCatalogList != NULL) {
- xmlChar *ret;
-
- ret = xmlCatalogListXMLResolveURI(xmlDefaultXMLCatalogList, URI);
- if ((ret != NULL) && (ret != XML_CATAL_BREAK))
- return(ret);
- } else {
- const xmlChar *ret;
-
- ret = xmlCatalogSGMLResolve(NULL, URI);
- if (ret != NULL)
- return(xmlStrdup(ret));
- }
- return(NULL);
+ ret = xmlACatalogResolveURI(xmlDefaultCatalog, URI);
+ return(ret);
}
/**
@@ -2538,12 +2936,10 @@ xmlCatalogDump(FILE *out) {
if (out == NULL)
return;
- if (xmlDefaultXMLCatalogList != NULL) {
- xmlDumpXMLCatalog(out, xmlDefaultXMLCatalogList);
- } else if (xmlDefaultCatalog != NULL) {
- xmlHashScan(xmlDefaultCatalog,
- (xmlHashScanner) xmlCatalogDumpEntry, out);
- }
+ if (!xmlCatalogInitialized)
+ xmlInitializeCatalog();
+
+ xmlACatalogDump(xmlDefaultCatalog, out);
}
/**
@@ -2554,6 +2950,8 @@ xmlCatalogDump(FILE *out) {
*
* Add an entry in the catalog, it may overwrite existing but
* different entries.
+ * If called before any other catalo routine, allows to override the
+ * default shared catalog put in place by xmlInitializeCatalog();
*
* Returns 0 if successful, -1 otherwise
*/
@@ -2561,38 +2959,26 @@ int
xmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace) {
int res = -1;
- if ((xmlDefaultCatalog != NULL) &&
- (xmlStrEqual(type, BAD_CAST "sgmlcatalog"))) {
- xmlCatalogEntryPtr entry;
-
- entry = xmlNewCatalogEntry(SGML_CATA_CATALOG, replace, NULL,
- XML_CATA_PREFER_NONE);
- res = xmlHashAddEntry(xmlDefaultCatalog, replace, entry);
- return(0);
- }
- if ((xmlDefaultXMLCatalogList == NULL) &&
+ /*
+ * Specific case where one want to override the default catalog
+ * put in place by xmlInitializeCatalog();
+ */
+ if ((xmlDefaultCatalog == NULL) &&
(xmlStrEqual(type, BAD_CAST "catalog"))) {
- xmlDefaultXMLCatalogList = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
- orig, xmlCatalogDefaultPrefer);
+ xmlDefaultCatalog = xmlNewCatalog(XML_XML_CATALOG_TYPE,
+ xmlCatalogDefaultPrefer);
+ xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
+ orig, xmlCatalogDefaultPrefer);
+
+ if (!xmlCatalogInitialized)
+ xmlInitializeCatalog();
return(0);
}
if (!xmlCatalogInitialized)
xmlInitializeCatalog();
- if (xmlDefaultXMLCatalogList != NULL) {
- res = xmlAddXMLCatalog(xmlDefaultXMLCatalogList, type, orig, replace);
- } else if (xmlDefaultCatalog != NULL) {
- xmlCatalogEntryType cattype;
-
- cattype = xmlGetSGMLCatalogEntryType(type);
- if (cattype != XML_CATA_NONE) {
- xmlCatalogEntryPtr entry;
- entry = xmlNewCatalogEntry(cattype, orig, replace,
- XML_CATA_PREFER_NONE);
- res = xmlHashAddEntry(xmlDefaultCatalog, orig, entry);
- }
- }
+ res = xmlACatalogAdd(xmlDefaultCatalog, type, orig, replace);
return(res);
}
@@ -2606,19 +2992,12 @@ xmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace)
*/
int
xmlCatalogRemove(const xmlChar *value) {
- int res = -1;
+ int res;
if (!xmlCatalogInitialized)
xmlInitializeCatalog();
- if (xmlDefaultXMLCatalogList != NULL) {
- res = xmlDelXMLCatalog(xmlDefaultXMLCatalogList, value);
- } else if (xmlDefaultCatalog != NULL) {
- res = xmlHashRemoveEntry(xmlDefaultCatalog, value,
- (xmlHashDeallocator) xmlFreeCatalogEntry);
- if (res == 0)
- res = 1;
- }
+ res = xmlACatalogRemove(xmlDefaultCatalog, value);
return(res);
}
@@ -2636,25 +3015,15 @@ xmlCatalogConvert(void) {
if (!xmlCatalogInitialized)
xmlInitializeCatalog();
- if (xmlDebugCatalogs) {
- xmlGenericError(xmlGenericErrorContext,
- "Converting SGML catalog to XML\n");
- }
-
- if (xmlDefaultXMLCatalogList == NULL) {
- xmlDefaultXMLCatalogList = xmlNewCatalogEntry(XML_CATA_CATALOG,
- NULL, BAD_CAST "NewCatalog.xml",
- xmlCatalogDefaultPrefer);
- }
- if (xmlDefaultCatalog != NULL) {
- res = 0;
-
- xmlHashScan(xmlDefaultCatalog,
- (xmlHashScanner) xmlCatalogConvertEntry, &res);
- }
+ res = xmlConvertSGMLCatalog(xmlDefaultCatalog);
return(res);
}
+/************************************************************************
+ * *
+ * Public interface manipulating the common preferences *
+ * *
+ ************************************************************************/
/**
* xmlCatalogGetDefaults:
*
@@ -2758,6 +3127,12 @@ xmlCatalogSetDebug(int level) {
return(ret);
}
+/************************************************************************
+ * *
+ * Minimal interfaces used for per-document catalogs by the parser *
+ * *
+ ************************************************************************/
+
/**
* xmlCatalogFreeLocal:
* @catalogs: a document's list of catalogs
@@ -2889,4 +3264,97 @@ xmlCatalogLocalResolveURI(void *catalogs, const xmlChar *URI) {
return(NULL);
}
+/************************************************************************
+ * *
+ * Deprecated interfaces *
+ * *
+ ************************************************************************/
+/**
+ * xmlCatalogGetSystem:
+ * @pubId: the public ID string
+ *
+ * Try to lookup the system ID associated to a public ID
+ * DEPRECATED, use xmlCatalogResolveSystem()
+ *
+ * Returns the system ID if found or NULL otherwise.
+ */
+const xmlChar *
+xmlCatalogGetSystem(const xmlChar *sysID) {
+ xmlChar *ret;
+ static xmlChar result[1000];
+ static int msg = 0;
+
+ if (msg == 0) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Use of deprecated xmlCatalogGetSystem() call\n");
+ msg++;
+ }
+
+ if (sysID == NULL)
+ return(NULL);
+
+ if (!xmlCatalogInitialized)
+ xmlInitializeCatalog();
+
+ /*
+ * Check first the XML catalogs
+ */
+ if (xmlDefaultCatalog != NULL) {
+ ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, NULL, sysID);
+ if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
+ snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
+ result[sizeof(result) - 1] = 0;
+ return(result);
+ }
+ }
+
+ if (xmlDefaultCatalog != NULL)
+ return(xmlCatalogGetSGMLSystem(xmlDefaultCatalog->sgml, sysID));
+ return(NULL);
+}
+
+/**
+ * xmlCatalogGetPublic:
+ * @pubId: the public ID string
+ *
+ * Try to lookup the system ID associated to a public ID
+ * DEPRECATED, use xmlCatalogResolvePublic()
+ *
+ * Returns the system ID if found or NULL otherwise.
+ */
+const xmlChar *
+xmlCatalogGetPublic(const xmlChar *pubID) {
+ xmlChar *ret;
+ static xmlChar result[1000];
+ static int msg = 0;
+
+ if (msg == 0) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Use of deprecated xmlCatalogGetPublic() call\n");
+ msg++;
+ }
+
+ if (pubID == NULL)
+ return(NULL);
+
+ if (!xmlCatalogInitialized)
+ xmlInitializeCatalog();
+
+ /*
+ * Check first the XML catalogs
+ */
+ if (xmlDefaultCatalog != NULL) {
+ ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, pubID, NULL);
+ if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
+ snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
+ result[sizeof(result) - 1] = 0;
+ return(result);
+ }
+ }
+
+ if (xmlDefaultCatalog != NULL)
+ return(xmlCatalogGetSGMLPublic(xmlDefaultCatalog->sgml, pubID));
+ return(NULL);
+}
+
#endif /* LIBXML_CATALOG_ENABLED */