📄 catalog.c.svn-base
字号:
/** * catalog.c: set of generic Catalog related routines * * Reference: SGML Open Technical Resolution TR9401:1997. * http://www.jclark.com/sp/catalog.htm * * XML Catalogs Working Draft 06 August 2001 * http://www.oasis-open.org/committees/entity/spec-2001-08-06.html * * See Copyright for the status of this software. * * Daniel.Veillard@imag.fr */#define IN_LIBXML#include "libxml.h"#ifdef LIBXML_CATALOG_ENABLED#ifdef HAVE_SYS_TYPES_H#include <sys/types.h>#endif#ifdef HAVE_SYS_STAT_H#include <sys/stat.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h>#endif#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#include <string.h>#include <libxml/xmlmemory.h>#include <libxml/hash.h>#include <libxml/uri.h>#include <libxml/parserInternals.h>#include <libxml/catalog.h>#include <libxml/xmlerror.h>#include <libxml/threads.h>#include <libxml/globals.h>#define MAX_DELEGATE 50#define MAX_CATAL_DEPTH 50/** * TODO: * * macro to flag unimplemented blocks * XML_CATALOG_PREFER user env to select between system/public prefered * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk> *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with *> values "system" and "public". I have made the default be "system" to *> match yours. */#define TODO \ xmlGenericError(xmlGenericErrorContext, \ "Unimplemented block at %s:%d\n", \ __FILE__, __LINE__);#define XML_URN_PUBID "urn:publicid:"#define XML_CATAL_BREAK ((xmlChar *) -1)#ifndef XML_XML_DEFAULT_CATALOG#define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog"#endif#ifndef XML_SGML_DEFAULT_CATALOG#define XML_SGML_DEFAULT_CATALOG "file:///etc/sgml/catalog"#endifstatic int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename);/************************************************************************ * * * Types, all private * * * ************************************************************************/typedef enum { XML_CATA_REMOVED = -1, XML_CATA_NONE = 0, XML_CATA_CATALOG, XML_CATA_BROKEN_CATALOG, XML_CATA_NEXT_CATALOG, XML_CATA_PUBLIC, XML_CATA_SYSTEM, XML_CATA_REWRITE_SYSTEM, XML_CATA_DELEGATE_PUBLIC, XML_CATA_DELEGATE_SYSTEM, XML_CATA_URI, XML_CATA_REWRITE_URI, XML_CATA_DELEGATE_URI, SGML_CATA_SYSTEM, SGML_CATA_PUBLIC, SGML_CATA_ENTITY, SGML_CATA_PENTITY, SGML_CATA_DOCTYPE, SGML_CATA_LINKTYPE, SGML_CATA_NOTATION, SGML_CATA_DELEGATE, SGML_CATA_BASE, SGML_CATA_CATALOG, SGML_CATA_DOCUMENT, SGML_CATA_SGMLDECL} xmlCatalogEntryType;typedef struct _xmlCatalogEntry xmlCatalogEntry;typedef xmlCatalogEntry *xmlCatalogEntryPtr;struct _xmlCatalogEntry { struct _xmlCatalogEntry *next; struct _xmlCatalogEntry *parent; struct _xmlCatalogEntry *children; xmlCatalogEntryType type; xmlChar *name; xmlChar *value; xmlChar *URL; /* The expanded URL using the base */ xmlCatalogPrefer prefer; int dealloc; int depth;};typedef enum { XML_XML_CATALOG_TYPE = 1, XML_SGML_CATALOG_TYPE} xmlCatalogType;#define XML_MAX_SGML_CATA_DEPTH 10struct _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 * * * ************************************************************************//* * Those are preferences */static int xmlDebugCatalogs = 0; /* used for debugging */static xmlCatalogAllow xmlCatalogDefaultAllow = XML_CATA_ALLOW_ALL;static xmlCatalogPrefer xmlCatalogDefaultPrefer = XML_CATA_PREFER_PUBLIC;/* * Hash table containing all the trees of XML catalogs parsed by * the application. */static xmlHashTablePtr xmlCatalogXMLFiles = NULL;/* * The default catalog in use by the application */static xmlCatalogPtr xmlDefaultCatalog = NULL;/* * A mutex for modifying the shared global catalog(s) * xmlDefaultCatalog tree. * It also protects xmlCatalogXMLFiles * The core of this readers/writer scheme is in xmlFetchXMLCatalogFile() */static xmlRMutexPtr xmlCatalogMutex = NULL;/* * Whether the catalog support was initialized. */static int xmlCatalogInitialized = 0;/************************************************************************ * * * Catalog error handlers * * * ************************************************************************//** * xmlCatalogErrMemory: * @extra: extra informations * * Handle an out of memory condition */static voidxmlCatalogErrMemory(const char *extra){ __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_CATALOG, XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, extra, NULL, NULL, 0, 0, "Memory allocation failed : %s\n", extra);}/** * xmlCatalogErr: * @catal: the Catalog entry * @node: the context node * @msg: the error message * @extra: extra informations * * Handle a catalog error */static voidxmlCatalogErr(xmlCatalogEntryPtr catal, xmlNodePtr node, int error, const char *msg, const xmlChar *str1, const xmlChar *str2, const xmlChar *str3){ __xmlRaiseError(NULL, NULL, NULL, catal, node, XML_FROM_CATALOG, error, XML_ERR_ERROR, NULL, 0, (const char *) str1, (const char *) str2, (const char *) str3, 0, 0, msg, str1, str2, str3);}/************************************************************************ * * * 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 xmlCatalogEntryPtrxmlNewCatalogEntry(xmlCatalogEntryType type, const xmlChar *name, const xmlChar *value, const xmlChar *URL, xmlCatalogPrefer prefer) { xmlCatalogEntryPtr ret; ret = (xmlCatalogEntryPtr) xmlMalloc(sizeof(xmlCatalogEntry)); if (ret == NULL) { xmlCatalogErrMemory("allocating catalog entry"); return(NULL); } ret->next = NULL; ret->parent = NULL; ret->children = NULL; ret->type = type; if (name != NULL) ret->name = xmlStrdup(name); else ret->name = NULL; if (value != NULL) ret->value = xmlStrdup(value); else ret->value = NULL; if (URL == NULL) URL = value; if (URL != NULL) ret->URL = xmlStrdup(URL); else ret->URL = NULL; ret->prefer = prefer; ret->dealloc = 0; ret->depth = 0; return(ret);}static voidxmlFreeCatalogEntryList(xmlCatalogEntryPtr ret);/** * xmlFreeCatalogEntry: * @ret: a Catalog entry * * Free the memory allocated to a Catalog entry */static voidxmlFreeCatalogEntry(xmlCatalogEntryPtr ret) { if (ret == NULL) return; /* * Entries stored in the file hash must be deallocated * only by the file hash cleaner ! */ if (ret->dealloc == 1) return; if (xmlDebugCatalogs) { if (ret->name != NULL) xmlGenericError(xmlGenericErrorContext, "Free catalog entry %s\n", ret->name); else if (ret->value != NULL) xmlGenericError(xmlGenericErrorContext, "Free catalog entry %s\n", ret->value); else xmlGenericError(xmlGenericErrorContext, "Free catalog entry\n"); } if (ret->name != NULL) xmlFree(ret->name); if (ret->value != NULL) xmlFree(ret->value); if (ret->URL != NULL) xmlFree(ret->URL); xmlFree(ret);}/** * xmlFreeCatalogEntryList: * @ret: a Catalog entry list * * Free the memory allocated to a full chained list of Catalog entries */static voidxmlFreeCatalogEntryList(xmlCatalogEntryPtr ret) { xmlCatalogEntryPtr next; while (ret != NULL) { next = ret->next; xmlFreeCatalogEntry(ret); ret = next; }}/** * xmlFreeCatalogHashEntryList: * @ret: a Catalog entry list * * Free the memory allocated to list of Catalog entries from the * catalog file hash. */static voidxmlFreeCatalogHashEntryList(xmlCatalogEntryPtr catal) { xmlCatalogEntryPtr children, next; if (catal == NULL) return; children = catal->children; while (children != NULL) { next = children->next; children->dealloc = 0; children->children = NULL; xmlFreeCatalogEntry(children); children = next; } catal->dealloc = 0; xmlFreeCatalogEntry(catal);}/** * xmlCreateNewCatalog: * @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 xmlCatalogPtrxmlCreateNewCatalog(xmlCatalogType type, xmlCatalogPrefer prefer) { xmlCatalogPtr ret; ret = (xmlCatalogPtr) xmlMalloc(sizeof(xmlCatalog)); if (ret == NULL) { xmlCatalogErrMemory("allocating catalog"); return(NULL); } memset(ret, 0, sizeof(xmlCatalog)); ret->type = type; ret->catalNr = 0; ret->catalMax = XML_MAX_SGML_CATA_DEPTH; ret->prefer = prefer; if (ret->type == XML_SGML_CATALOG_TYPE) ret->sgml = xmlHashCreate(10); return(ret);}/** * xmlFreeCatalog: * @catal: a Catalog * * Free the memory allocated to a Catalog */voidxmlFreeCatalog(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 * * * ************************************************************************/#ifdef LIBXML_OUTPUT_ENABLED/** * xmlCatalogDumpEntry: * @entry: the catalog entry * @out: the file. * * Serialize an SGML Catalog entry */static voidxmlCatalogDumpEntry(xmlCatalogEntryPtr entry, FILE *out) { if ((entry == NULL) || (out == NULL)) return; switch (entry->type) { case SGML_CATA_ENTITY: fprintf(out, "ENTITY "); break; case SGML_CATA_PENTITY: fprintf(out, "ENTITY %%"); break; case SGML_CATA_DOCTYPE: fprintf(out, "DOCTYPE "); break; case SGML_CATA_LINKTYPE: fprintf(out, "LINKTYPE "); break; case SGML_CATA_NOTATION: fprintf(out, "NOTATION "); break; case SGML_CATA_PUBLIC: fprintf(out, "PUBLIC "); break; case SGML_CATA_SYSTEM: fprintf(out, "SYSTEM "); break; case SGML_CATA_DELEGATE: fprintf(out, "DELEGATE "); break; case SGML_CATA_BASE: fprintf(out, "BASE "); break; case SGML_CATA_CATALOG: fprintf(out, "CATALOG "); break; case SGML_CATA_DOCUMENT: fprintf(out, "DOCUMENT "); break; case SGML_CATA_SGMLDECL: fprintf(out, "SGMLDECL "); break; default: return; } switch (entry->type) { case SGML_CATA_ENTITY: case SGML_CATA_PENTITY: case SGML_CATA_DOCTYPE: case SGML_CATA_LINKTYPE: case SGML_CATA_NOTATION: fprintf(out, "%s", (const char *) entry->name); break; case SGML_CATA_PUBLIC: case SGML_CATA_SYSTEM: case SGML_CATA_SGMLDECL: case SGML_CATA_DOCUMENT: case SGML_CATA_CATALOG: case SGML_CATA_BASE: case SGML_CATA_DELEGATE: fprintf(out, "\"%s\"", entry->name); break; default: break; } switch (entry->type) { case SGML_CATA_ENTITY: case SGML_CATA_PENTITY: case SGML_CATA_DOCTYPE: case SGML_CATA_LINKTYPE: case SGML_CATA_NOTATION: case SGML_CATA_PUBLIC: case SGML_CATA_SYSTEM: case SGML_CATA_DELEGATE: fprintf(out, " \"%s\"", entry->value); break; default: break; } fprintf(out, "\n");}static intxmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) { int ret; xmlDocPtr doc; xmlNsPtr ns; xmlDtdPtr dtd; xmlNodePtr node, catalog; xmlOutputBufferPtr buf; xmlCatalogEntryPtr cur;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -