1c2c66affSColin Finck /**
2c2c66affSColin Finck * catalog.c: set of generic Catalog related routines
3c2c66affSColin Finck *
4c2c66affSColin Finck * Reference: SGML Open Technical Resolution TR9401:1997.
5c2c66affSColin Finck * http://www.jclark.com/sp/catalog.htm
6c2c66affSColin Finck *
7c2c66affSColin Finck * XML Catalogs Working Draft 06 August 2001
8c2c66affSColin Finck * http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
9c2c66affSColin Finck *
10c2c66affSColin Finck * See Copyright for the status of this software.
11c2c66affSColin Finck *
12c2c66affSColin Finck * Daniel.Veillard@imag.fr
13c2c66affSColin Finck */
14c2c66affSColin Finck
15c2c66affSColin Finck #define IN_LIBXML
16c2c66affSColin Finck #include "libxml.h"
17c2c66affSColin Finck
18c2c66affSColin Finck #ifdef LIBXML_CATALOG_ENABLED
19*911153daSThomas Faber #include <stdlib.h>
20*911153daSThomas Faber #include <string.h>
21c2c66affSColin Finck #ifdef HAVE_SYS_TYPES_H
22c2c66affSColin Finck #include <sys/types.h>
23c2c66affSColin Finck #endif
24c2c66affSColin Finck #ifdef HAVE_SYS_STAT_H
25c2c66affSColin Finck #include <sys/stat.h>
26c2c66affSColin Finck #endif
27c2c66affSColin Finck #ifdef HAVE_UNISTD_H
28c2c66affSColin Finck #include <unistd.h>
29c2c66affSColin Finck #endif
30c2c66affSColin Finck #ifdef HAVE_FCNTL_H
31c2c66affSColin Finck #include <fcntl.h>
32c2c66affSColin Finck #endif
33c2c66affSColin Finck #include <libxml/xmlmemory.h>
34c2c66affSColin Finck #include <libxml/hash.h>
35c2c66affSColin Finck #include <libxml/uri.h>
36c2c66affSColin Finck #include <libxml/parserInternals.h>
37c2c66affSColin Finck #include <libxml/catalog.h>
38c2c66affSColin Finck #include <libxml/xmlerror.h>
39c2c66affSColin Finck #include <libxml/threads.h>
40c2c66affSColin Finck #include <libxml/globals.h>
41c2c66affSColin Finck
42c2c66affSColin Finck #include "buf.h"
43c2c66affSColin Finck
44c2c66affSColin Finck #define MAX_DELEGATE 50
45c2c66affSColin Finck #define MAX_CATAL_DEPTH 50
46c2c66affSColin Finck
47c2c66affSColin Finck #ifdef _WIN32
48c2c66affSColin Finck # define PATH_SEPARATOR ';'
49c2c66affSColin Finck #else
50c2c66affSColin Finck # define PATH_SEPARATOR ':'
51c2c66affSColin Finck #endif
52c2c66affSColin Finck
53c2c66affSColin Finck /**
54c2c66affSColin Finck * TODO:
55c2c66affSColin Finck *
56c2c66affSColin Finck * macro to flag unimplemented blocks
57f22fa382SThomas Faber * XML_CATALOG_PREFER user env to select between system/public preferred
58c2c66affSColin Finck * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk>
59c2c66affSColin Finck *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
60c2c66affSColin Finck *> values "system" and "public". I have made the default be "system" to
61c2c66affSColin Finck *> match yours.
62c2c66affSColin Finck */
63c2c66affSColin Finck #define TODO \
64c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext, \
65c2c66affSColin Finck "Unimplemented block at %s:%d\n", \
66c2c66affSColin Finck __FILE__, __LINE__);
67c2c66affSColin Finck
68c2c66affSColin Finck #define XML_URN_PUBID "urn:publicid:"
69c2c66affSColin Finck #define XML_CATAL_BREAK ((xmlChar *) -1)
70c2c66affSColin Finck #ifndef XML_XML_DEFAULT_CATALOG
71*911153daSThomas Faber #define XML_XML_DEFAULT_CATALOG "file://" SYSCONFDIR "/xml/catalog"
72c2c66affSColin Finck #endif
73c2c66affSColin Finck #ifndef XML_SGML_DEFAULT_CATALOG
74*911153daSThomas Faber #define XML_SGML_DEFAULT_CATALOG "file://" SYSCONFDIR "/sgml/catalog"
75c2c66affSColin Finck #endif
76c2c66affSColin Finck
77c2c66affSColin Finck #if defined(_WIN32) && defined(_MSC_VER)
78c2c66affSColin Finck #undef XML_XML_DEFAULT_CATALOG
79*911153daSThomas Faber static char XML_XML_DEFAULT_CATALOG[256] = "file://" SYSCONFDIR "/xml/catalog";
80c2c66affSColin Finck #if !defined(_WINDOWS_)
81c2c66affSColin Finck void* __stdcall GetModuleHandleA(const char*);
82c2c66affSColin Finck unsigned long __stdcall GetModuleFileNameA(void*, char*, unsigned long);
83c2c66affSColin Finck #endif
84c2c66affSColin Finck #endif
85c2c66affSColin Finck
86c2c66affSColin Finck static xmlChar *xmlCatalogNormalizePublic(const xmlChar *pubID);
87c2c66affSColin Finck static int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename);
88c2c66affSColin Finck
89c2c66affSColin Finck /************************************************************************
90c2c66affSColin Finck * *
91c2c66affSColin Finck * Types, all private *
92c2c66affSColin Finck * *
93c2c66affSColin Finck ************************************************************************/
94c2c66affSColin Finck
95c2c66affSColin Finck typedef enum {
96c2c66affSColin Finck XML_CATA_REMOVED = -1,
97c2c66affSColin Finck XML_CATA_NONE = 0,
98c2c66affSColin Finck XML_CATA_CATALOG,
99c2c66affSColin Finck XML_CATA_BROKEN_CATALOG,
100c2c66affSColin Finck XML_CATA_NEXT_CATALOG,
101c2c66affSColin Finck XML_CATA_GROUP,
102c2c66affSColin Finck XML_CATA_PUBLIC,
103c2c66affSColin Finck XML_CATA_SYSTEM,
104c2c66affSColin Finck XML_CATA_REWRITE_SYSTEM,
105c2c66affSColin Finck XML_CATA_DELEGATE_PUBLIC,
106c2c66affSColin Finck XML_CATA_DELEGATE_SYSTEM,
107c2c66affSColin Finck XML_CATA_URI,
108c2c66affSColin Finck XML_CATA_REWRITE_URI,
109c2c66affSColin Finck XML_CATA_DELEGATE_URI,
110c2c66affSColin Finck SGML_CATA_SYSTEM,
111c2c66affSColin Finck SGML_CATA_PUBLIC,
112c2c66affSColin Finck SGML_CATA_ENTITY,
113c2c66affSColin Finck SGML_CATA_PENTITY,
114c2c66affSColin Finck SGML_CATA_DOCTYPE,
115c2c66affSColin Finck SGML_CATA_LINKTYPE,
116c2c66affSColin Finck SGML_CATA_NOTATION,
117c2c66affSColin Finck SGML_CATA_DELEGATE,
118c2c66affSColin Finck SGML_CATA_BASE,
119c2c66affSColin Finck SGML_CATA_CATALOG,
120c2c66affSColin Finck SGML_CATA_DOCUMENT,
121c2c66affSColin Finck SGML_CATA_SGMLDECL
122c2c66affSColin Finck } xmlCatalogEntryType;
123c2c66affSColin Finck
124c2c66affSColin Finck typedef struct _xmlCatalogEntry xmlCatalogEntry;
125c2c66affSColin Finck typedef xmlCatalogEntry *xmlCatalogEntryPtr;
126c2c66affSColin Finck struct _xmlCatalogEntry {
127c2c66affSColin Finck struct _xmlCatalogEntry *next;
128c2c66affSColin Finck struct _xmlCatalogEntry *parent;
129c2c66affSColin Finck struct _xmlCatalogEntry *children;
130c2c66affSColin Finck xmlCatalogEntryType type;
131c2c66affSColin Finck xmlChar *name;
132c2c66affSColin Finck xmlChar *value;
133c2c66affSColin Finck xmlChar *URL; /* The expanded URL using the base */
134c2c66affSColin Finck xmlCatalogPrefer prefer;
135c2c66affSColin Finck int dealloc;
136c2c66affSColin Finck int depth;
137c2c66affSColin Finck struct _xmlCatalogEntry *group;
138c2c66affSColin Finck };
139c2c66affSColin Finck
140c2c66affSColin Finck typedef enum {
141c2c66affSColin Finck XML_XML_CATALOG_TYPE = 1,
142c2c66affSColin Finck XML_SGML_CATALOG_TYPE
143c2c66affSColin Finck } xmlCatalogType;
144c2c66affSColin Finck
145c2c66affSColin Finck #define XML_MAX_SGML_CATA_DEPTH 10
146c2c66affSColin Finck struct _xmlCatalog {
147c2c66affSColin Finck xmlCatalogType type; /* either XML or SGML */
148c2c66affSColin Finck
149c2c66affSColin Finck /*
150c2c66affSColin Finck * SGML Catalogs are stored as a simple hash table of catalog entries
151c2c66affSColin Finck * Catalog stack to check against overflows when building the
152c2c66affSColin Finck * SGML catalog
153c2c66affSColin Finck */
154c2c66affSColin Finck char *catalTab[XML_MAX_SGML_CATA_DEPTH]; /* stack of catals */
155c2c66affSColin Finck int catalNr; /* Number of current catal streams */
156c2c66affSColin Finck int catalMax; /* Max number of catal streams */
157c2c66affSColin Finck xmlHashTablePtr sgml;
158c2c66affSColin Finck
159c2c66affSColin Finck /*
160c2c66affSColin Finck * XML Catalogs are stored as a tree of Catalog entries
161c2c66affSColin Finck */
162c2c66affSColin Finck xmlCatalogPrefer prefer;
163c2c66affSColin Finck xmlCatalogEntryPtr xml;
164c2c66affSColin Finck };
165c2c66affSColin Finck
166c2c66affSColin Finck /************************************************************************
167c2c66affSColin Finck * *
168c2c66affSColin Finck * Global variables *
169c2c66affSColin Finck * *
170c2c66affSColin Finck ************************************************************************/
171c2c66affSColin Finck
172c2c66affSColin Finck /*
173c2c66affSColin Finck * Those are preferences
174c2c66affSColin Finck */
175c2c66affSColin Finck static int xmlDebugCatalogs = 0; /* used for debugging */
176c2c66affSColin Finck static xmlCatalogAllow xmlCatalogDefaultAllow = XML_CATA_ALLOW_ALL;
177c2c66affSColin Finck static xmlCatalogPrefer xmlCatalogDefaultPrefer = XML_CATA_PREFER_PUBLIC;
178c2c66affSColin Finck
179c2c66affSColin Finck /*
180c2c66affSColin Finck * Hash table containing all the trees of XML catalogs parsed by
181c2c66affSColin Finck * the application.
182c2c66affSColin Finck */
183c2c66affSColin Finck static xmlHashTablePtr xmlCatalogXMLFiles = NULL;
184c2c66affSColin Finck
185c2c66affSColin Finck /*
186c2c66affSColin Finck * The default catalog in use by the application
187c2c66affSColin Finck */
188c2c66affSColin Finck static xmlCatalogPtr xmlDefaultCatalog = NULL;
189c2c66affSColin Finck
190c2c66affSColin Finck /*
191c2c66affSColin Finck * A mutex for modifying the shared global catalog(s)
192c2c66affSColin Finck * xmlDefaultCatalog tree.
193c2c66affSColin Finck * It also protects xmlCatalogXMLFiles
194c2c66affSColin Finck * The core of this readers/writer scheme is in xmlFetchXMLCatalogFile()
195c2c66affSColin Finck */
196c2c66affSColin Finck static xmlRMutexPtr xmlCatalogMutex = NULL;
197c2c66affSColin Finck
198c2c66affSColin Finck /*
199c2c66affSColin Finck * Whether the catalog support was initialized.
200c2c66affSColin Finck */
201c2c66affSColin Finck static int xmlCatalogInitialized = 0;
202c2c66affSColin Finck
203c2c66affSColin Finck /************************************************************************
204c2c66affSColin Finck * *
205c2c66affSColin Finck * Catalog error handlers *
206c2c66affSColin Finck * *
207c2c66affSColin Finck ************************************************************************/
208c2c66affSColin Finck
209c2c66affSColin Finck /**
210c2c66affSColin Finck * xmlCatalogErrMemory:
21140ee59d6SThomas Faber * @extra: extra information
212c2c66affSColin Finck *
213c2c66affSColin Finck * Handle an out of memory condition
214c2c66affSColin Finck */
215c2c66affSColin Finck static void
xmlCatalogErrMemory(const char * extra)216c2c66affSColin Finck xmlCatalogErrMemory(const char *extra)
217c2c66affSColin Finck {
218c2c66affSColin Finck __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_CATALOG,
219c2c66affSColin Finck XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0,
220c2c66affSColin Finck extra, NULL, NULL, 0, 0,
221c2c66affSColin Finck "Memory allocation failed : %s\n", extra);
222c2c66affSColin Finck }
223c2c66affSColin Finck
224c2c66affSColin Finck /**
225c2c66affSColin Finck * xmlCatalogErr:
226c2c66affSColin Finck * @catal: the Catalog entry
227c2c66affSColin Finck * @node: the context node
228c2c66affSColin Finck * @msg: the error message
22940ee59d6SThomas Faber * @extra: extra information
230c2c66affSColin Finck *
231c2c66affSColin Finck * Handle a catalog error
232c2c66affSColin Finck */
233c2c66affSColin Finck static void LIBXML_ATTR_FORMAT(4,0)
xmlCatalogErr(xmlCatalogEntryPtr catal,xmlNodePtr node,int error,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)234c2c66affSColin Finck xmlCatalogErr(xmlCatalogEntryPtr catal, xmlNodePtr node, int error,
235c2c66affSColin Finck const char *msg, const xmlChar *str1, const xmlChar *str2,
236c2c66affSColin Finck const xmlChar *str3)
237c2c66affSColin Finck {
238c2c66affSColin Finck __xmlRaiseError(NULL, NULL, NULL, catal, node, XML_FROM_CATALOG,
239c2c66affSColin Finck error, XML_ERR_ERROR, NULL, 0,
240c2c66affSColin Finck (const char *) str1, (const char *) str2,
241c2c66affSColin Finck (const char *) str3, 0, 0,
242c2c66affSColin Finck msg, str1, str2, str3);
243c2c66affSColin Finck }
244c2c66affSColin Finck
245c2c66affSColin Finck
246c2c66affSColin Finck /************************************************************************
247c2c66affSColin Finck * *
248c2c66affSColin Finck * Allocation and Freeing *
249c2c66affSColin Finck * *
250c2c66affSColin Finck ************************************************************************/
251c2c66affSColin Finck
252c2c66affSColin Finck /**
253c2c66affSColin Finck * xmlNewCatalogEntry:
254c2c66affSColin Finck * @type: type of entry
255c2c66affSColin Finck * @name: name of the entry
256c2c66affSColin Finck * @value: value of the entry
257c2c66affSColin Finck * @prefer: the PUBLIC vs. SYSTEM current preference value
258c2c66affSColin Finck * @group: for members of a group, the group entry
259c2c66affSColin Finck *
260c2c66affSColin Finck * create a new Catalog entry, this type is shared both by XML and
261c2c66affSColin Finck * SGML catalogs, but the acceptable types values differs.
262c2c66affSColin Finck *
263c2c66affSColin Finck * Returns the xmlCatalogEntryPtr or NULL in case of error
264c2c66affSColin Finck */
265c2c66affSColin Finck static xmlCatalogEntryPtr
xmlNewCatalogEntry(xmlCatalogEntryType type,const xmlChar * name,const xmlChar * value,const xmlChar * URL,xmlCatalogPrefer prefer,xmlCatalogEntryPtr group)266c2c66affSColin Finck xmlNewCatalogEntry(xmlCatalogEntryType type, const xmlChar *name,
267c2c66affSColin Finck const xmlChar *value, const xmlChar *URL, xmlCatalogPrefer prefer,
268c2c66affSColin Finck xmlCatalogEntryPtr group) {
269c2c66affSColin Finck xmlCatalogEntryPtr ret;
270c2c66affSColin Finck xmlChar *normid = NULL;
271c2c66affSColin Finck
272c2c66affSColin Finck ret = (xmlCatalogEntryPtr) xmlMalloc(sizeof(xmlCatalogEntry));
273c2c66affSColin Finck if (ret == NULL) {
274c2c66affSColin Finck xmlCatalogErrMemory("allocating catalog entry");
275c2c66affSColin Finck return(NULL);
276c2c66affSColin Finck }
277c2c66affSColin Finck ret->next = NULL;
278c2c66affSColin Finck ret->parent = NULL;
279c2c66affSColin Finck ret->children = NULL;
280c2c66affSColin Finck ret->type = type;
281c2c66affSColin Finck if (type == XML_CATA_PUBLIC || type == XML_CATA_DELEGATE_PUBLIC) {
282c2c66affSColin Finck normid = xmlCatalogNormalizePublic(name);
283c2c66affSColin Finck if (normid != NULL)
284c2c66affSColin Finck name = (*normid != 0 ? normid : NULL);
285c2c66affSColin Finck }
286c2c66affSColin Finck if (name != NULL)
287c2c66affSColin Finck ret->name = xmlStrdup(name);
288c2c66affSColin Finck else
289c2c66affSColin Finck ret->name = NULL;
290c2c66affSColin Finck if (normid != NULL)
291c2c66affSColin Finck xmlFree(normid);
292c2c66affSColin Finck if (value != NULL)
293c2c66affSColin Finck ret->value = xmlStrdup(value);
294c2c66affSColin Finck else
295c2c66affSColin Finck ret->value = NULL;
296c2c66affSColin Finck if (URL == NULL)
297c2c66affSColin Finck URL = value;
298c2c66affSColin Finck if (URL != NULL)
299c2c66affSColin Finck ret->URL = xmlStrdup(URL);
300c2c66affSColin Finck else
301c2c66affSColin Finck ret->URL = NULL;
302c2c66affSColin Finck ret->prefer = prefer;
303c2c66affSColin Finck ret->dealloc = 0;
304c2c66affSColin Finck ret->depth = 0;
305c2c66affSColin Finck ret->group = group;
306c2c66affSColin Finck return(ret);
307c2c66affSColin Finck }
308c2c66affSColin Finck
309c2c66affSColin Finck static void
310c2c66affSColin Finck xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret);
311c2c66affSColin Finck
312c2c66affSColin Finck /**
313c2c66affSColin Finck * xmlFreeCatalogEntry:
3145bb277a5SThomas Faber * @payload: a Catalog entry
315c2c66affSColin Finck *
316c2c66affSColin Finck * Free the memory allocated to a Catalog entry
317c2c66affSColin Finck */
318c2c66affSColin Finck static void
xmlFreeCatalogEntry(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)3195bb277a5SThomas Faber xmlFreeCatalogEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
3205bb277a5SThomas Faber xmlCatalogEntryPtr ret = (xmlCatalogEntryPtr) payload;
321c2c66affSColin Finck if (ret == NULL)
322c2c66affSColin Finck return;
323c2c66affSColin Finck /*
324c2c66affSColin Finck * Entries stored in the file hash must be deallocated
325c2c66affSColin Finck * only by the file hash cleaner !
326c2c66affSColin Finck */
327c2c66affSColin Finck if (ret->dealloc == 1)
328c2c66affSColin Finck return;
329c2c66affSColin Finck
330c2c66affSColin Finck if (xmlDebugCatalogs) {
331c2c66affSColin Finck if (ret->name != NULL)
332c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
333c2c66affSColin Finck "Free catalog entry %s\n", ret->name);
334c2c66affSColin Finck else if (ret->value != NULL)
335c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
336c2c66affSColin Finck "Free catalog entry %s\n", ret->value);
337c2c66affSColin Finck else
338c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
339c2c66affSColin Finck "Free catalog entry\n");
340c2c66affSColin Finck }
341c2c66affSColin Finck
342c2c66affSColin Finck if (ret->name != NULL)
343c2c66affSColin Finck xmlFree(ret->name);
344c2c66affSColin Finck if (ret->value != NULL)
345c2c66affSColin Finck xmlFree(ret->value);
346c2c66affSColin Finck if (ret->URL != NULL)
347c2c66affSColin Finck xmlFree(ret->URL);
348c2c66affSColin Finck xmlFree(ret);
349c2c66affSColin Finck }
350c2c66affSColin Finck
351c2c66affSColin Finck /**
352c2c66affSColin Finck * xmlFreeCatalogEntryList:
353c2c66affSColin Finck * @ret: a Catalog entry list
354c2c66affSColin Finck *
355c2c66affSColin Finck * Free the memory allocated to a full chained list of Catalog entries
356c2c66affSColin Finck */
357c2c66affSColin Finck static void
xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret)358c2c66affSColin Finck xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret) {
359c2c66affSColin Finck xmlCatalogEntryPtr next;
360c2c66affSColin Finck
361c2c66affSColin Finck while (ret != NULL) {
362c2c66affSColin Finck next = ret->next;
3635bb277a5SThomas Faber xmlFreeCatalogEntry(ret, NULL);
364c2c66affSColin Finck ret = next;
365c2c66affSColin Finck }
366c2c66affSColin Finck }
367c2c66affSColin Finck
368c2c66affSColin Finck /**
369c2c66affSColin Finck * xmlFreeCatalogHashEntryList:
3705bb277a5SThomas Faber * @payload: a Catalog entry list
371c2c66affSColin Finck *
372c2c66affSColin Finck * Free the memory allocated to list of Catalog entries from the
373c2c66affSColin Finck * catalog file hash.
374c2c66affSColin Finck */
375c2c66affSColin Finck static void
xmlFreeCatalogHashEntryList(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)3765bb277a5SThomas Faber xmlFreeCatalogHashEntryList(void *payload,
3775bb277a5SThomas Faber const xmlChar *name ATTRIBUTE_UNUSED) {
3785bb277a5SThomas Faber xmlCatalogEntryPtr catal = (xmlCatalogEntryPtr) payload;
379c2c66affSColin Finck xmlCatalogEntryPtr children, next;
380c2c66affSColin Finck
381c2c66affSColin Finck if (catal == NULL)
382c2c66affSColin Finck return;
383c2c66affSColin Finck
384c2c66affSColin Finck children = catal->children;
385c2c66affSColin Finck while (children != NULL) {
386c2c66affSColin Finck next = children->next;
387c2c66affSColin Finck children->dealloc = 0;
388c2c66affSColin Finck children->children = NULL;
3895bb277a5SThomas Faber xmlFreeCatalogEntry(children, NULL);
390c2c66affSColin Finck children = next;
391c2c66affSColin Finck }
392c2c66affSColin Finck catal->dealloc = 0;
3935bb277a5SThomas Faber xmlFreeCatalogEntry(catal, NULL);
394c2c66affSColin Finck }
395c2c66affSColin Finck
396c2c66affSColin Finck /**
397c2c66affSColin Finck * xmlCreateNewCatalog:
398c2c66affSColin Finck * @type: type of catalog
399c2c66affSColin Finck * @prefer: the PUBLIC vs. SYSTEM current preference value
400c2c66affSColin Finck *
401c2c66affSColin Finck * create a new Catalog, this type is shared both by XML and
402c2c66affSColin Finck * SGML catalogs, but the acceptable types values differs.
403c2c66affSColin Finck *
404c2c66affSColin Finck * Returns the xmlCatalogPtr or NULL in case of error
405c2c66affSColin Finck */
406c2c66affSColin Finck static xmlCatalogPtr
xmlCreateNewCatalog(xmlCatalogType type,xmlCatalogPrefer prefer)407c2c66affSColin Finck xmlCreateNewCatalog(xmlCatalogType type, xmlCatalogPrefer prefer) {
408c2c66affSColin Finck xmlCatalogPtr ret;
409c2c66affSColin Finck
410c2c66affSColin Finck ret = (xmlCatalogPtr) xmlMalloc(sizeof(xmlCatalog));
411c2c66affSColin Finck if (ret == NULL) {
412c2c66affSColin Finck xmlCatalogErrMemory("allocating catalog");
413c2c66affSColin Finck return(NULL);
414c2c66affSColin Finck }
415c2c66affSColin Finck memset(ret, 0, sizeof(xmlCatalog));
416c2c66affSColin Finck ret->type = type;
417c2c66affSColin Finck ret->catalNr = 0;
418c2c66affSColin Finck ret->catalMax = XML_MAX_SGML_CATA_DEPTH;
419c2c66affSColin Finck ret->prefer = prefer;
420c2c66affSColin Finck if (ret->type == XML_SGML_CATALOG_TYPE)
421c2c66affSColin Finck ret->sgml = xmlHashCreate(10);
422c2c66affSColin Finck return(ret);
423c2c66affSColin Finck }
424c2c66affSColin Finck
425c2c66affSColin Finck /**
426c2c66affSColin Finck * xmlFreeCatalog:
427c2c66affSColin Finck * @catal: a Catalog
428c2c66affSColin Finck *
429c2c66affSColin Finck * Free the memory allocated to a Catalog
430c2c66affSColin Finck */
431c2c66affSColin Finck void
xmlFreeCatalog(xmlCatalogPtr catal)432c2c66affSColin Finck xmlFreeCatalog(xmlCatalogPtr catal) {
433c2c66affSColin Finck if (catal == NULL)
434c2c66affSColin Finck return;
435c2c66affSColin Finck if (catal->xml != NULL)
436c2c66affSColin Finck xmlFreeCatalogEntryList(catal->xml);
437c2c66affSColin Finck if (catal->sgml != NULL)
4385bb277a5SThomas Faber xmlHashFree(catal->sgml, xmlFreeCatalogEntry);
439c2c66affSColin Finck xmlFree(catal);
440c2c66affSColin Finck }
441c2c66affSColin Finck
442c2c66affSColin Finck /************************************************************************
443c2c66affSColin Finck * *
444c2c66affSColin Finck * Serializing Catalogs *
445c2c66affSColin Finck * *
446c2c66affSColin Finck ************************************************************************/
447c2c66affSColin Finck
448c2c66affSColin Finck #ifdef LIBXML_OUTPUT_ENABLED
449c2c66affSColin Finck /**
450c2c66affSColin Finck * xmlCatalogDumpEntry:
451c2c66affSColin Finck * @entry: the catalog entry
452c2c66affSColin Finck * @out: the file.
453c2c66affSColin Finck *
454c2c66affSColin Finck * Serialize an SGML Catalog entry
455c2c66affSColin Finck */
456c2c66affSColin Finck static void
xmlCatalogDumpEntry(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)4575bb277a5SThomas Faber xmlCatalogDumpEntry(void *payload, void *data,
4585bb277a5SThomas Faber const xmlChar *name ATTRIBUTE_UNUSED) {
4595bb277a5SThomas Faber xmlCatalogEntryPtr entry = (xmlCatalogEntryPtr) payload;
4605bb277a5SThomas Faber FILE *out = (FILE *) data;
461c2c66affSColin Finck if ((entry == NULL) || (out == NULL))
462c2c66affSColin Finck return;
463c2c66affSColin Finck switch (entry->type) {
464c2c66affSColin Finck case SGML_CATA_ENTITY:
465c2c66affSColin Finck fprintf(out, "ENTITY "); break;
466c2c66affSColin Finck case SGML_CATA_PENTITY:
467c2c66affSColin Finck fprintf(out, "ENTITY %%"); break;
468c2c66affSColin Finck case SGML_CATA_DOCTYPE:
469c2c66affSColin Finck fprintf(out, "DOCTYPE "); break;
470c2c66affSColin Finck case SGML_CATA_LINKTYPE:
471c2c66affSColin Finck fprintf(out, "LINKTYPE "); break;
472c2c66affSColin Finck case SGML_CATA_NOTATION:
473c2c66affSColin Finck fprintf(out, "NOTATION "); break;
474c2c66affSColin Finck case SGML_CATA_PUBLIC:
475c2c66affSColin Finck fprintf(out, "PUBLIC "); break;
476c2c66affSColin Finck case SGML_CATA_SYSTEM:
477c2c66affSColin Finck fprintf(out, "SYSTEM "); break;
478c2c66affSColin Finck case SGML_CATA_DELEGATE:
479c2c66affSColin Finck fprintf(out, "DELEGATE "); break;
480c2c66affSColin Finck case SGML_CATA_BASE:
481c2c66affSColin Finck fprintf(out, "BASE "); break;
482c2c66affSColin Finck case SGML_CATA_CATALOG:
483c2c66affSColin Finck fprintf(out, "CATALOG "); break;
484c2c66affSColin Finck case SGML_CATA_DOCUMENT:
485c2c66affSColin Finck fprintf(out, "DOCUMENT "); break;
486c2c66affSColin Finck case SGML_CATA_SGMLDECL:
487c2c66affSColin Finck fprintf(out, "SGMLDECL "); break;
488c2c66affSColin Finck default:
489c2c66affSColin Finck return;
490c2c66affSColin Finck }
491c2c66affSColin Finck switch (entry->type) {
492c2c66affSColin Finck case SGML_CATA_ENTITY:
493c2c66affSColin Finck case SGML_CATA_PENTITY:
494c2c66affSColin Finck case SGML_CATA_DOCTYPE:
495c2c66affSColin Finck case SGML_CATA_LINKTYPE:
496c2c66affSColin Finck case SGML_CATA_NOTATION:
497c2c66affSColin Finck fprintf(out, "%s", (const char *) entry->name); break;
498c2c66affSColin Finck case SGML_CATA_PUBLIC:
499c2c66affSColin Finck case SGML_CATA_SYSTEM:
500c2c66affSColin Finck case SGML_CATA_SGMLDECL:
501c2c66affSColin Finck case SGML_CATA_DOCUMENT:
502c2c66affSColin Finck case SGML_CATA_CATALOG:
503c2c66affSColin Finck case SGML_CATA_BASE:
504c2c66affSColin Finck case SGML_CATA_DELEGATE:
505c2c66affSColin Finck fprintf(out, "\"%s\"", entry->name); break;
506c2c66affSColin Finck default:
507c2c66affSColin Finck break;
508c2c66affSColin Finck }
509c2c66affSColin Finck switch (entry->type) {
510c2c66affSColin Finck case SGML_CATA_ENTITY:
511c2c66affSColin Finck case SGML_CATA_PENTITY:
512c2c66affSColin Finck case SGML_CATA_DOCTYPE:
513c2c66affSColin Finck case SGML_CATA_LINKTYPE:
514c2c66affSColin Finck case SGML_CATA_NOTATION:
515c2c66affSColin Finck case SGML_CATA_PUBLIC:
516c2c66affSColin Finck case SGML_CATA_SYSTEM:
517c2c66affSColin Finck case SGML_CATA_DELEGATE:
518c2c66affSColin Finck fprintf(out, " \"%s\"", entry->value); break;
519c2c66affSColin Finck default:
520c2c66affSColin Finck break;
521c2c66affSColin Finck }
522c2c66affSColin Finck fprintf(out, "\n");
523c2c66affSColin Finck }
524c2c66affSColin Finck
525c2c66affSColin Finck /**
526c2c66affSColin Finck * xmlDumpXMLCatalogNode:
527c2c66affSColin Finck * @catal: top catalog entry
528c2c66affSColin Finck * @catalog: pointer to the xml tree
529c2c66affSColin Finck * @doc: the containing document
530c2c66affSColin Finck * @ns: the current namespace
531c2c66affSColin Finck * @cgroup: group node for group members
532c2c66affSColin Finck *
533c2c66affSColin Finck * Serializes a Catalog entry, called by xmlDumpXMLCatalog and recursively
534c2c66affSColin Finck * for group entries
535c2c66affSColin Finck */
xmlDumpXMLCatalogNode(xmlCatalogEntryPtr catal,xmlNodePtr catalog,xmlDocPtr doc,xmlNsPtr ns,xmlCatalogEntryPtr cgroup)536c2c66affSColin Finck static void xmlDumpXMLCatalogNode(xmlCatalogEntryPtr catal, xmlNodePtr catalog,
537c2c66affSColin Finck xmlDocPtr doc, xmlNsPtr ns, xmlCatalogEntryPtr cgroup) {
538c2c66affSColin Finck xmlNodePtr node;
539c2c66affSColin Finck xmlCatalogEntryPtr cur;
540c2c66affSColin Finck /*
541c2c66affSColin Finck * add all the catalog entries
542c2c66affSColin Finck */
543c2c66affSColin Finck cur = catal;
544c2c66affSColin Finck while (cur != NULL) {
545c2c66affSColin Finck if (cur->group == cgroup) {
546c2c66affSColin Finck switch (cur->type) {
547c2c66affSColin Finck case XML_CATA_REMOVED:
548c2c66affSColin Finck break;
549c2c66affSColin Finck case XML_CATA_BROKEN_CATALOG:
550c2c66affSColin Finck case XML_CATA_CATALOG:
551c2c66affSColin Finck if (cur == catal) {
552c2c66affSColin Finck cur = cur->children;
553c2c66affSColin Finck continue;
554c2c66affSColin Finck }
555c2c66affSColin Finck break;
556c2c66affSColin Finck case XML_CATA_NEXT_CATALOG:
557c2c66affSColin Finck node = xmlNewDocNode(doc, ns, BAD_CAST "nextCatalog", NULL);
558c2c66affSColin Finck xmlSetProp(node, BAD_CAST "catalog", cur->value);
559c2c66affSColin Finck xmlAddChild(catalog, node);
560c2c66affSColin Finck break;
561c2c66affSColin Finck case XML_CATA_NONE:
562c2c66affSColin Finck break;
563c2c66affSColin Finck case XML_CATA_GROUP:
564c2c66affSColin Finck node = xmlNewDocNode(doc, ns, BAD_CAST "group", NULL);
565c2c66affSColin Finck xmlSetProp(node, BAD_CAST "id", cur->name);
566c2c66affSColin Finck if (cur->value != NULL) {
567c2c66affSColin Finck xmlNsPtr xns;
568c2c66affSColin Finck xns = xmlSearchNsByHref(doc, node, XML_XML_NAMESPACE);
569c2c66affSColin Finck if (xns != NULL)
570c2c66affSColin Finck xmlSetNsProp(node, xns, BAD_CAST "base",
571c2c66affSColin Finck cur->value);
572c2c66affSColin Finck }
573c2c66affSColin Finck switch (cur->prefer) {
574c2c66affSColin Finck case XML_CATA_PREFER_NONE:
575c2c66affSColin Finck break;
576c2c66affSColin Finck case XML_CATA_PREFER_PUBLIC:
577c2c66affSColin Finck xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "public");
578c2c66affSColin Finck break;
579c2c66affSColin Finck case XML_CATA_PREFER_SYSTEM:
580c2c66affSColin Finck xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "system");
581c2c66affSColin Finck break;
582c2c66affSColin Finck }
583c2c66affSColin Finck xmlDumpXMLCatalogNode(cur->next, node, doc, ns, cur);
584c2c66affSColin Finck xmlAddChild(catalog, node);
585c2c66affSColin Finck break;
586c2c66affSColin Finck case XML_CATA_PUBLIC:
587c2c66affSColin Finck node = xmlNewDocNode(doc, ns, BAD_CAST "public", NULL);
588c2c66affSColin Finck xmlSetProp(node, BAD_CAST "publicId", cur->name);
589c2c66affSColin Finck xmlSetProp(node, BAD_CAST "uri", cur->value);
590c2c66affSColin Finck xmlAddChild(catalog, node);
591c2c66affSColin Finck break;
592c2c66affSColin Finck case XML_CATA_SYSTEM:
593c2c66affSColin Finck node = xmlNewDocNode(doc, ns, BAD_CAST "system", NULL);
594c2c66affSColin Finck xmlSetProp(node, BAD_CAST "systemId", cur->name);
595c2c66affSColin Finck xmlSetProp(node, BAD_CAST "uri", cur->value);
596c2c66affSColin Finck xmlAddChild(catalog, node);
597c2c66affSColin Finck break;
598c2c66affSColin Finck case XML_CATA_REWRITE_SYSTEM:
599c2c66affSColin Finck node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteSystem", NULL);
600c2c66affSColin Finck xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
601c2c66affSColin Finck xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
602c2c66affSColin Finck xmlAddChild(catalog, node);
603c2c66affSColin Finck break;
604c2c66affSColin Finck case XML_CATA_DELEGATE_PUBLIC:
605c2c66affSColin Finck node = xmlNewDocNode(doc, ns, BAD_CAST "delegatePublic", NULL);
606c2c66affSColin Finck xmlSetProp(node, BAD_CAST "publicIdStartString", cur->name);
607c2c66affSColin Finck xmlSetProp(node, BAD_CAST "catalog", cur->value);
608c2c66affSColin Finck xmlAddChild(catalog, node);
609c2c66affSColin Finck break;
610c2c66affSColin Finck case XML_CATA_DELEGATE_SYSTEM:
611c2c66affSColin Finck node = xmlNewDocNode(doc, ns, BAD_CAST "delegateSystem", NULL);
612c2c66affSColin Finck xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
613c2c66affSColin Finck xmlSetProp(node, BAD_CAST "catalog", cur->value);
614c2c66affSColin Finck xmlAddChild(catalog, node);
615c2c66affSColin Finck break;
616c2c66affSColin Finck case XML_CATA_URI:
617c2c66affSColin Finck node = xmlNewDocNode(doc, ns, BAD_CAST "uri", NULL);
618c2c66affSColin Finck xmlSetProp(node, BAD_CAST "name", cur->name);
619c2c66affSColin Finck xmlSetProp(node, BAD_CAST "uri", cur->value);
620c2c66affSColin Finck xmlAddChild(catalog, node);
621c2c66affSColin Finck break;
622c2c66affSColin Finck case XML_CATA_REWRITE_URI:
623c2c66affSColin Finck node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteURI", NULL);
624c2c66affSColin Finck xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
625c2c66affSColin Finck xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
626c2c66affSColin Finck xmlAddChild(catalog, node);
627c2c66affSColin Finck break;
628c2c66affSColin Finck case XML_CATA_DELEGATE_URI:
629c2c66affSColin Finck node = xmlNewDocNode(doc, ns, BAD_CAST "delegateURI", NULL);
630c2c66affSColin Finck xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
631c2c66affSColin Finck xmlSetProp(node, BAD_CAST "catalog", cur->value);
632c2c66affSColin Finck xmlAddChild(catalog, node);
633c2c66affSColin Finck break;
634c2c66affSColin Finck case SGML_CATA_SYSTEM:
635c2c66affSColin Finck case SGML_CATA_PUBLIC:
636c2c66affSColin Finck case SGML_CATA_ENTITY:
637c2c66affSColin Finck case SGML_CATA_PENTITY:
638c2c66affSColin Finck case SGML_CATA_DOCTYPE:
639c2c66affSColin Finck case SGML_CATA_LINKTYPE:
640c2c66affSColin Finck case SGML_CATA_NOTATION:
641c2c66affSColin Finck case SGML_CATA_DELEGATE:
642c2c66affSColin Finck case SGML_CATA_BASE:
643c2c66affSColin Finck case SGML_CATA_CATALOG:
644c2c66affSColin Finck case SGML_CATA_DOCUMENT:
645c2c66affSColin Finck case SGML_CATA_SGMLDECL:
646c2c66affSColin Finck break;
647c2c66affSColin Finck }
648c2c66affSColin Finck }
649c2c66affSColin Finck cur = cur->next;
650c2c66affSColin Finck }
651c2c66affSColin Finck }
652c2c66affSColin Finck
653c2c66affSColin Finck static int
xmlDumpXMLCatalog(FILE * out,xmlCatalogEntryPtr catal)654c2c66affSColin Finck xmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) {
655c2c66affSColin Finck int ret;
656c2c66affSColin Finck xmlDocPtr doc;
657c2c66affSColin Finck xmlNsPtr ns;
658c2c66affSColin Finck xmlDtdPtr dtd;
659c2c66affSColin Finck xmlNodePtr catalog;
660c2c66affSColin Finck xmlOutputBufferPtr buf;
661c2c66affSColin Finck
662c2c66affSColin Finck /*
663c2c66affSColin Finck * Rebuild a catalog
664c2c66affSColin Finck */
665c2c66affSColin Finck doc = xmlNewDoc(NULL);
666c2c66affSColin Finck if (doc == NULL)
667c2c66affSColin Finck return(-1);
668c2c66affSColin Finck dtd = xmlNewDtd(doc, BAD_CAST "catalog",
669c2c66affSColin Finck BAD_CAST "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN",
670c2c66affSColin Finck BAD_CAST "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd");
671c2c66affSColin Finck
672c2c66affSColin Finck xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd);
673c2c66affSColin Finck
674c2c66affSColin Finck ns = xmlNewNs(NULL, XML_CATALOGS_NAMESPACE, NULL);
675c2c66affSColin Finck if (ns == NULL) {
676c2c66affSColin Finck xmlFreeDoc(doc);
677c2c66affSColin Finck return(-1);
678c2c66affSColin Finck }
679c2c66affSColin Finck catalog = xmlNewDocNode(doc, ns, BAD_CAST "catalog", NULL);
680c2c66affSColin Finck if (catalog == NULL) {
681c2c66affSColin Finck xmlFreeNs(ns);
682c2c66affSColin Finck xmlFreeDoc(doc);
683c2c66affSColin Finck return(-1);
684c2c66affSColin Finck }
685c2c66affSColin Finck catalog->nsDef = ns;
686c2c66affSColin Finck xmlAddChild((xmlNodePtr) doc, catalog);
687c2c66affSColin Finck
688c2c66affSColin Finck xmlDumpXMLCatalogNode(catal, catalog, doc, ns, NULL);
689c2c66affSColin Finck
690c2c66affSColin Finck /*
691c2c66affSColin Finck * reserialize it
692c2c66affSColin Finck */
693c2c66affSColin Finck buf = xmlOutputBufferCreateFile(out, NULL);
694c2c66affSColin Finck if (buf == NULL) {
695c2c66affSColin Finck xmlFreeDoc(doc);
696c2c66affSColin Finck return(-1);
697c2c66affSColin Finck }
698c2c66affSColin Finck ret = xmlSaveFormatFileTo(buf, doc, NULL, 1);
699c2c66affSColin Finck
700c2c66affSColin Finck /*
701c2c66affSColin Finck * Free it
702c2c66affSColin Finck */
703c2c66affSColin Finck xmlFreeDoc(doc);
704c2c66affSColin Finck
705c2c66affSColin Finck return(ret);
706c2c66affSColin Finck }
707c2c66affSColin Finck #endif /* LIBXML_OUTPUT_ENABLED */
708c2c66affSColin Finck
709c2c66affSColin Finck /************************************************************************
710c2c66affSColin Finck * *
711c2c66affSColin Finck * Converting SGML Catalogs to XML *
712c2c66affSColin Finck * *
713c2c66affSColin Finck ************************************************************************/
714c2c66affSColin Finck
715c2c66affSColin Finck /**
716c2c66affSColin Finck * xmlCatalogConvertEntry:
717c2c66affSColin Finck * @entry: the entry
718c2c66affSColin Finck * @catal: pointer to the catalog being converted
719c2c66affSColin Finck *
720c2c66affSColin Finck * Convert one entry from the catalog
721c2c66affSColin Finck */
722c2c66affSColin Finck static void
xmlCatalogConvertEntry(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)7235bb277a5SThomas Faber xmlCatalogConvertEntry(void *payload, void *data,
7245bb277a5SThomas Faber const xmlChar *name ATTRIBUTE_UNUSED) {
7255bb277a5SThomas Faber xmlCatalogEntryPtr entry = (xmlCatalogEntryPtr) payload;
7265bb277a5SThomas Faber xmlCatalogPtr catal = (xmlCatalogPtr) data;
727c2c66affSColin Finck if ((entry == NULL) || (catal == NULL) || (catal->sgml == NULL) ||
728c2c66affSColin Finck (catal->xml == NULL))
729c2c66affSColin Finck return;
730c2c66affSColin Finck switch (entry->type) {
731c2c66affSColin Finck case SGML_CATA_ENTITY:
732c2c66affSColin Finck entry->type = XML_CATA_PUBLIC;
733c2c66affSColin Finck break;
734c2c66affSColin Finck case SGML_CATA_PENTITY:
735c2c66affSColin Finck entry->type = XML_CATA_PUBLIC;
736c2c66affSColin Finck break;
737c2c66affSColin Finck case SGML_CATA_DOCTYPE:
738c2c66affSColin Finck entry->type = XML_CATA_PUBLIC;
739c2c66affSColin Finck break;
740c2c66affSColin Finck case SGML_CATA_LINKTYPE:
741c2c66affSColin Finck entry->type = XML_CATA_PUBLIC;
742c2c66affSColin Finck break;
743c2c66affSColin Finck case SGML_CATA_NOTATION:
744c2c66affSColin Finck entry->type = XML_CATA_PUBLIC;
745c2c66affSColin Finck break;
746c2c66affSColin Finck case SGML_CATA_PUBLIC:
747c2c66affSColin Finck entry->type = XML_CATA_PUBLIC;
748c2c66affSColin Finck break;
749c2c66affSColin Finck case SGML_CATA_SYSTEM:
750c2c66affSColin Finck entry->type = XML_CATA_SYSTEM;
751c2c66affSColin Finck break;
752c2c66affSColin Finck case SGML_CATA_DELEGATE:
753c2c66affSColin Finck entry->type = XML_CATA_DELEGATE_PUBLIC;
754c2c66affSColin Finck break;
755c2c66affSColin Finck case SGML_CATA_CATALOG:
756c2c66affSColin Finck entry->type = XML_CATA_CATALOG;
757c2c66affSColin Finck break;
758c2c66affSColin Finck default:
7595bb277a5SThomas Faber xmlHashRemoveEntry(catal->sgml, entry->name, xmlFreeCatalogEntry);
760c2c66affSColin Finck return;
761c2c66affSColin Finck }
762c2c66affSColin Finck /*
763c2c66affSColin Finck * Conversion successful, remove from the SGML catalog
764c2c66affSColin Finck * and add it to the default XML one
765c2c66affSColin Finck */
766c2c66affSColin Finck xmlHashRemoveEntry(catal->sgml, entry->name, NULL);
767c2c66affSColin Finck entry->parent = catal->xml;
768c2c66affSColin Finck entry->next = NULL;
769c2c66affSColin Finck if (catal->xml->children == NULL)
770c2c66affSColin Finck catal->xml->children = entry;
771c2c66affSColin Finck else {
772c2c66affSColin Finck xmlCatalogEntryPtr prev;
773c2c66affSColin Finck
774c2c66affSColin Finck prev = catal->xml->children;
775c2c66affSColin Finck while (prev->next != NULL)
776c2c66affSColin Finck prev = prev->next;
777c2c66affSColin Finck prev->next = entry;
778c2c66affSColin Finck }
779c2c66affSColin Finck }
780c2c66affSColin Finck
781c2c66affSColin Finck /**
782c2c66affSColin Finck * xmlConvertSGMLCatalog:
783c2c66affSColin Finck * @catal: the catalog
784c2c66affSColin Finck *
785c2c66affSColin Finck * Convert all the SGML catalog entries as XML ones
786c2c66affSColin Finck *
787c2c66affSColin Finck * Returns the number of entries converted if successful, -1 otherwise
788c2c66affSColin Finck */
789c2c66affSColin Finck int
xmlConvertSGMLCatalog(xmlCatalogPtr catal)790c2c66affSColin Finck xmlConvertSGMLCatalog(xmlCatalogPtr catal) {
791c2c66affSColin Finck
792c2c66affSColin Finck if ((catal == NULL) || (catal->type != XML_SGML_CATALOG_TYPE))
793c2c66affSColin Finck return(-1);
794c2c66affSColin Finck
795c2c66affSColin Finck if (xmlDebugCatalogs) {
796c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
797c2c66affSColin Finck "Converting SGML catalog to XML\n");
798c2c66affSColin Finck }
7995bb277a5SThomas Faber xmlHashScan(catal->sgml, xmlCatalogConvertEntry, &catal);
800c2c66affSColin Finck return(0);
801c2c66affSColin Finck }
802c2c66affSColin Finck
803c2c66affSColin Finck /************************************************************************
804c2c66affSColin Finck * *
805c2c66affSColin Finck * Helper function *
806c2c66affSColin Finck * *
807c2c66affSColin Finck ************************************************************************/
808c2c66affSColin Finck
809c2c66affSColin Finck /**
810c2c66affSColin Finck * xmlCatalogUnWrapURN:
811c2c66affSColin Finck * @urn: an "urn:publicid:" to unwrap
812c2c66affSColin Finck *
813c2c66affSColin Finck * Expand the URN into the equivalent Public Identifier
814c2c66affSColin Finck *
815c2c66affSColin Finck * Returns the new identifier or NULL, the string must be deallocated
816c2c66affSColin Finck * by the caller.
817c2c66affSColin Finck */
818c2c66affSColin Finck static xmlChar *
xmlCatalogUnWrapURN(const xmlChar * urn)819c2c66affSColin Finck xmlCatalogUnWrapURN(const xmlChar *urn) {
820c2c66affSColin Finck xmlChar result[2000];
821c2c66affSColin Finck unsigned int i = 0;
822c2c66affSColin Finck
823c2c66affSColin Finck if (xmlStrncmp(urn, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1))
824c2c66affSColin Finck return(NULL);
825c2c66affSColin Finck urn += sizeof(XML_URN_PUBID) - 1;
826c2c66affSColin Finck
827c2c66affSColin Finck while (*urn != 0) {
828c2c66affSColin Finck if (i > sizeof(result) - 4)
829c2c66affSColin Finck break;
830c2c66affSColin Finck if (*urn == '+') {
831c2c66affSColin Finck result[i++] = ' ';
832c2c66affSColin Finck urn++;
833c2c66affSColin Finck } else if (*urn == ':') {
834c2c66affSColin Finck result[i++] = '/';
835c2c66affSColin Finck result[i++] = '/';
836c2c66affSColin Finck urn++;
837c2c66affSColin Finck } else if (*urn == ';') {
838c2c66affSColin Finck result[i++] = ':';
839c2c66affSColin Finck result[i++] = ':';
840c2c66affSColin Finck urn++;
841c2c66affSColin Finck } else if (*urn == '%') {
842c2c66affSColin Finck if ((urn[1] == '2') && (urn[2] == 'B'))
843c2c66affSColin Finck result[i++] = '+';
844c2c66affSColin Finck else if ((urn[1] == '3') && (urn[2] == 'A'))
845c2c66affSColin Finck result[i++] = ':';
846c2c66affSColin Finck else if ((urn[1] == '2') && (urn[2] == 'F'))
847c2c66affSColin Finck result[i++] = '/';
848c2c66affSColin Finck else if ((urn[1] == '3') && (urn[2] == 'B'))
849c2c66affSColin Finck result[i++] = ';';
850c2c66affSColin Finck else if ((urn[1] == '2') && (urn[2] == '7'))
851c2c66affSColin Finck result[i++] = '\'';
852c2c66affSColin Finck else if ((urn[1] == '3') && (urn[2] == 'F'))
853c2c66affSColin Finck result[i++] = '?';
854c2c66affSColin Finck else if ((urn[1] == '2') && (urn[2] == '3'))
855c2c66affSColin Finck result[i++] = '#';
856c2c66affSColin Finck else if ((urn[1] == '2') && (urn[2] == '5'))
857c2c66affSColin Finck result[i++] = '%';
858c2c66affSColin Finck else {
859c2c66affSColin Finck result[i++] = *urn;
860c2c66affSColin Finck urn++;
861c2c66affSColin Finck continue;
862c2c66affSColin Finck }
863c2c66affSColin Finck urn += 3;
864c2c66affSColin Finck } else {
865c2c66affSColin Finck result[i++] = *urn;
866c2c66affSColin Finck urn++;
867c2c66affSColin Finck }
868c2c66affSColin Finck }
869c2c66affSColin Finck result[i] = 0;
870c2c66affSColin Finck
871c2c66affSColin Finck return(xmlStrdup(result));
872c2c66affSColin Finck }
873c2c66affSColin Finck
874c2c66affSColin Finck /**
875c2c66affSColin Finck * xmlParseCatalogFile:
876c2c66affSColin Finck * @filename: the filename
877c2c66affSColin Finck *
878c2c66affSColin Finck * parse an XML file and build a tree. It's like xmlParseFile()
879c2c66affSColin Finck * except it bypass all catalog lookups.
880c2c66affSColin Finck *
881c2c66affSColin Finck * Returns the resulting document tree or NULL in case of error
882c2c66affSColin Finck */
883c2c66affSColin Finck
884c2c66affSColin Finck xmlDocPtr
xmlParseCatalogFile(const char * filename)885c2c66affSColin Finck xmlParseCatalogFile(const char *filename) {
886c2c66affSColin Finck xmlDocPtr ret;
887c2c66affSColin Finck xmlParserCtxtPtr ctxt;
888c2c66affSColin Finck char *directory = NULL;
889c2c66affSColin Finck xmlParserInputPtr inputStream;
890c2c66affSColin Finck xmlParserInputBufferPtr buf;
891c2c66affSColin Finck
892c2c66affSColin Finck ctxt = xmlNewParserCtxt();
893c2c66affSColin Finck if (ctxt == NULL) {
894c2c66affSColin Finck #ifdef LIBXML_SAX1_ENABLED
895c2c66affSColin Finck if (xmlDefaultSAXHandler.error != NULL) {
896c2c66affSColin Finck xmlDefaultSAXHandler.error(NULL, "out of memory\n");
897c2c66affSColin Finck }
898c2c66affSColin Finck #endif
899c2c66affSColin Finck return(NULL);
900c2c66affSColin Finck }
901c2c66affSColin Finck
902c2c66affSColin Finck buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
903c2c66affSColin Finck if (buf == NULL) {
904c2c66affSColin Finck xmlFreeParserCtxt(ctxt);
905c2c66affSColin Finck return(NULL);
906c2c66affSColin Finck }
907c2c66affSColin Finck
908c2c66affSColin Finck inputStream = xmlNewInputStream(ctxt);
909c2c66affSColin Finck if (inputStream == NULL) {
9107244e0c5SThomas Faber xmlFreeParserInputBuffer(buf);
911c2c66affSColin Finck xmlFreeParserCtxt(ctxt);
912c2c66affSColin Finck return(NULL);
913c2c66affSColin Finck }
914c2c66affSColin Finck
915c2c66affSColin Finck inputStream->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
916c2c66affSColin Finck inputStream->buf = buf;
917c2c66affSColin Finck xmlBufResetInput(buf->buffer, inputStream);
918c2c66affSColin Finck
919c2c66affSColin Finck inputPush(ctxt, inputStream);
92040ee59d6SThomas Faber if (ctxt->directory == NULL)
921c2c66affSColin Finck directory = xmlParserGetDirectory(filename);
922c2c66affSColin Finck if ((ctxt->directory == NULL) && (directory != NULL))
923c2c66affSColin Finck ctxt->directory = directory;
924c2c66affSColin Finck ctxt->valid = 0;
925c2c66affSColin Finck ctxt->validate = 0;
926c2c66affSColin Finck ctxt->loadsubset = 0;
927c2c66affSColin Finck ctxt->pedantic = 0;
928c2c66affSColin Finck ctxt->dictNames = 1;
929c2c66affSColin Finck
930c2c66affSColin Finck xmlParseDocument(ctxt);
931c2c66affSColin Finck
932c2c66affSColin Finck if (ctxt->wellFormed)
933c2c66affSColin Finck ret = ctxt->myDoc;
934c2c66affSColin Finck else {
935c2c66affSColin Finck ret = NULL;
936c2c66affSColin Finck xmlFreeDoc(ctxt->myDoc);
937c2c66affSColin Finck ctxt->myDoc = NULL;
938c2c66affSColin Finck }
939c2c66affSColin Finck xmlFreeParserCtxt(ctxt);
940c2c66affSColin Finck
941c2c66affSColin Finck return(ret);
942c2c66affSColin Finck }
943c2c66affSColin Finck
944c2c66affSColin Finck /**
945c2c66affSColin Finck * xmlLoadFileContent:
946c2c66affSColin Finck * @filename: a file path
947c2c66affSColin Finck *
948c2c66affSColin Finck * Load a file content into memory.
949c2c66affSColin Finck *
950c2c66affSColin Finck * Returns a pointer to the 0 terminated string or NULL in case of error
951c2c66affSColin Finck */
952c2c66affSColin Finck static xmlChar *
xmlLoadFileContent(const char * filename)953c2c66affSColin Finck xmlLoadFileContent(const char *filename)
954c2c66affSColin Finck {
955c2c66affSColin Finck #ifdef HAVE_STAT
956c2c66affSColin Finck int fd;
957c2c66affSColin Finck #else
958c2c66affSColin Finck FILE *fd;
959c2c66affSColin Finck #endif
960c2c66affSColin Finck int len;
961c2c66affSColin Finck long size;
962c2c66affSColin Finck
963c2c66affSColin Finck #ifdef HAVE_STAT
964c2c66affSColin Finck struct stat info;
965c2c66affSColin Finck #endif
966c2c66affSColin Finck xmlChar *content;
967c2c66affSColin Finck
968c2c66affSColin Finck if (filename == NULL)
969c2c66affSColin Finck return (NULL);
970c2c66affSColin Finck
971c2c66affSColin Finck #ifdef HAVE_STAT
972c2c66affSColin Finck if (stat(filename, &info) < 0)
973c2c66affSColin Finck return (NULL);
974c2c66affSColin Finck #endif
975c2c66affSColin Finck
976c2c66affSColin Finck #ifdef HAVE_STAT
977c2c66affSColin Finck if ((fd = open(filename, O_RDONLY)) < 0)
978c2c66affSColin Finck #else
979c2c66affSColin Finck if ((fd = fopen(filename, "rb")) == NULL)
980c2c66affSColin Finck #endif
981c2c66affSColin Finck {
982c2c66affSColin Finck return (NULL);
983c2c66affSColin Finck }
984c2c66affSColin Finck #ifdef HAVE_STAT
985c2c66affSColin Finck size = info.st_size;
986c2c66affSColin Finck #else
987c2c66affSColin Finck if (fseek(fd, 0, SEEK_END) || (size = ftell(fd)) == EOF || fseek(fd, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */
988c2c66affSColin Finck fclose(fd);
989c2c66affSColin Finck return (NULL);
990c2c66affSColin Finck }
991c2c66affSColin Finck #endif
992c2c66affSColin Finck content = (xmlChar*)xmlMallocAtomic(size + 10);
993c2c66affSColin Finck if (content == NULL) {
994c2c66affSColin Finck xmlCatalogErrMemory("allocating catalog data");
995c2c66affSColin Finck #ifdef HAVE_STAT
996c2c66affSColin Finck close(fd);
997c2c66affSColin Finck #else
998c2c66affSColin Finck fclose(fd);
999c2c66affSColin Finck #endif
1000c2c66affSColin Finck return (NULL);
1001c2c66affSColin Finck }
1002c2c66affSColin Finck #ifdef HAVE_STAT
1003c2c66affSColin Finck len = read(fd, content, size);
1004c2c66affSColin Finck close(fd);
1005c2c66affSColin Finck #else
1006c2c66affSColin Finck len = fread(content, 1, size, fd);
1007c2c66affSColin Finck fclose(fd);
1008c2c66affSColin Finck #endif
1009c2c66affSColin Finck if (len < 0) {
1010c2c66affSColin Finck xmlFree(content);
1011c2c66affSColin Finck return (NULL);
1012c2c66affSColin Finck }
1013c2c66affSColin Finck content[len] = 0;
1014c2c66affSColin Finck
1015c2c66affSColin Finck return(content);
1016c2c66affSColin Finck }
1017c2c66affSColin Finck
1018c2c66affSColin Finck /**
1019c2c66affSColin Finck * xmlCatalogNormalizePublic:
1020c2c66affSColin Finck * @pubID: the public ID string
1021c2c66affSColin Finck *
1022c2c66affSColin Finck * Normalizes the Public Identifier
1023c2c66affSColin Finck *
1024c2c66affSColin Finck * Implements 6.2. Public Identifier Normalization
1025c2c66affSColin Finck * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1026c2c66affSColin Finck *
1027c2c66affSColin Finck * Returns the new string or NULL, the string must be deallocated
1028c2c66affSColin Finck * by the caller.
1029c2c66affSColin Finck */
1030c2c66affSColin Finck static xmlChar *
xmlCatalogNormalizePublic(const xmlChar * pubID)1031c2c66affSColin Finck xmlCatalogNormalizePublic(const xmlChar *pubID)
1032c2c66affSColin Finck {
1033c2c66affSColin Finck int ok = 1;
1034c2c66affSColin Finck int white;
1035c2c66affSColin Finck const xmlChar *p;
1036c2c66affSColin Finck xmlChar *ret;
1037c2c66affSColin Finck xmlChar *q;
1038c2c66affSColin Finck
1039c2c66affSColin Finck if (pubID == NULL)
1040c2c66affSColin Finck return(NULL);
1041c2c66affSColin Finck
1042c2c66affSColin Finck white = 1;
1043c2c66affSColin Finck for (p = pubID;*p != 0 && ok;p++) {
1044c2c66affSColin Finck if (!xmlIsBlank_ch(*p))
1045c2c66affSColin Finck white = 0;
1046c2c66affSColin Finck else if (*p == 0x20 && !white)
1047c2c66affSColin Finck white = 1;
1048c2c66affSColin Finck else
1049c2c66affSColin Finck ok = 0;
1050c2c66affSColin Finck }
1051c2c66affSColin Finck if (ok && !white) /* is normalized */
1052c2c66affSColin Finck return(NULL);
1053c2c66affSColin Finck
1054c2c66affSColin Finck ret = xmlStrdup(pubID);
1055c2c66affSColin Finck q = ret;
1056c2c66affSColin Finck white = 0;
1057c2c66affSColin Finck for (p = pubID;*p != 0;p++) {
1058c2c66affSColin Finck if (xmlIsBlank_ch(*p)) {
1059c2c66affSColin Finck if (q != ret)
1060c2c66affSColin Finck white = 1;
1061c2c66affSColin Finck } else {
1062c2c66affSColin Finck if (white) {
1063c2c66affSColin Finck *(q++) = 0x20;
1064c2c66affSColin Finck white = 0;
1065c2c66affSColin Finck }
1066c2c66affSColin Finck *(q++) = *p;
1067c2c66affSColin Finck }
1068c2c66affSColin Finck }
1069c2c66affSColin Finck *q = 0;
1070c2c66affSColin Finck return(ret);
1071c2c66affSColin Finck }
1072c2c66affSColin Finck
1073c2c66affSColin Finck /************************************************************************
1074c2c66affSColin Finck * *
1075c2c66affSColin Finck * The XML Catalog parser *
1076c2c66affSColin Finck * *
1077c2c66affSColin Finck ************************************************************************/
1078c2c66affSColin Finck
1079c2c66affSColin Finck static xmlCatalogEntryPtr
1080c2c66affSColin Finck xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename);
1081c2c66affSColin Finck static void
1082c2c66affSColin Finck xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
1083c2c66affSColin Finck xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup);
1084c2c66affSColin Finck static xmlChar *
1085c2c66affSColin Finck xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1086c2c66affSColin Finck const xmlChar *sysID);
1087c2c66affSColin Finck static xmlChar *
1088c2c66affSColin Finck xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI);
1089c2c66affSColin Finck
1090c2c66affSColin Finck
1091c2c66affSColin Finck /**
1092c2c66affSColin Finck * xmlGetXMLCatalogEntryType:
1093c2c66affSColin Finck * @name: the name
1094c2c66affSColin Finck *
1095c2c66affSColin Finck * lookup the internal type associated to an XML catalog entry name
1096c2c66affSColin Finck *
1097c2c66affSColin Finck * Returns the type associated with that name
1098c2c66affSColin Finck */
1099c2c66affSColin Finck static xmlCatalogEntryType
xmlGetXMLCatalogEntryType(const xmlChar * name)1100c2c66affSColin Finck xmlGetXMLCatalogEntryType(const xmlChar *name) {
1101c2c66affSColin Finck xmlCatalogEntryType type = XML_CATA_NONE;
1102c2c66affSColin Finck if (xmlStrEqual(name, (const xmlChar *) "system"))
1103c2c66affSColin Finck type = XML_CATA_SYSTEM;
1104c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "public"))
1105c2c66affSColin Finck type = XML_CATA_PUBLIC;
1106c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "rewriteSystem"))
1107c2c66affSColin Finck type = XML_CATA_REWRITE_SYSTEM;
1108c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "delegatePublic"))
1109c2c66affSColin Finck type = XML_CATA_DELEGATE_PUBLIC;
1110c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "delegateSystem"))
1111c2c66affSColin Finck type = XML_CATA_DELEGATE_SYSTEM;
1112c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "uri"))
1113c2c66affSColin Finck type = XML_CATA_URI;
1114c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "rewriteURI"))
1115c2c66affSColin Finck type = XML_CATA_REWRITE_URI;
1116c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "delegateURI"))
1117c2c66affSColin Finck type = XML_CATA_DELEGATE_URI;
1118c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "nextCatalog"))
1119c2c66affSColin Finck type = XML_CATA_NEXT_CATALOG;
1120c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "catalog"))
1121c2c66affSColin Finck type = XML_CATA_CATALOG;
1122c2c66affSColin Finck return(type);
1123c2c66affSColin Finck }
1124c2c66affSColin Finck
1125c2c66affSColin Finck /**
1126c2c66affSColin Finck * xmlParseXMLCatalogOneNode:
1127c2c66affSColin Finck * @cur: the XML node
1128c2c66affSColin Finck * @type: the type of Catalog entry
1129c2c66affSColin Finck * @name: the name of the node
1130c2c66affSColin Finck * @attrName: the attribute holding the value
1131c2c66affSColin Finck * @uriAttrName: the attribute holding the URI-Reference
1132c2c66affSColin Finck * @prefer: the PUBLIC vs. SYSTEM current preference value
1133c2c66affSColin Finck * @cgroup: the group which includes this node
1134c2c66affSColin Finck *
1135c2c66affSColin Finck * Finishes the examination of an XML tree node of a catalog and build
1136c2c66affSColin Finck * a Catalog entry from it.
1137c2c66affSColin Finck *
1138c2c66affSColin Finck * Returns the new Catalog entry node or NULL in case of error.
1139c2c66affSColin Finck */
1140c2c66affSColin Finck static xmlCatalogEntryPtr
xmlParseXMLCatalogOneNode(xmlNodePtr cur,xmlCatalogEntryType type,const xmlChar * name,const xmlChar * attrName,const xmlChar * uriAttrName,xmlCatalogPrefer prefer,xmlCatalogEntryPtr cgroup)1141c2c66affSColin Finck xmlParseXMLCatalogOneNode(xmlNodePtr cur, xmlCatalogEntryType type,
1142c2c66affSColin Finck const xmlChar *name, const xmlChar *attrName,
1143c2c66affSColin Finck const xmlChar *uriAttrName, xmlCatalogPrefer prefer,
1144c2c66affSColin Finck xmlCatalogEntryPtr cgroup) {
1145c2c66affSColin Finck int ok = 1;
1146c2c66affSColin Finck xmlChar *uriValue;
1147c2c66affSColin Finck xmlChar *nameValue = NULL;
1148c2c66affSColin Finck xmlChar *base = NULL;
1149c2c66affSColin Finck xmlChar *URL = NULL;
1150c2c66affSColin Finck xmlCatalogEntryPtr ret = NULL;
1151c2c66affSColin Finck
1152c2c66affSColin Finck if (attrName != NULL) {
1153c2c66affSColin Finck nameValue = xmlGetProp(cur, attrName);
1154c2c66affSColin Finck if (nameValue == NULL) {
1155c2c66affSColin Finck xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
1156c2c66affSColin Finck "%s entry lacks '%s'\n", name, attrName, NULL);
1157c2c66affSColin Finck ok = 0;
1158c2c66affSColin Finck }
1159c2c66affSColin Finck }
1160c2c66affSColin Finck uriValue = xmlGetProp(cur, uriAttrName);
1161c2c66affSColin Finck if (uriValue == NULL) {
1162c2c66affSColin Finck xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
1163c2c66affSColin Finck "%s entry lacks '%s'\n", name, uriAttrName, NULL);
1164c2c66affSColin Finck ok = 0;
1165c2c66affSColin Finck }
1166c2c66affSColin Finck if (!ok) {
1167c2c66affSColin Finck if (nameValue != NULL)
1168c2c66affSColin Finck xmlFree(nameValue);
1169c2c66affSColin Finck if (uriValue != NULL)
1170c2c66affSColin Finck xmlFree(uriValue);
1171c2c66affSColin Finck return(NULL);
1172c2c66affSColin Finck }
1173c2c66affSColin Finck
1174c2c66affSColin Finck base = xmlNodeGetBase(cur->doc, cur);
1175c2c66affSColin Finck URL = xmlBuildURI(uriValue, base);
1176c2c66affSColin Finck if (URL != NULL) {
1177c2c66affSColin Finck if (xmlDebugCatalogs > 1) {
1178c2c66affSColin Finck if (nameValue != NULL)
1179c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1180c2c66affSColin Finck "Found %s: '%s' '%s'\n", name, nameValue, URL);
1181c2c66affSColin Finck else
1182c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1183c2c66affSColin Finck "Found %s: '%s'\n", name, URL);
1184c2c66affSColin Finck }
1185c2c66affSColin Finck ret = xmlNewCatalogEntry(type, nameValue, uriValue, URL, prefer, cgroup);
1186c2c66affSColin Finck } else {
1187c2c66affSColin Finck xmlCatalogErr(ret, cur, XML_CATALOG_ENTRY_BROKEN,
1188c2c66affSColin Finck "%s entry '%s' broken ?: %s\n", name, uriAttrName, uriValue);
1189c2c66affSColin Finck }
1190c2c66affSColin Finck if (nameValue != NULL)
1191c2c66affSColin Finck xmlFree(nameValue);
1192c2c66affSColin Finck if (uriValue != NULL)
1193c2c66affSColin Finck xmlFree(uriValue);
1194c2c66affSColin Finck if (base != NULL)
1195c2c66affSColin Finck xmlFree(base);
1196c2c66affSColin Finck if (URL != NULL)
1197c2c66affSColin Finck xmlFree(URL);
1198c2c66affSColin Finck return(ret);
1199c2c66affSColin Finck }
1200c2c66affSColin Finck
1201c2c66affSColin Finck /**
1202c2c66affSColin Finck * xmlParseXMLCatalogNode:
1203c2c66affSColin Finck * @cur: the XML node
1204c2c66affSColin Finck * @prefer: the PUBLIC vs. SYSTEM current preference value
1205c2c66affSColin Finck * @parent: the parent Catalog entry
1206c2c66affSColin Finck * @cgroup: the group which includes this node
1207c2c66affSColin Finck *
1208c2c66affSColin Finck * Examines an XML tree node of a catalog and build
1209c2c66affSColin Finck * a Catalog entry from it adding it to its parent. The examination can
1210c2c66affSColin Finck * be recursive.
1211c2c66affSColin Finck */
1212c2c66affSColin Finck static void
xmlParseXMLCatalogNode(xmlNodePtr cur,xmlCatalogPrefer prefer,xmlCatalogEntryPtr parent,xmlCatalogEntryPtr cgroup)1213c2c66affSColin Finck xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer,
1214c2c66affSColin Finck xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup)
1215c2c66affSColin Finck {
1216c2c66affSColin Finck xmlChar *base = NULL;
1217c2c66affSColin Finck xmlCatalogEntryPtr entry = NULL;
1218c2c66affSColin Finck
1219c2c66affSColin Finck if (cur == NULL)
1220c2c66affSColin Finck return;
1221c2c66affSColin Finck if (xmlStrEqual(cur->name, BAD_CAST "group")) {
1222c2c66affSColin Finck xmlChar *prop;
1223c2c66affSColin Finck xmlCatalogPrefer pref = XML_CATA_PREFER_NONE;
1224c2c66affSColin Finck
1225c2c66affSColin Finck prop = xmlGetProp(cur, BAD_CAST "prefer");
1226c2c66affSColin Finck if (prop != NULL) {
1227c2c66affSColin Finck if (xmlStrEqual(prop, BAD_CAST "system")) {
1228c2c66affSColin Finck prefer = XML_CATA_PREFER_SYSTEM;
1229c2c66affSColin Finck } else if (xmlStrEqual(prop, BAD_CAST "public")) {
1230c2c66affSColin Finck prefer = XML_CATA_PREFER_PUBLIC;
1231c2c66affSColin Finck } else {
1232c2c66affSColin Finck xmlCatalogErr(parent, cur, XML_CATALOG_PREFER_VALUE,
1233c2c66affSColin Finck "Invalid value for prefer: '%s'\n",
1234c2c66affSColin Finck prop, NULL, NULL);
1235c2c66affSColin Finck }
1236c2c66affSColin Finck xmlFree(prop);
1237c2c66affSColin Finck pref = prefer;
1238c2c66affSColin Finck }
1239c2c66affSColin Finck prop = xmlGetProp(cur, BAD_CAST "id");
1240c2c66affSColin Finck base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE);
1241c2c66affSColin Finck entry = xmlNewCatalogEntry(XML_CATA_GROUP, prop, base, NULL, pref, cgroup);
1242c2c66affSColin Finck xmlFree(prop);
1243c2c66affSColin Finck } else if (xmlStrEqual(cur->name, BAD_CAST "public")) {
1244c2c66affSColin Finck entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_PUBLIC,
1245c2c66affSColin Finck BAD_CAST "public", BAD_CAST "publicId", BAD_CAST "uri", prefer, cgroup);
1246c2c66affSColin Finck } else if (xmlStrEqual(cur->name, BAD_CAST "system")) {
1247c2c66affSColin Finck entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_SYSTEM,
1248c2c66affSColin Finck BAD_CAST "system", BAD_CAST "systemId", BAD_CAST "uri", prefer, cgroup);
1249c2c66affSColin Finck } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteSystem")) {
1250c2c66affSColin Finck entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_SYSTEM,
1251c2c66affSColin Finck BAD_CAST "rewriteSystem", BAD_CAST "systemIdStartString",
1252c2c66affSColin Finck BAD_CAST "rewritePrefix", prefer, cgroup);
1253c2c66affSColin Finck } else if (xmlStrEqual(cur->name, BAD_CAST "delegatePublic")) {
1254c2c66affSColin Finck entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_PUBLIC,
1255c2c66affSColin Finck BAD_CAST "delegatePublic", BAD_CAST "publicIdStartString",
1256c2c66affSColin Finck BAD_CAST "catalog", prefer, cgroup);
1257c2c66affSColin Finck } else if (xmlStrEqual(cur->name, BAD_CAST "delegateSystem")) {
1258c2c66affSColin Finck entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_SYSTEM,
1259c2c66affSColin Finck BAD_CAST "delegateSystem", BAD_CAST "systemIdStartString",
1260c2c66affSColin Finck BAD_CAST "catalog", prefer, cgroup);
1261c2c66affSColin Finck } else if (xmlStrEqual(cur->name, BAD_CAST "uri")) {
1262c2c66affSColin Finck entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_URI,
1263c2c66affSColin Finck BAD_CAST "uri", BAD_CAST "name",
1264c2c66affSColin Finck BAD_CAST "uri", prefer, cgroup);
1265c2c66affSColin Finck } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteURI")) {
1266c2c66affSColin Finck entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_URI,
1267c2c66affSColin Finck BAD_CAST "rewriteURI", BAD_CAST "uriStartString",
1268c2c66affSColin Finck BAD_CAST "rewritePrefix", prefer, cgroup);
1269c2c66affSColin Finck } else if (xmlStrEqual(cur->name, BAD_CAST "delegateURI")) {
1270c2c66affSColin Finck entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_URI,
1271c2c66affSColin Finck BAD_CAST "delegateURI", BAD_CAST "uriStartString",
1272c2c66affSColin Finck BAD_CAST "catalog", prefer, cgroup);
1273c2c66affSColin Finck } else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) {
1274c2c66affSColin Finck entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG,
1275c2c66affSColin Finck BAD_CAST "nextCatalog", NULL,
1276c2c66affSColin Finck BAD_CAST "catalog", prefer, cgroup);
1277c2c66affSColin Finck }
1278c2c66affSColin Finck if (entry != NULL) {
1279c2c66affSColin Finck if (parent != NULL) {
1280c2c66affSColin Finck entry->parent = parent;
1281c2c66affSColin Finck if (parent->children == NULL)
1282c2c66affSColin Finck parent->children = entry;
1283c2c66affSColin Finck else {
1284c2c66affSColin Finck xmlCatalogEntryPtr prev;
1285c2c66affSColin Finck
1286c2c66affSColin Finck prev = parent->children;
1287c2c66affSColin Finck while (prev->next != NULL)
1288c2c66affSColin Finck prev = prev->next;
1289c2c66affSColin Finck prev->next = entry;
1290c2c66affSColin Finck }
1291c2c66affSColin Finck }
1292c2c66affSColin Finck if (entry->type == XML_CATA_GROUP) {
1293c2c66affSColin Finck /*
1294c2c66affSColin Finck * Recurse to propagate prefer to the subtree
1295c2c66affSColin Finck * (xml:base handling is automated)
1296c2c66affSColin Finck */
1297c2c66affSColin Finck xmlParseXMLCatalogNodeList(cur->children, prefer, parent, entry);
1298c2c66affSColin Finck }
1299c2c66affSColin Finck }
1300c2c66affSColin Finck if (base != NULL)
1301c2c66affSColin Finck xmlFree(base);
1302c2c66affSColin Finck }
1303c2c66affSColin Finck
1304c2c66affSColin Finck /**
1305c2c66affSColin Finck * xmlParseXMLCatalogNodeList:
1306c2c66affSColin Finck * @cur: the XML node list of siblings
1307c2c66affSColin Finck * @prefer: the PUBLIC vs. SYSTEM current preference value
1308c2c66affSColin Finck * @parent: the parent Catalog entry
1309c2c66affSColin Finck * @cgroup: the group which includes this list
1310c2c66affSColin Finck *
1311c2c66affSColin Finck * Examines a list of XML sibling nodes of a catalog and build
1312c2c66affSColin Finck * a list of Catalog entry from it adding it to the parent.
1313c2c66affSColin Finck * The examination will recurse to examine node subtrees.
1314c2c66affSColin Finck */
1315c2c66affSColin Finck static void
xmlParseXMLCatalogNodeList(xmlNodePtr cur,xmlCatalogPrefer prefer,xmlCatalogEntryPtr parent,xmlCatalogEntryPtr cgroup)1316c2c66affSColin Finck xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
1317c2c66affSColin Finck xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup) {
1318c2c66affSColin Finck while (cur != NULL) {
1319c2c66affSColin Finck if ((cur->ns != NULL) && (cur->ns->href != NULL) &&
1320c2c66affSColin Finck (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) {
1321c2c66affSColin Finck xmlParseXMLCatalogNode(cur, prefer, parent, cgroup);
1322c2c66affSColin Finck }
1323c2c66affSColin Finck cur = cur->next;
1324c2c66affSColin Finck }
1325c2c66affSColin Finck /* TODO: sort the list according to REWRITE lengths and prefer value */
1326c2c66affSColin Finck }
1327c2c66affSColin Finck
1328c2c66affSColin Finck /**
1329c2c66affSColin Finck * xmlParseXMLCatalogFile:
1330c2c66affSColin Finck * @prefer: the PUBLIC vs. SYSTEM current preference value
1331c2c66affSColin Finck * @filename: the filename for the catalog
1332c2c66affSColin Finck *
1333c2c66affSColin Finck * Parses the catalog file to extract the XML tree and then analyze the
1334c2c66affSColin Finck * tree to build a list of Catalog entries corresponding to this catalog
1335c2c66affSColin Finck *
1336c2c66affSColin Finck * Returns the resulting Catalog entries list
1337c2c66affSColin Finck */
1338c2c66affSColin Finck static xmlCatalogEntryPtr
xmlParseXMLCatalogFile(xmlCatalogPrefer prefer,const xmlChar * filename)1339c2c66affSColin Finck xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename) {
1340c2c66affSColin Finck xmlDocPtr doc;
1341c2c66affSColin Finck xmlNodePtr cur;
1342c2c66affSColin Finck xmlChar *prop;
1343c2c66affSColin Finck xmlCatalogEntryPtr parent = NULL;
1344c2c66affSColin Finck
1345c2c66affSColin Finck if (filename == NULL)
1346c2c66affSColin Finck return(NULL);
1347c2c66affSColin Finck
1348c2c66affSColin Finck doc = xmlParseCatalogFile((const char *) filename);
1349c2c66affSColin Finck if (doc == NULL) {
1350c2c66affSColin Finck if (xmlDebugCatalogs)
1351c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1352c2c66affSColin Finck "Failed to parse catalog %s\n", filename);
1353c2c66affSColin Finck return(NULL);
1354c2c66affSColin Finck }
1355c2c66affSColin Finck
1356c2c66affSColin Finck if (xmlDebugCatalogs)
1357c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1358c2c66affSColin Finck "%d Parsing catalog %s\n", xmlGetThreadId(), filename);
1359c2c66affSColin Finck
1360c2c66affSColin Finck cur = xmlDocGetRootElement(doc);
1361c2c66affSColin Finck if ((cur != NULL) && (xmlStrEqual(cur->name, BAD_CAST "catalog")) &&
1362c2c66affSColin Finck (cur->ns != NULL) && (cur->ns->href != NULL) &&
1363c2c66affSColin Finck (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) {
1364c2c66affSColin Finck
1365c2c66affSColin Finck parent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
1366c2c66affSColin Finck (const xmlChar *)filename, NULL, prefer, NULL);
1367c2c66affSColin Finck if (parent == NULL) {
1368c2c66affSColin Finck xmlFreeDoc(doc);
1369c2c66affSColin Finck return(NULL);
1370c2c66affSColin Finck }
1371c2c66affSColin Finck
1372c2c66affSColin Finck prop = xmlGetProp(cur, BAD_CAST "prefer");
1373c2c66affSColin Finck if (prop != NULL) {
1374c2c66affSColin Finck if (xmlStrEqual(prop, BAD_CAST "system")) {
1375c2c66affSColin Finck prefer = XML_CATA_PREFER_SYSTEM;
1376c2c66affSColin Finck } else if (xmlStrEqual(prop, BAD_CAST "public")) {
1377c2c66affSColin Finck prefer = XML_CATA_PREFER_PUBLIC;
1378c2c66affSColin Finck } else {
1379c2c66affSColin Finck xmlCatalogErr(NULL, cur, XML_CATALOG_PREFER_VALUE,
1380c2c66affSColin Finck "Invalid value for prefer: '%s'\n",
1381c2c66affSColin Finck prop, NULL, NULL);
1382c2c66affSColin Finck }
1383c2c66affSColin Finck xmlFree(prop);
1384c2c66affSColin Finck }
1385c2c66affSColin Finck cur = cur->children;
1386c2c66affSColin Finck xmlParseXMLCatalogNodeList(cur, prefer, parent, NULL);
1387c2c66affSColin Finck } else {
1388c2c66affSColin Finck xmlCatalogErr(NULL, (xmlNodePtr) doc, XML_CATALOG_NOT_CATALOG,
1389c2c66affSColin Finck "File %s is not an XML Catalog\n",
1390c2c66affSColin Finck filename, NULL, NULL);
1391c2c66affSColin Finck xmlFreeDoc(doc);
1392c2c66affSColin Finck return(NULL);
1393c2c66affSColin Finck }
1394c2c66affSColin Finck xmlFreeDoc(doc);
1395c2c66affSColin Finck return(parent);
1396c2c66affSColin Finck }
1397c2c66affSColin Finck
1398c2c66affSColin Finck /**
1399c2c66affSColin Finck * xmlFetchXMLCatalogFile:
1400c2c66affSColin Finck * @catal: an existing but incomplete catalog entry
1401c2c66affSColin Finck *
1402c2c66affSColin Finck * Fetch and parse the subcatalog referenced by an entry
1403c2c66affSColin Finck *
1404c2c66affSColin Finck * Returns 0 in case of success, -1 otherwise
1405c2c66affSColin Finck */
1406c2c66affSColin Finck static int
xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal)1407c2c66affSColin Finck xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) {
1408c2c66affSColin Finck xmlCatalogEntryPtr doc;
1409c2c66affSColin Finck
1410c2c66affSColin Finck if (catal == NULL)
1411c2c66affSColin Finck return(-1);
1412c2c66affSColin Finck if (catal->URL == NULL)
1413c2c66affSColin Finck return(-1);
1414c2c66affSColin Finck
1415c2c66affSColin Finck /*
1416c2c66affSColin Finck * lock the whole catalog for modification
1417c2c66affSColin Finck */
1418c2c66affSColin Finck xmlRMutexLock(xmlCatalogMutex);
1419c2c66affSColin Finck if (catal->children != NULL) {
1420c2c66affSColin Finck /* Okay someone else did it in the meantime */
1421c2c66affSColin Finck xmlRMutexUnlock(xmlCatalogMutex);
1422c2c66affSColin Finck return(0);
1423c2c66affSColin Finck }
1424c2c66affSColin Finck
1425c2c66affSColin Finck if (xmlCatalogXMLFiles != NULL) {
1426c2c66affSColin Finck doc = (xmlCatalogEntryPtr)
1427c2c66affSColin Finck xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
1428c2c66affSColin Finck if (doc != NULL) {
1429c2c66affSColin Finck if (xmlDebugCatalogs)
1430c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1431c2c66affSColin Finck "Found %s in file hash\n", catal->URL);
1432c2c66affSColin Finck
1433c2c66affSColin Finck if (catal->type == XML_CATA_CATALOG)
1434c2c66affSColin Finck catal->children = doc->children;
1435c2c66affSColin Finck else
1436c2c66affSColin Finck catal->children = doc;
1437c2c66affSColin Finck catal->dealloc = 0;
1438c2c66affSColin Finck xmlRMutexUnlock(xmlCatalogMutex);
1439c2c66affSColin Finck return(0);
1440c2c66affSColin Finck }
1441c2c66affSColin Finck if (xmlDebugCatalogs)
1442c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1443c2c66affSColin Finck "%s not found in file hash\n", catal->URL);
1444c2c66affSColin Finck }
1445c2c66affSColin Finck
1446c2c66affSColin Finck /*
1447c2c66affSColin Finck * Fetch and parse. Note that xmlParseXMLCatalogFile does not
1448c2c66affSColin Finck * use the existing catalog, there is no recursion allowed at
1449c2c66affSColin Finck * that level.
1450c2c66affSColin Finck */
1451c2c66affSColin Finck doc = xmlParseXMLCatalogFile(catal->prefer, catal->URL);
1452c2c66affSColin Finck if (doc == NULL) {
1453c2c66affSColin Finck catal->type = XML_CATA_BROKEN_CATALOG;
1454c2c66affSColin Finck xmlRMutexUnlock(xmlCatalogMutex);
1455c2c66affSColin Finck return(-1);
1456c2c66affSColin Finck }
1457c2c66affSColin Finck
1458c2c66affSColin Finck if (catal->type == XML_CATA_CATALOG)
1459c2c66affSColin Finck catal->children = doc->children;
1460c2c66affSColin Finck else
1461c2c66affSColin Finck catal->children = doc;
1462c2c66affSColin Finck
1463c2c66affSColin Finck doc->dealloc = 1;
1464c2c66affSColin Finck
1465c2c66affSColin Finck if (xmlCatalogXMLFiles == NULL)
1466c2c66affSColin Finck xmlCatalogXMLFiles = xmlHashCreate(10);
1467c2c66affSColin Finck if (xmlCatalogXMLFiles != NULL) {
1468c2c66affSColin Finck if (xmlDebugCatalogs)
1469c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1470c2c66affSColin Finck "%s added to file hash\n", catal->URL);
1471c2c66affSColin Finck xmlHashAddEntry(xmlCatalogXMLFiles, catal->URL, doc);
1472c2c66affSColin Finck }
1473c2c66affSColin Finck xmlRMutexUnlock(xmlCatalogMutex);
1474c2c66affSColin Finck return(0);
1475c2c66affSColin Finck }
1476c2c66affSColin Finck
1477c2c66affSColin Finck /************************************************************************
1478c2c66affSColin Finck * *
1479c2c66affSColin Finck * XML Catalog handling *
1480c2c66affSColin Finck * *
1481c2c66affSColin Finck ************************************************************************/
1482c2c66affSColin Finck
1483c2c66affSColin Finck /**
1484c2c66affSColin Finck * xmlAddXMLCatalog:
1485c2c66affSColin Finck * @catal: top of an XML catalog
1486c2c66affSColin Finck * @type: the type of record to add to the catalog
1487c2c66affSColin Finck * @orig: the system, public or prefix to match (or NULL)
1488c2c66affSColin Finck * @replace: the replacement value for the match
1489c2c66affSColin Finck *
1490c2c66affSColin Finck * Add an entry in the XML catalog, it may overwrite existing but
1491c2c66affSColin Finck * different entries.
1492c2c66affSColin Finck *
1493c2c66affSColin Finck * Returns 0 if successful, -1 otherwise
1494c2c66affSColin Finck */
1495c2c66affSColin Finck static int
xmlAddXMLCatalog(xmlCatalogEntryPtr catal,const xmlChar * type,const xmlChar * orig,const xmlChar * replace)1496c2c66affSColin Finck xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type,
1497c2c66affSColin Finck const xmlChar *orig, const xmlChar *replace) {
1498c2c66affSColin Finck xmlCatalogEntryPtr cur;
1499c2c66affSColin Finck xmlCatalogEntryType typ;
1500c2c66affSColin Finck int doregister = 0;
1501c2c66affSColin Finck
1502c2c66affSColin Finck if ((catal == NULL) ||
1503c2c66affSColin Finck ((catal->type != XML_CATA_CATALOG) &&
1504c2c66affSColin Finck (catal->type != XML_CATA_BROKEN_CATALOG)))
1505c2c66affSColin Finck return(-1);
1506c2c66affSColin Finck if (catal->children == NULL) {
1507c2c66affSColin Finck xmlFetchXMLCatalogFile(catal);
1508c2c66affSColin Finck }
1509c2c66affSColin Finck if (catal->children == NULL)
1510c2c66affSColin Finck doregister = 1;
1511c2c66affSColin Finck
1512c2c66affSColin Finck typ = xmlGetXMLCatalogEntryType(type);
1513c2c66affSColin Finck if (typ == XML_CATA_NONE) {
1514c2c66affSColin Finck if (xmlDebugCatalogs)
1515c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1516c2c66affSColin Finck "Failed to add unknown element %s to catalog\n", type);
1517c2c66affSColin Finck return(-1);
1518c2c66affSColin Finck }
1519c2c66affSColin Finck
1520c2c66affSColin Finck cur = catal->children;
1521c2c66affSColin Finck /*
1522c2c66affSColin Finck * Might be a simple "update in place"
1523c2c66affSColin Finck */
1524c2c66affSColin Finck if (cur != NULL) {
1525c2c66affSColin Finck while (cur != NULL) {
1526c2c66affSColin Finck if ((orig != NULL) && (cur->type == typ) &&
1527c2c66affSColin Finck (xmlStrEqual(orig, cur->name))) {
1528c2c66affSColin Finck if (xmlDebugCatalogs)
1529c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1530c2c66affSColin Finck "Updating element %s to catalog\n", type);
1531c2c66affSColin Finck if (cur->value != NULL)
1532c2c66affSColin Finck xmlFree(cur->value);
1533c2c66affSColin Finck if (cur->URL != NULL)
1534c2c66affSColin Finck xmlFree(cur->URL);
1535c2c66affSColin Finck cur->value = xmlStrdup(replace);
1536c2c66affSColin Finck cur->URL = xmlStrdup(replace);
1537c2c66affSColin Finck return(0);
1538c2c66affSColin Finck }
1539c2c66affSColin Finck if (cur->next == NULL)
1540c2c66affSColin Finck break;
1541c2c66affSColin Finck cur = cur->next;
1542c2c66affSColin Finck }
1543c2c66affSColin Finck }
1544c2c66affSColin Finck if (xmlDebugCatalogs)
1545c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1546c2c66affSColin Finck "Adding element %s to catalog\n", type);
1547c2c66affSColin Finck if (cur == NULL)
1548c2c66affSColin Finck catal->children = xmlNewCatalogEntry(typ, orig, replace,
1549c2c66affSColin Finck NULL, catal->prefer, NULL);
1550c2c66affSColin Finck else
1551c2c66affSColin Finck cur->next = xmlNewCatalogEntry(typ, orig, replace,
1552c2c66affSColin Finck NULL, catal->prefer, NULL);
1553c2c66affSColin Finck if (doregister) {
1554c2c66affSColin Finck catal->type = XML_CATA_CATALOG;
1555c2c66affSColin Finck cur = (xmlCatalogEntryPtr)xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
1556c2c66affSColin Finck if (cur != NULL)
1557c2c66affSColin Finck cur->children = catal->children;
1558c2c66affSColin Finck }
1559c2c66affSColin Finck
1560c2c66affSColin Finck return(0);
1561c2c66affSColin Finck }
1562c2c66affSColin Finck
1563c2c66affSColin Finck /**
1564c2c66affSColin Finck * xmlDelXMLCatalog:
1565c2c66affSColin Finck * @catal: top of an XML catalog
1566c2c66affSColin Finck * @value: the value to remove from the catalog
1567c2c66affSColin Finck *
1568c2c66affSColin Finck * Remove entries in the XML catalog where the value or the URI
1569c2c66affSColin Finck * is equal to @value
1570c2c66affSColin Finck *
1571c2c66affSColin Finck * Returns the number of entries removed if successful, -1 otherwise
1572c2c66affSColin Finck */
1573c2c66affSColin Finck static int
xmlDelXMLCatalog(xmlCatalogEntryPtr catal,const xmlChar * value)1574c2c66affSColin Finck xmlDelXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *value) {
1575c2c66affSColin Finck xmlCatalogEntryPtr cur;
1576c2c66affSColin Finck int ret = 0;
1577c2c66affSColin Finck
1578c2c66affSColin Finck if ((catal == NULL) ||
1579c2c66affSColin Finck ((catal->type != XML_CATA_CATALOG) &&
1580c2c66affSColin Finck (catal->type != XML_CATA_BROKEN_CATALOG)))
1581c2c66affSColin Finck return(-1);
1582c2c66affSColin Finck if (value == NULL)
1583c2c66affSColin Finck return(-1);
1584c2c66affSColin Finck if (catal->children == NULL) {
1585c2c66affSColin Finck xmlFetchXMLCatalogFile(catal);
1586c2c66affSColin Finck }
1587c2c66affSColin Finck
1588c2c66affSColin Finck /*
1589c2c66affSColin Finck * Scan the children
1590c2c66affSColin Finck */
1591c2c66affSColin Finck cur = catal->children;
1592c2c66affSColin Finck while (cur != NULL) {
1593c2c66affSColin Finck if (((cur->name != NULL) && (xmlStrEqual(value, cur->name))) ||
1594c2c66affSColin Finck (xmlStrEqual(value, cur->value))) {
1595c2c66affSColin Finck if (xmlDebugCatalogs) {
1596c2c66affSColin Finck if (cur->name != NULL)
1597c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1598c2c66affSColin Finck "Removing element %s from catalog\n", cur->name);
1599c2c66affSColin Finck else
1600c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1601c2c66affSColin Finck "Removing element %s from catalog\n", cur->value);
1602c2c66affSColin Finck }
1603c2c66affSColin Finck cur->type = XML_CATA_REMOVED;
1604c2c66affSColin Finck }
1605c2c66affSColin Finck cur = cur->next;
1606c2c66affSColin Finck }
1607c2c66affSColin Finck return(ret);
1608c2c66affSColin Finck }
1609c2c66affSColin Finck
1610c2c66affSColin Finck /**
1611c2c66affSColin Finck * xmlCatalogXMLResolve:
1612c2c66affSColin Finck * @catal: a catalog list
1613c2c66affSColin Finck * @pubID: the public ID string
1614c2c66affSColin Finck * @sysID: the system ID string
1615c2c66affSColin Finck *
1616c2c66affSColin Finck * Do a complete resolution lookup of an External Identifier for a
1617c2c66affSColin Finck * list of catalog entries.
1618c2c66affSColin Finck *
1619c2c66affSColin Finck * Implements (or tries to) 7.1. External Identifier Resolution
1620c2c66affSColin Finck * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1621c2c66affSColin Finck *
1622c2c66affSColin Finck * Returns the URI of the resource or NULL if not found
1623c2c66affSColin Finck */
1624c2c66affSColin Finck static xmlChar *
xmlCatalogXMLResolve(xmlCatalogEntryPtr catal,const xmlChar * pubID,const xmlChar * sysID)1625c2c66affSColin Finck xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1626c2c66affSColin Finck const xmlChar *sysID) {
1627c2c66affSColin Finck xmlChar *ret = NULL;
1628c2c66affSColin Finck xmlCatalogEntryPtr cur;
1629c2c66affSColin Finck int haveDelegate = 0;
1630c2c66affSColin Finck int haveNext = 0;
1631c2c66affSColin Finck
1632c2c66affSColin Finck /*
1633c2c66affSColin Finck * protection against loops
1634c2c66affSColin Finck */
1635c2c66affSColin Finck if (catal->depth > MAX_CATAL_DEPTH) {
1636c2c66affSColin Finck xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
1637c2c66affSColin Finck "Detected recursion in catalog %s\n",
1638c2c66affSColin Finck catal->name, NULL, NULL);
1639c2c66affSColin Finck return(NULL);
1640c2c66affSColin Finck }
1641c2c66affSColin Finck catal->depth++;
1642c2c66affSColin Finck
1643c2c66affSColin Finck /*
1644c2c66affSColin Finck * First tries steps 2/ 3/ 4/ if a system ID is provided.
1645c2c66affSColin Finck */
1646c2c66affSColin Finck if (sysID != NULL) {
1647c2c66affSColin Finck xmlCatalogEntryPtr rewrite = NULL;
1648c2c66affSColin Finck int lenrewrite = 0, len;
1649c2c66affSColin Finck cur = catal;
1650c2c66affSColin Finck haveDelegate = 0;
1651c2c66affSColin Finck while (cur != NULL) {
1652c2c66affSColin Finck switch (cur->type) {
1653c2c66affSColin Finck case XML_CATA_SYSTEM:
1654c2c66affSColin Finck if (xmlStrEqual(sysID, cur->name)) {
1655c2c66affSColin Finck if (xmlDebugCatalogs)
1656c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1657c2c66affSColin Finck "Found system match %s, using %s\n",
1658c2c66affSColin Finck cur->name, cur->URL);
1659c2c66affSColin Finck catal->depth--;
1660c2c66affSColin Finck return(xmlStrdup(cur->URL));
1661c2c66affSColin Finck }
1662c2c66affSColin Finck break;
1663c2c66affSColin Finck case XML_CATA_REWRITE_SYSTEM:
1664c2c66affSColin Finck len = xmlStrlen(cur->name);
1665c2c66affSColin Finck if ((len > lenrewrite) &&
1666c2c66affSColin Finck (!xmlStrncmp(sysID, cur->name, len))) {
1667c2c66affSColin Finck lenrewrite = len;
1668c2c66affSColin Finck rewrite = cur;
1669c2c66affSColin Finck }
1670c2c66affSColin Finck break;
1671c2c66affSColin Finck case XML_CATA_DELEGATE_SYSTEM:
1672c2c66affSColin Finck if (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))
1673c2c66affSColin Finck haveDelegate++;
1674c2c66affSColin Finck break;
1675c2c66affSColin Finck case XML_CATA_NEXT_CATALOG:
1676c2c66affSColin Finck haveNext++;
1677c2c66affSColin Finck break;
1678c2c66affSColin Finck default:
1679c2c66affSColin Finck break;
1680c2c66affSColin Finck }
1681c2c66affSColin Finck cur = cur->next;
1682c2c66affSColin Finck }
1683c2c66affSColin Finck if (rewrite != NULL) {
1684c2c66affSColin Finck if (xmlDebugCatalogs)
1685c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1686c2c66affSColin Finck "Using rewriting rule %s\n", rewrite->name);
1687c2c66affSColin Finck ret = xmlStrdup(rewrite->URL);
1688c2c66affSColin Finck if (ret != NULL)
1689c2c66affSColin Finck ret = xmlStrcat(ret, &sysID[lenrewrite]);
1690c2c66affSColin Finck catal->depth--;
1691c2c66affSColin Finck return(ret);
1692c2c66affSColin Finck }
1693c2c66affSColin Finck if (haveDelegate) {
1694c2c66affSColin Finck const xmlChar *delegates[MAX_DELEGATE];
1695c2c66affSColin Finck int nbList = 0, i;
1696c2c66affSColin Finck
1697c2c66affSColin Finck /*
1698c2c66affSColin Finck * Assume the entries have been sorted by decreasing substring
1699c2c66affSColin Finck * matches when the list was produced.
1700c2c66affSColin Finck */
1701c2c66affSColin Finck cur = catal;
1702c2c66affSColin Finck while (cur != NULL) {
1703c2c66affSColin Finck if ((cur->type == XML_CATA_DELEGATE_SYSTEM) &&
1704c2c66affSColin Finck (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))) {
1705c2c66affSColin Finck for (i = 0;i < nbList;i++)
1706c2c66affSColin Finck if (xmlStrEqual(cur->URL, delegates[i]))
1707c2c66affSColin Finck break;
1708c2c66affSColin Finck if (i < nbList) {
1709c2c66affSColin Finck cur = cur->next;
1710c2c66affSColin Finck continue;
1711c2c66affSColin Finck }
1712c2c66affSColin Finck if (nbList < MAX_DELEGATE)
1713c2c66affSColin Finck delegates[nbList++] = cur->URL;
1714c2c66affSColin Finck
1715c2c66affSColin Finck if (cur->children == NULL) {
1716c2c66affSColin Finck xmlFetchXMLCatalogFile(cur);
1717c2c66affSColin Finck }
1718c2c66affSColin Finck if (cur->children != NULL) {
1719c2c66affSColin Finck if (xmlDebugCatalogs)
1720c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1721c2c66affSColin Finck "Trying system delegate %s\n", cur->URL);
1722c2c66affSColin Finck ret = xmlCatalogListXMLResolve(
1723c2c66affSColin Finck cur->children, NULL, sysID);
1724c2c66affSColin Finck if (ret != NULL) {
1725c2c66affSColin Finck catal->depth--;
1726c2c66affSColin Finck return(ret);
1727c2c66affSColin Finck }
1728c2c66affSColin Finck }
1729c2c66affSColin Finck }
1730c2c66affSColin Finck cur = cur->next;
1731c2c66affSColin Finck }
1732c2c66affSColin Finck /*
1733c2c66affSColin Finck * Apply the cut algorithm explained in 4/
1734c2c66affSColin Finck */
1735c2c66affSColin Finck catal->depth--;
1736c2c66affSColin Finck return(XML_CATAL_BREAK);
1737c2c66affSColin Finck }
1738c2c66affSColin Finck }
1739c2c66affSColin Finck /*
1740c2c66affSColin Finck * Then tries 5/ 6/ if a public ID is provided
1741c2c66affSColin Finck */
1742c2c66affSColin Finck if (pubID != NULL) {
1743c2c66affSColin Finck cur = catal;
1744c2c66affSColin Finck haveDelegate = 0;
1745c2c66affSColin Finck while (cur != NULL) {
1746c2c66affSColin Finck switch (cur->type) {
1747c2c66affSColin Finck case XML_CATA_PUBLIC:
1748c2c66affSColin Finck if (xmlStrEqual(pubID, cur->name)) {
1749c2c66affSColin Finck if (xmlDebugCatalogs)
1750c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1751c2c66affSColin Finck "Found public match %s\n", cur->name);
1752c2c66affSColin Finck catal->depth--;
1753c2c66affSColin Finck return(xmlStrdup(cur->URL));
1754c2c66affSColin Finck }
1755c2c66affSColin Finck break;
1756c2c66affSColin Finck case XML_CATA_DELEGATE_PUBLIC:
1757c2c66affSColin Finck if (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)) &&
1758c2c66affSColin Finck (cur->prefer == XML_CATA_PREFER_PUBLIC))
1759c2c66affSColin Finck haveDelegate++;
1760c2c66affSColin Finck break;
1761c2c66affSColin Finck case XML_CATA_NEXT_CATALOG:
1762c2c66affSColin Finck if (sysID == NULL)
1763c2c66affSColin Finck haveNext++;
1764c2c66affSColin Finck break;
1765c2c66affSColin Finck default:
1766c2c66affSColin Finck break;
1767c2c66affSColin Finck }
1768c2c66affSColin Finck cur = cur->next;
1769c2c66affSColin Finck }
1770c2c66affSColin Finck if (haveDelegate) {
1771c2c66affSColin Finck const xmlChar *delegates[MAX_DELEGATE];
1772c2c66affSColin Finck int nbList = 0, i;
1773c2c66affSColin Finck
1774c2c66affSColin Finck /*
1775c2c66affSColin Finck * Assume the entries have been sorted by decreasing substring
1776c2c66affSColin Finck * matches when the list was produced.
1777c2c66affSColin Finck */
1778c2c66affSColin Finck cur = catal;
1779c2c66affSColin Finck while (cur != NULL) {
1780c2c66affSColin Finck if ((cur->type == XML_CATA_DELEGATE_PUBLIC) &&
1781c2c66affSColin Finck (cur->prefer == XML_CATA_PREFER_PUBLIC) &&
1782c2c66affSColin Finck (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)))) {
1783c2c66affSColin Finck
1784c2c66affSColin Finck for (i = 0;i < nbList;i++)
1785c2c66affSColin Finck if (xmlStrEqual(cur->URL, delegates[i]))
1786c2c66affSColin Finck break;
1787c2c66affSColin Finck if (i < nbList) {
1788c2c66affSColin Finck cur = cur->next;
1789c2c66affSColin Finck continue;
1790c2c66affSColin Finck }
1791c2c66affSColin Finck if (nbList < MAX_DELEGATE)
1792c2c66affSColin Finck delegates[nbList++] = cur->URL;
1793c2c66affSColin Finck
1794c2c66affSColin Finck if (cur->children == NULL) {
1795c2c66affSColin Finck xmlFetchXMLCatalogFile(cur);
1796c2c66affSColin Finck }
1797c2c66affSColin Finck if (cur->children != NULL) {
1798c2c66affSColin Finck if (xmlDebugCatalogs)
1799c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1800c2c66affSColin Finck "Trying public delegate %s\n", cur->URL);
1801c2c66affSColin Finck ret = xmlCatalogListXMLResolve(
1802c2c66affSColin Finck cur->children, pubID, NULL);
1803c2c66affSColin Finck if (ret != NULL) {
1804c2c66affSColin Finck catal->depth--;
1805c2c66affSColin Finck return(ret);
1806c2c66affSColin Finck }
1807c2c66affSColin Finck }
1808c2c66affSColin Finck }
1809c2c66affSColin Finck cur = cur->next;
1810c2c66affSColin Finck }
1811c2c66affSColin Finck /*
1812c2c66affSColin Finck * Apply the cut algorithm explained in 4/
1813c2c66affSColin Finck */
1814c2c66affSColin Finck catal->depth--;
1815c2c66affSColin Finck return(XML_CATAL_BREAK);
1816c2c66affSColin Finck }
1817c2c66affSColin Finck }
1818c2c66affSColin Finck if (haveNext) {
1819c2c66affSColin Finck cur = catal;
1820c2c66affSColin Finck while (cur != NULL) {
1821c2c66affSColin Finck if (cur->type == XML_CATA_NEXT_CATALOG) {
1822c2c66affSColin Finck if (cur->children == NULL) {
1823c2c66affSColin Finck xmlFetchXMLCatalogFile(cur);
1824c2c66affSColin Finck }
1825c2c66affSColin Finck if (cur->children != NULL) {
1826c2c66affSColin Finck ret = xmlCatalogListXMLResolve(cur->children, pubID, sysID);
1827c2c66affSColin Finck if (ret != NULL) {
1828c2c66affSColin Finck catal->depth--;
1829c2c66affSColin Finck return(ret);
1830c2c66affSColin Finck } else if (catal->depth > MAX_CATAL_DEPTH) {
1831c2c66affSColin Finck return(NULL);
1832c2c66affSColin Finck }
1833c2c66affSColin Finck }
1834c2c66affSColin Finck }
1835c2c66affSColin Finck cur = cur->next;
1836c2c66affSColin Finck }
1837c2c66affSColin Finck }
1838c2c66affSColin Finck
1839c2c66affSColin Finck catal->depth--;
1840c2c66affSColin Finck return(NULL);
1841c2c66affSColin Finck }
1842c2c66affSColin Finck
1843c2c66affSColin Finck /**
1844c2c66affSColin Finck * xmlCatalogXMLResolveURI:
1845c2c66affSColin Finck * @catal: a catalog list
1846c2c66affSColin Finck * @URI: the URI
1847c2c66affSColin Finck * @sysID: the system ID string
1848c2c66affSColin Finck *
1849c2c66affSColin Finck * Do a complete resolution lookup of an External Identifier for a
1850c2c66affSColin Finck * list of catalog entries.
1851c2c66affSColin Finck *
1852c2c66affSColin Finck * Implements (or tries to) 7.2.2. URI Resolution
1853c2c66affSColin Finck * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1854c2c66affSColin Finck *
1855c2c66affSColin Finck * Returns the URI of the resource or NULL if not found
1856c2c66affSColin Finck */
1857c2c66affSColin Finck static xmlChar *
xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal,const xmlChar * URI)1858c2c66affSColin Finck xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
1859c2c66affSColin Finck xmlChar *ret = NULL;
1860c2c66affSColin Finck xmlCatalogEntryPtr cur;
1861c2c66affSColin Finck int haveDelegate = 0;
1862c2c66affSColin Finck int haveNext = 0;
1863c2c66affSColin Finck xmlCatalogEntryPtr rewrite = NULL;
1864c2c66affSColin Finck int lenrewrite = 0, len;
1865c2c66affSColin Finck
1866c2c66affSColin Finck if (catal == NULL)
1867c2c66affSColin Finck return(NULL);
1868c2c66affSColin Finck
1869c2c66affSColin Finck if (URI == NULL)
1870c2c66affSColin Finck return(NULL);
1871c2c66affSColin Finck
1872c2c66affSColin Finck if (catal->depth > MAX_CATAL_DEPTH) {
1873c2c66affSColin Finck xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
1874c2c66affSColin Finck "Detected recursion in catalog %s\n",
1875c2c66affSColin Finck catal->name, NULL, NULL);
1876c2c66affSColin Finck return(NULL);
1877c2c66affSColin Finck }
1878c2c66affSColin Finck
1879c2c66affSColin Finck /*
1880c2c66affSColin Finck * First tries steps 2/ 3/ 4/ if a system ID is provided.
1881c2c66affSColin Finck */
1882c2c66affSColin Finck cur = catal;
1883c2c66affSColin Finck haveDelegate = 0;
1884c2c66affSColin Finck while (cur != NULL) {
1885c2c66affSColin Finck switch (cur->type) {
1886c2c66affSColin Finck case XML_CATA_URI:
1887c2c66affSColin Finck if (xmlStrEqual(URI, cur->name)) {
1888c2c66affSColin Finck if (xmlDebugCatalogs)
1889c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1890c2c66affSColin Finck "Found URI match %s\n", cur->name);
1891c2c66affSColin Finck return(xmlStrdup(cur->URL));
1892c2c66affSColin Finck }
1893c2c66affSColin Finck break;
1894c2c66affSColin Finck case XML_CATA_REWRITE_URI:
1895c2c66affSColin Finck len = xmlStrlen(cur->name);
1896c2c66affSColin Finck if ((len > lenrewrite) &&
1897c2c66affSColin Finck (!xmlStrncmp(URI, cur->name, len))) {
1898c2c66affSColin Finck lenrewrite = len;
1899c2c66affSColin Finck rewrite = cur;
1900c2c66affSColin Finck }
1901c2c66affSColin Finck break;
1902c2c66affSColin Finck case XML_CATA_DELEGATE_URI:
1903c2c66affSColin Finck if (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))
1904c2c66affSColin Finck haveDelegate++;
1905c2c66affSColin Finck break;
1906c2c66affSColin Finck case XML_CATA_NEXT_CATALOG:
1907c2c66affSColin Finck haveNext++;
1908c2c66affSColin Finck break;
1909c2c66affSColin Finck default:
1910c2c66affSColin Finck break;
1911c2c66affSColin Finck }
1912c2c66affSColin Finck cur = cur->next;
1913c2c66affSColin Finck }
1914c2c66affSColin Finck if (rewrite != NULL) {
1915c2c66affSColin Finck if (xmlDebugCatalogs)
1916c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1917c2c66affSColin Finck "Using rewriting rule %s\n", rewrite->name);
1918c2c66affSColin Finck ret = xmlStrdup(rewrite->URL);
1919c2c66affSColin Finck if (ret != NULL)
1920c2c66affSColin Finck ret = xmlStrcat(ret, &URI[lenrewrite]);
1921c2c66affSColin Finck return(ret);
1922c2c66affSColin Finck }
1923c2c66affSColin Finck if (haveDelegate) {
1924c2c66affSColin Finck const xmlChar *delegates[MAX_DELEGATE];
1925c2c66affSColin Finck int nbList = 0, i;
1926c2c66affSColin Finck
1927c2c66affSColin Finck /*
1928c2c66affSColin Finck * Assume the entries have been sorted by decreasing substring
1929c2c66affSColin Finck * matches when the list was produced.
1930c2c66affSColin Finck */
1931c2c66affSColin Finck cur = catal;
1932c2c66affSColin Finck while (cur != NULL) {
1933c2c66affSColin Finck if (((cur->type == XML_CATA_DELEGATE_SYSTEM) ||
1934c2c66affSColin Finck (cur->type == XML_CATA_DELEGATE_URI)) &&
1935c2c66affSColin Finck (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))) {
1936c2c66affSColin Finck for (i = 0;i < nbList;i++)
1937c2c66affSColin Finck if (xmlStrEqual(cur->URL, delegates[i]))
1938c2c66affSColin Finck break;
1939c2c66affSColin Finck if (i < nbList) {
1940c2c66affSColin Finck cur = cur->next;
1941c2c66affSColin Finck continue;
1942c2c66affSColin Finck }
1943c2c66affSColin Finck if (nbList < MAX_DELEGATE)
1944c2c66affSColin Finck delegates[nbList++] = cur->URL;
1945c2c66affSColin Finck
1946c2c66affSColin Finck if (cur->children == NULL) {
1947c2c66affSColin Finck xmlFetchXMLCatalogFile(cur);
1948c2c66affSColin Finck }
1949c2c66affSColin Finck if (cur->children != NULL) {
1950c2c66affSColin Finck if (xmlDebugCatalogs)
1951c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
1952c2c66affSColin Finck "Trying URI delegate %s\n", cur->URL);
1953c2c66affSColin Finck ret = xmlCatalogListXMLResolveURI(
1954c2c66affSColin Finck cur->children, URI);
1955c2c66affSColin Finck if (ret != NULL)
1956c2c66affSColin Finck return(ret);
1957c2c66affSColin Finck }
1958c2c66affSColin Finck }
1959c2c66affSColin Finck cur = cur->next;
1960c2c66affSColin Finck }
1961c2c66affSColin Finck /*
1962c2c66affSColin Finck * Apply the cut algorithm explained in 4/
1963c2c66affSColin Finck */
1964c2c66affSColin Finck return(XML_CATAL_BREAK);
1965c2c66affSColin Finck }
1966c2c66affSColin Finck if (haveNext) {
1967c2c66affSColin Finck cur = catal;
1968c2c66affSColin Finck while (cur != NULL) {
1969c2c66affSColin Finck if (cur->type == XML_CATA_NEXT_CATALOG) {
1970c2c66affSColin Finck if (cur->children == NULL) {
1971c2c66affSColin Finck xmlFetchXMLCatalogFile(cur);
1972c2c66affSColin Finck }
1973c2c66affSColin Finck if (cur->children != NULL) {
1974c2c66affSColin Finck ret = xmlCatalogListXMLResolveURI(cur->children, URI);
1975c2c66affSColin Finck if (ret != NULL)
1976c2c66affSColin Finck return(ret);
1977c2c66affSColin Finck }
1978c2c66affSColin Finck }
1979c2c66affSColin Finck cur = cur->next;
1980c2c66affSColin Finck }
1981c2c66affSColin Finck }
1982c2c66affSColin Finck
1983c2c66affSColin Finck return(NULL);
1984c2c66affSColin Finck }
1985c2c66affSColin Finck
1986c2c66affSColin Finck /**
1987c2c66affSColin Finck * xmlCatalogListXMLResolve:
1988c2c66affSColin Finck * @catal: a catalog list
1989c2c66affSColin Finck * @pubID: the public ID string
1990c2c66affSColin Finck * @sysID: the system ID string
1991c2c66affSColin Finck *
1992c2c66affSColin Finck * Do a complete resolution lookup of an External Identifier for a
1993c2c66affSColin Finck * list of catalogs
1994c2c66affSColin Finck *
1995c2c66affSColin Finck * Implements (or tries to) 7.1. External Identifier Resolution
1996c2c66affSColin Finck * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1997c2c66affSColin Finck *
1998c2c66affSColin Finck * Returns the URI of the resource or NULL if not found
1999c2c66affSColin Finck */
2000c2c66affSColin Finck static xmlChar *
xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal,const xmlChar * pubID,const xmlChar * sysID)2001c2c66affSColin Finck xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
2002c2c66affSColin Finck const xmlChar *sysID) {
2003c2c66affSColin Finck xmlChar *ret = NULL;
2004c2c66affSColin Finck xmlChar *urnID = NULL;
2005c2c66affSColin Finck xmlChar *normid;
2006c2c66affSColin Finck
2007c2c66affSColin Finck if (catal == NULL)
2008c2c66affSColin Finck return(NULL);
2009c2c66affSColin Finck if ((pubID == NULL) && (sysID == NULL))
2010c2c66affSColin Finck return(NULL);
2011c2c66affSColin Finck
2012c2c66affSColin Finck normid = xmlCatalogNormalizePublic(pubID);
2013c2c66affSColin Finck if (normid != NULL)
2014c2c66affSColin Finck pubID = (*normid != 0 ? normid : NULL);
2015c2c66affSColin Finck
2016c2c66affSColin Finck if (!xmlStrncmp(pubID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2017c2c66affSColin Finck urnID = xmlCatalogUnWrapURN(pubID);
2018c2c66affSColin Finck if (xmlDebugCatalogs) {
2019c2c66affSColin Finck if (urnID == NULL)
2020c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
2021c2c66affSColin Finck "Public URN ID %s expanded to NULL\n", pubID);
2022c2c66affSColin Finck else
2023c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
2024c2c66affSColin Finck "Public URN ID expanded to %s\n", urnID);
2025c2c66affSColin Finck }
2026c2c66affSColin Finck ret = xmlCatalogListXMLResolve(catal, urnID, sysID);
2027c2c66affSColin Finck if (urnID != NULL)
2028c2c66affSColin Finck xmlFree(urnID);
2029c2c66affSColin Finck if (normid != NULL)
2030c2c66affSColin Finck xmlFree(normid);
2031c2c66affSColin Finck return(ret);
2032c2c66affSColin Finck }
2033c2c66affSColin Finck if (!xmlStrncmp(sysID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2034c2c66affSColin Finck urnID = xmlCatalogUnWrapURN(sysID);
2035c2c66affSColin Finck if (xmlDebugCatalogs) {
2036c2c66affSColin Finck if (urnID == NULL)
2037c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
2038c2c66affSColin Finck "System URN ID %s expanded to NULL\n", sysID);
2039c2c66affSColin Finck else
2040c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
2041c2c66affSColin Finck "System URN ID expanded to %s\n", urnID);
2042c2c66affSColin Finck }
2043c2c66affSColin Finck if (pubID == NULL)
2044c2c66affSColin Finck ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
2045c2c66affSColin Finck else if (xmlStrEqual(pubID, urnID))
2046c2c66affSColin Finck ret = xmlCatalogListXMLResolve(catal, pubID, NULL);
2047c2c66affSColin Finck else {
2048c2c66affSColin Finck ret = xmlCatalogListXMLResolve(catal, pubID, urnID);
2049c2c66affSColin Finck }
2050c2c66affSColin Finck if (urnID != NULL)
2051c2c66affSColin Finck xmlFree(urnID);
2052c2c66affSColin Finck if (normid != NULL)
2053c2c66affSColin Finck xmlFree(normid);
2054c2c66affSColin Finck return(ret);
2055c2c66affSColin Finck }
2056c2c66affSColin Finck while (catal != NULL) {
2057c2c66affSColin Finck if (catal->type == XML_CATA_CATALOG) {
2058c2c66affSColin Finck if (catal->children == NULL) {
2059c2c66affSColin Finck xmlFetchXMLCatalogFile(catal);
2060c2c66affSColin Finck }
2061c2c66affSColin Finck if (catal->children != NULL) {
2062c2c66affSColin Finck ret = xmlCatalogXMLResolve(catal->children, pubID, sysID);
2063c2c66affSColin Finck if (ret != NULL) {
2064c2c66affSColin Finck break;
206540ee59d6SThomas Faber } else if (catal->children->depth > MAX_CATAL_DEPTH) {
2066c2c66affSColin Finck ret = NULL;
2067c2c66affSColin Finck break;
2068c2c66affSColin Finck }
2069c2c66affSColin Finck }
2070c2c66affSColin Finck }
2071c2c66affSColin Finck catal = catal->next;
2072c2c66affSColin Finck }
2073c2c66affSColin Finck if (normid != NULL)
2074c2c66affSColin Finck xmlFree(normid);
2075c2c66affSColin Finck return(ret);
2076c2c66affSColin Finck }
2077c2c66affSColin Finck
2078c2c66affSColin Finck /**
2079c2c66affSColin Finck * xmlCatalogListXMLResolveURI:
2080c2c66affSColin Finck * @catal: a catalog list
2081c2c66affSColin Finck * @URI: the URI
2082c2c66affSColin Finck *
2083c2c66affSColin Finck * Do a complete resolution lookup of an URI for a list of catalogs
2084c2c66affSColin Finck *
2085c2c66affSColin Finck * Implements (or tries to) 7.2. URI Resolution
2086c2c66affSColin Finck * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
2087c2c66affSColin Finck *
2088c2c66affSColin Finck * Returns the URI of the resource or NULL if not found
2089c2c66affSColin Finck */
2090c2c66affSColin Finck static xmlChar *
xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal,const xmlChar * URI)2091c2c66affSColin Finck xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
2092c2c66affSColin Finck xmlChar *ret = NULL;
2093c2c66affSColin Finck xmlChar *urnID = NULL;
2094c2c66affSColin Finck
2095c2c66affSColin Finck if (catal == NULL)
2096c2c66affSColin Finck return(NULL);
2097c2c66affSColin Finck if (URI == NULL)
2098c2c66affSColin Finck return(NULL);
2099c2c66affSColin Finck
2100c2c66affSColin Finck if (!xmlStrncmp(URI, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2101c2c66affSColin Finck urnID = xmlCatalogUnWrapURN(URI);
2102c2c66affSColin Finck if (xmlDebugCatalogs) {
2103c2c66affSColin Finck if (urnID == NULL)
2104c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
2105c2c66affSColin Finck "URN ID %s expanded to NULL\n", URI);
2106c2c66affSColin Finck else
2107c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
2108c2c66affSColin Finck "URN ID expanded to %s\n", urnID);
2109c2c66affSColin Finck }
2110c2c66affSColin Finck ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
2111c2c66affSColin Finck if (urnID != NULL)
2112c2c66affSColin Finck xmlFree(urnID);
2113c2c66affSColin Finck return(ret);
2114c2c66affSColin Finck }
2115c2c66affSColin Finck while (catal != NULL) {
2116c2c66affSColin Finck if (catal->type == XML_CATA_CATALOG) {
2117c2c66affSColin Finck if (catal->children == NULL) {
2118c2c66affSColin Finck xmlFetchXMLCatalogFile(catal);
2119c2c66affSColin Finck }
2120c2c66affSColin Finck if (catal->children != NULL) {
2121c2c66affSColin Finck ret = xmlCatalogXMLResolveURI(catal->children, URI);
2122c2c66affSColin Finck if (ret != NULL)
2123c2c66affSColin Finck return(ret);
2124c2c66affSColin Finck }
2125c2c66affSColin Finck }
2126c2c66affSColin Finck catal = catal->next;
2127c2c66affSColin Finck }
2128c2c66affSColin Finck return(ret);
2129c2c66affSColin Finck }
2130c2c66affSColin Finck
2131c2c66affSColin Finck /************************************************************************
2132c2c66affSColin Finck * *
2133c2c66affSColin Finck * The SGML Catalog parser *
2134c2c66affSColin Finck * *
2135c2c66affSColin Finck ************************************************************************/
2136c2c66affSColin Finck
2137c2c66affSColin Finck
2138c2c66affSColin Finck #define RAW *cur
2139c2c66affSColin Finck #define NEXT cur++;
2140c2c66affSColin Finck #define SKIP(x) cur += x;
2141c2c66affSColin Finck
2142c2c66affSColin Finck #define SKIP_BLANKS while (IS_BLANK_CH(*cur)) NEXT;
2143c2c66affSColin Finck
2144c2c66affSColin Finck /**
2145c2c66affSColin Finck * xmlParseSGMLCatalogComment:
2146c2c66affSColin Finck * @cur: the current character
2147c2c66affSColin Finck *
2148c2c66affSColin Finck * Skip a comment in an SGML catalog
2149c2c66affSColin Finck *
2150c2c66affSColin Finck * Returns new current character
2151c2c66affSColin Finck */
2152c2c66affSColin Finck static const xmlChar *
xmlParseSGMLCatalogComment(const xmlChar * cur)2153c2c66affSColin Finck xmlParseSGMLCatalogComment(const xmlChar *cur) {
2154c2c66affSColin Finck if ((cur[0] != '-') || (cur[1] != '-'))
2155c2c66affSColin Finck return(cur);
2156c2c66affSColin Finck SKIP(2);
2157c2c66affSColin Finck while ((cur[0] != 0) && ((cur[0] != '-') || ((cur[1] != '-'))))
2158c2c66affSColin Finck NEXT;
2159c2c66affSColin Finck if (cur[0] == 0) {
2160c2c66affSColin Finck return(NULL);
2161c2c66affSColin Finck }
2162c2c66affSColin Finck return(cur + 2);
2163c2c66affSColin Finck }
2164c2c66affSColin Finck
2165c2c66affSColin Finck /**
2166c2c66affSColin Finck * xmlParseSGMLCatalogPubid:
2167c2c66affSColin Finck * @cur: the current character
2168c2c66affSColin Finck * @id: the return location
2169c2c66affSColin Finck *
2170c2c66affSColin Finck * Parse an SGML catalog ID
2171c2c66affSColin Finck *
2172c2c66affSColin Finck * Returns new current character and store the value in @id
2173c2c66affSColin Finck */
2174c2c66affSColin Finck static const xmlChar *
xmlParseSGMLCatalogPubid(const xmlChar * cur,xmlChar ** id)2175c2c66affSColin Finck xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) {
2176c2c66affSColin Finck xmlChar *buf = NULL, *tmp;
2177c2c66affSColin Finck int len = 0;
2178c2c66affSColin Finck int size = 50;
2179c2c66affSColin Finck xmlChar stop;
2180c2c66affSColin Finck int count = 0;
2181c2c66affSColin Finck
2182c2c66affSColin Finck *id = NULL;
2183c2c66affSColin Finck
2184c2c66affSColin Finck if (RAW == '"') {
2185c2c66affSColin Finck NEXT;
2186c2c66affSColin Finck stop = '"';
2187c2c66affSColin Finck } else if (RAW == '\'') {
2188c2c66affSColin Finck NEXT;
2189c2c66affSColin Finck stop = '\'';
2190c2c66affSColin Finck } else {
2191c2c66affSColin Finck stop = ' ';
2192c2c66affSColin Finck }
2193c2c66affSColin Finck buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
2194c2c66affSColin Finck if (buf == NULL) {
2195c2c66affSColin Finck xmlCatalogErrMemory("allocating public ID");
2196c2c66affSColin Finck return(NULL);
2197c2c66affSColin Finck }
2198c2c66affSColin Finck while (IS_PUBIDCHAR_CH(*cur) || (*cur == '?')) {
2199c2c66affSColin Finck if ((*cur == stop) && (stop != ' '))
2200c2c66affSColin Finck break;
2201c2c66affSColin Finck if ((stop == ' ') && (IS_BLANK_CH(*cur)))
2202c2c66affSColin Finck break;
2203c2c66affSColin Finck if (len + 1 >= size) {
2204c2c66affSColin Finck size *= 2;
2205c2c66affSColin Finck tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
2206c2c66affSColin Finck if (tmp == NULL) {
2207c2c66affSColin Finck xmlCatalogErrMemory("allocating public ID");
2208c2c66affSColin Finck xmlFree(buf);
2209c2c66affSColin Finck return(NULL);
2210c2c66affSColin Finck }
2211c2c66affSColin Finck buf = tmp;
2212c2c66affSColin Finck }
2213c2c66affSColin Finck buf[len++] = *cur;
2214c2c66affSColin Finck count++;
2215c2c66affSColin Finck NEXT;
2216c2c66affSColin Finck }
2217c2c66affSColin Finck buf[len] = 0;
2218c2c66affSColin Finck if (stop == ' ') {
2219c2c66affSColin Finck if (!IS_BLANK_CH(*cur)) {
2220c2c66affSColin Finck xmlFree(buf);
2221c2c66affSColin Finck return(NULL);
2222c2c66affSColin Finck }
2223c2c66affSColin Finck } else {
2224c2c66affSColin Finck if (*cur != stop) {
2225c2c66affSColin Finck xmlFree(buf);
2226c2c66affSColin Finck return(NULL);
2227c2c66affSColin Finck }
2228c2c66affSColin Finck NEXT;
2229c2c66affSColin Finck }
2230c2c66affSColin Finck *id = buf;
2231c2c66affSColin Finck return(cur);
2232c2c66affSColin Finck }
2233c2c66affSColin Finck
2234c2c66affSColin Finck /**
2235c2c66affSColin Finck * xmlParseSGMLCatalogName:
2236c2c66affSColin Finck * @cur: the current character
2237c2c66affSColin Finck * @name: the return location
2238c2c66affSColin Finck *
2239c2c66affSColin Finck * Parse an SGML catalog name
2240c2c66affSColin Finck *
2241c2c66affSColin Finck * Returns new current character and store the value in @name
2242c2c66affSColin Finck */
2243c2c66affSColin Finck static const xmlChar *
xmlParseSGMLCatalogName(const xmlChar * cur,xmlChar ** name)2244c2c66affSColin Finck xmlParseSGMLCatalogName(const xmlChar *cur, xmlChar **name) {
2245c2c66affSColin Finck xmlChar buf[XML_MAX_NAMELEN + 5];
2246c2c66affSColin Finck int len = 0;
2247c2c66affSColin Finck int c;
2248c2c66affSColin Finck
2249c2c66affSColin Finck *name = NULL;
2250c2c66affSColin Finck
2251c2c66affSColin Finck /*
2252c2c66affSColin Finck * Handler for more complex cases
2253c2c66affSColin Finck */
2254c2c66affSColin Finck c = *cur;
2255c2c66affSColin Finck if ((!IS_LETTER(c) && (c != '_') && (c != ':'))) {
2256c2c66affSColin Finck return(NULL);
2257c2c66affSColin Finck }
2258c2c66affSColin Finck
2259c2c66affSColin Finck while (((IS_LETTER(c)) || (IS_DIGIT(c)) ||
2260c2c66affSColin Finck (c == '.') || (c == '-') ||
2261c2c66affSColin Finck (c == '_') || (c == ':'))) {
2262c2c66affSColin Finck buf[len++] = c;
2263c2c66affSColin Finck cur++;
2264c2c66affSColin Finck c = *cur;
2265c2c66affSColin Finck if (len >= XML_MAX_NAMELEN)
2266c2c66affSColin Finck return(NULL);
2267c2c66affSColin Finck }
2268c2c66affSColin Finck *name = xmlStrndup(buf, len);
2269c2c66affSColin Finck return(cur);
2270c2c66affSColin Finck }
2271c2c66affSColin Finck
2272c2c66affSColin Finck /**
2273c2c66affSColin Finck * xmlGetSGMLCatalogEntryType:
2274c2c66affSColin Finck * @name: the entry name
2275c2c66affSColin Finck *
2276c2c66affSColin Finck * Get the Catalog entry type for a given SGML Catalog name
2277c2c66affSColin Finck *
2278c2c66affSColin Finck * Returns Catalog entry type
2279c2c66affSColin Finck */
2280c2c66affSColin Finck static xmlCatalogEntryType
xmlGetSGMLCatalogEntryType(const xmlChar * name)2281c2c66affSColin Finck xmlGetSGMLCatalogEntryType(const xmlChar *name) {
2282c2c66affSColin Finck xmlCatalogEntryType type = XML_CATA_NONE;
2283c2c66affSColin Finck if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
2284c2c66affSColin Finck type = SGML_CATA_SYSTEM;
2285c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
2286c2c66affSColin Finck type = SGML_CATA_PUBLIC;
2287c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
2288c2c66affSColin Finck type = SGML_CATA_DELEGATE;
2289c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
2290c2c66affSColin Finck type = SGML_CATA_ENTITY;
2291c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
2292c2c66affSColin Finck type = SGML_CATA_DOCTYPE;
2293c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
2294c2c66affSColin Finck type = SGML_CATA_LINKTYPE;
2295c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
2296c2c66affSColin Finck type = SGML_CATA_NOTATION;
2297c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
2298c2c66affSColin Finck type = SGML_CATA_SGMLDECL;
2299c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
2300c2c66affSColin Finck type = SGML_CATA_DOCUMENT;
2301c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
2302c2c66affSColin Finck type = SGML_CATA_CATALOG;
2303c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
2304c2c66affSColin Finck type = SGML_CATA_BASE;
2305c2c66affSColin Finck return(type);
2306c2c66affSColin Finck }
2307c2c66affSColin Finck
2308c2c66affSColin Finck /**
2309c2c66affSColin Finck * xmlParseSGMLCatalog:
2310c2c66affSColin Finck * @catal: the SGML Catalog
2311c2c66affSColin Finck * @value: the content of the SGML Catalog serialization
2312c2c66affSColin Finck * @file: the filepath for the catalog
2313c2c66affSColin Finck * @super: should this be handled as a Super Catalog in which case
2314c2c66affSColin Finck * parsing is not recursive
2315c2c66affSColin Finck *
2316c2c66affSColin Finck * Parse an SGML catalog content and fill up the @catal hash table with
2317c2c66affSColin Finck * the new entries found.
2318c2c66affSColin Finck *
2319c2c66affSColin Finck * Returns 0 in case of success, -1 in case of error.
2320c2c66affSColin Finck */
2321c2c66affSColin Finck static int
xmlParseSGMLCatalog(xmlCatalogPtr catal,const xmlChar * value,const char * file,int super)2322c2c66affSColin Finck xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value,
2323c2c66affSColin Finck const char *file, int super) {
2324c2c66affSColin Finck const xmlChar *cur = value;
2325c2c66affSColin Finck xmlChar *base = NULL;
2326c2c66affSColin Finck int res;
2327c2c66affSColin Finck
2328c2c66affSColin Finck if ((cur == NULL) || (file == NULL))
2329c2c66affSColin Finck return(-1);
2330c2c66affSColin Finck base = xmlStrdup((const xmlChar *) file);
2331c2c66affSColin Finck
2332c2c66affSColin Finck while ((cur != NULL) && (cur[0] != 0)) {
2333c2c66affSColin Finck SKIP_BLANKS;
2334c2c66affSColin Finck if (cur[0] == 0)
2335c2c66affSColin Finck break;
2336c2c66affSColin Finck if ((cur[0] == '-') && (cur[1] == '-')) {
2337c2c66affSColin Finck cur = xmlParseSGMLCatalogComment(cur);
2338c2c66affSColin Finck if (cur == NULL) {
2339c2c66affSColin Finck /* error */
2340c2c66affSColin Finck break;
2341c2c66affSColin Finck }
2342c2c66affSColin Finck } else {
2343c2c66affSColin Finck xmlChar *sysid = NULL;
2344c2c66affSColin Finck xmlChar *name = NULL;
2345c2c66affSColin Finck xmlCatalogEntryType type = XML_CATA_NONE;
2346c2c66affSColin Finck
2347c2c66affSColin Finck cur = xmlParseSGMLCatalogName(cur, &name);
234840ee59d6SThomas Faber if (cur == NULL || name == NULL) {
2349c2c66affSColin Finck /* error */
2350c2c66affSColin Finck break;
2351c2c66affSColin Finck }
2352c2c66affSColin Finck if (!IS_BLANK_CH(*cur)) {
2353c2c66affSColin Finck /* error */
23547244e0c5SThomas Faber xmlFree(name);
2355c2c66affSColin Finck break;
2356c2c66affSColin Finck }
2357c2c66affSColin Finck SKIP_BLANKS;
2358c2c66affSColin Finck if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
2359c2c66affSColin Finck type = SGML_CATA_SYSTEM;
2360c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
2361c2c66affSColin Finck type = SGML_CATA_PUBLIC;
2362c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
2363c2c66affSColin Finck type = SGML_CATA_DELEGATE;
2364c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
2365c2c66affSColin Finck type = SGML_CATA_ENTITY;
2366c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
2367c2c66affSColin Finck type = SGML_CATA_DOCTYPE;
2368c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
2369c2c66affSColin Finck type = SGML_CATA_LINKTYPE;
2370c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
2371c2c66affSColin Finck type = SGML_CATA_NOTATION;
2372c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
2373c2c66affSColin Finck type = SGML_CATA_SGMLDECL;
2374c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
2375c2c66affSColin Finck type = SGML_CATA_DOCUMENT;
2376c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
2377c2c66affSColin Finck type = SGML_CATA_CATALOG;
2378c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
2379c2c66affSColin Finck type = SGML_CATA_BASE;
2380c2c66affSColin Finck else if (xmlStrEqual(name, (const xmlChar *) "OVERRIDE")) {
2381c2c66affSColin Finck xmlFree(name);
2382c2c66affSColin Finck cur = xmlParseSGMLCatalogName(cur, &name);
2383c2c66affSColin Finck if (name == NULL) {
2384c2c66affSColin Finck /* error */
2385c2c66affSColin Finck break;
2386c2c66affSColin Finck }
2387c2c66affSColin Finck xmlFree(name);
2388c2c66affSColin Finck continue;
2389c2c66affSColin Finck }
2390c2c66affSColin Finck xmlFree(name);
2391c2c66affSColin Finck name = NULL;
2392c2c66affSColin Finck
2393c2c66affSColin Finck switch(type) {
2394c2c66affSColin Finck case SGML_CATA_ENTITY:
2395c2c66affSColin Finck if (*cur == '%')
2396c2c66affSColin Finck type = SGML_CATA_PENTITY;
2397fc82f8e2SThomas Faber /* Falls through. */
2398c2c66affSColin Finck case SGML_CATA_PENTITY:
2399c2c66affSColin Finck case SGML_CATA_DOCTYPE:
2400c2c66affSColin Finck case SGML_CATA_LINKTYPE:
2401c2c66affSColin Finck case SGML_CATA_NOTATION:
2402c2c66affSColin Finck cur = xmlParseSGMLCatalogName(cur, &name);
2403c2c66affSColin Finck if (cur == NULL) {
2404c2c66affSColin Finck /* error */
2405c2c66affSColin Finck break;
2406c2c66affSColin Finck }
2407c2c66affSColin Finck if (!IS_BLANK_CH(*cur)) {
2408c2c66affSColin Finck /* error */
2409c2c66affSColin Finck break;
2410c2c66affSColin Finck }
2411c2c66affSColin Finck SKIP_BLANKS;
2412c2c66affSColin Finck cur = xmlParseSGMLCatalogPubid(cur, &sysid);
2413c2c66affSColin Finck if (cur == NULL) {
2414c2c66affSColin Finck /* error */
2415c2c66affSColin Finck break;
2416c2c66affSColin Finck }
2417c2c66affSColin Finck break;
2418c2c66affSColin Finck case SGML_CATA_PUBLIC:
2419c2c66affSColin Finck case SGML_CATA_SYSTEM:
2420c2c66affSColin Finck case SGML_CATA_DELEGATE:
2421c2c66affSColin Finck cur = xmlParseSGMLCatalogPubid(cur, &name);
2422c2c66affSColin Finck if (cur == NULL) {
2423c2c66affSColin Finck /* error */
2424c2c66affSColin Finck break;
2425c2c66affSColin Finck }
2426c2c66affSColin Finck if (type != SGML_CATA_SYSTEM) {
2427c2c66affSColin Finck xmlChar *normid;
2428c2c66affSColin Finck
2429c2c66affSColin Finck normid = xmlCatalogNormalizePublic(name);
2430c2c66affSColin Finck if (normid != NULL) {
2431c2c66affSColin Finck if (name != NULL)
2432c2c66affSColin Finck xmlFree(name);
2433c2c66affSColin Finck if (*normid != 0)
2434c2c66affSColin Finck name = normid;
2435c2c66affSColin Finck else {
2436c2c66affSColin Finck xmlFree(normid);
2437c2c66affSColin Finck name = NULL;
2438c2c66affSColin Finck }
2439c2c66affSColin Finck }
2440c2c66affSColin Finck }
2441c2c66affSColin Finck if (!IS_BLANK_CH(*cur)) {
2442c2c66affSColin Finck /* error */
2443c2c66affSColin Finck break;
2444c2c66affSColin Finck }
2445c2c66affSColin Finck SKIP_BLANKS;
2446c2c66affSColin Finck cur = xmlParseSGMLCatalogPubid(cur, &sysid);
2447c2c66affSColin Finck if (cur == NULL) {
2448c2c66affSColin Finck /* error */
2449c2c66affSColin Finck break;
2450c2c66affSColin Finck }
2451c2c66affSColin Finck break;
2452c2c66affSColin Finck case SGML_CATA_BASE:
2453c2c66affSColin Finck case SGML_CATA_CATALOG:
2454c2c66affSColin Finck case SGML_CATA_DOCUMENT:
2455c2c66affSColin Finck case SGML_CATA_SGMLDECL:
2456c2c66affSColin Finck cur = xmlParseSGMLCatalogPubid(cur, &sysid);
2457c2c66affSColin Finck if (cur == NULL) {
2458c2c66affSColin Finck /* error */
2459c2c66affSColin Finck break;
2460c2c66affSColin Finck }
2461c2c66affSColin Finck break;
2462c2c66affSColin Finck default:
2463c2c66affSColin Finck break;
2464c2c66affSColin Finck }
2465c2c66affSColin Finck if (cur == NULL) {
2466c2c66affSColin Finck if (name != NULL)
2467c2c66affSColin Finck xmlFree(name);
2468c2c66affSColin Finck if (sysid != NULL)
2469c2c66affSColin Finck xmlFree(sysid);
2470c2c66affSColin Finck break;
2471c2c66affSColin Finck } else if (type == SGML_CATA_BASE) {
2472c2c66affSColin Finck if (base != NULL)
2473c2c66affSColin Finck xmlFree(base);
2474c2c66affSColin Finck base = xmlStrdup(sysid);
2475c2c66affSColin Finck } else if ((type == SGML_CATA_PUBLIC) ||
2476c2c66affSColin Finck (type == SGML_CATA_SYSTEM)) {
2477c2c66affSColin Finck xmlChar *filename;
2478c2c66affSColin Finck
2479c2c66affSColin Finck filename = xmlBuildURI(sysid, base);
2480c2c66affSColin Finck if (filename != NULL) {
2481c2c66affSColin Finck xmlCatalogEntryPtr entry;
2482c2c66affSColin Finck
2483c2c66affSColin Finck entry = xmlNewCatalogEntry(type, name, filename,
2484c2c66affSColin Finck NULL, XML_CATA_PREFER_NONE, NULL);
2485c2c66affSColin Finck res = xmlHashAddEntry(catal->sgml, name, entry);
2486c2c66affSColin Finck if (res < 0) {
24875bb277a5SThomas Faber xmlFreeCatalogEntry(entry, NULL);
2488c2c66affSColin Finck }
2489c2c66affSColin Finck xmlFree(filename);
2490c2c66affSColin Finck }
2491c2c66affSColin Finck
2492c2c66affSColin Finck } else if (type == SGML_CATA_CATALOG) {
2493c2c66affSColin Finck if (super) {
2494c2c66affSColin Finck xmlCatalogEntryPtr entry;
2495c2c66affSColin Finck
2496c2c66affSColin Finck entry = xmlNewCatalogEntry(type, sysid, NULL, NULL,
2497c2c66affSColin Finck XML_CATA_PREFER_NONE, NULL);
2498c2c66affSColin Finck res = xmlHashAddEntry(catal->sgml, sysid, entry);
2499c2c66affSColin Finck if (res < 0) {
25005bb277a5SThomas Faber xmlFreeCatalogEntry(entry, NULL);
2501c2c66affSColin Finck }
2502c2c66affSColin Finck } else {
2503c2c66affSColin Finck xmlChar *filename;
2504c2c66affSColin Finck
2505c2c66affSColin Finck filename = xmlBuildURI(sysid, base);
2506c2c66affSColin Finck if (filename != NULL) {
2507c2c66affSColin Finck xmlExpandCatalog(catal, (const char *)filename);
2508c2c66affSColin Finck xmlFree(filename);
2509c2c66affSColin Finck }
2510c2c66affSColin Finck }
2511c2c66affSColin Finck }
2512c2c66affSColin Finck /*
2513c2c66affSColin Finck * drop anything else we won't handle it
2514c2c66affSColin Finck */
2515c2c66affSColin Finck if (name != NULL)
2516c2c66affSColin Finck xmlFree(name);
2517c2c66affSColin Finck if (sysid != NULL)
2518c2c66affSColin Finck xmlFree(sysid);
2519c2c66affSColin Finck }
2520c2c66affSColin Finck }
2521c2c66affSColin Finck if (base != NULL)
2522c2c66affSColin Finck xmlFree(base);
2523c2c66affSColin Finck if (cur == NULL)
2524c2c66affSColin Finck return(-1);
2525c2c66affSColin Finck return(0);
2526c2c66affSColin Finck }
2527c2c66affSColin Finck
2528c2c66affSColin Finck /************************************************************************
2529c2c66affSColin Finck * *
2530c2c66affSColin Finck * SGML Catalog handling *
2531c2c66affSColin Finck * *
2532c2c66affSColin Finck ************************************************************************/
2533c2c66affSColin Finck
2534c2c66affSColin Finck /**
2535c2c66affSColin Finck * xmlCatalogGetSGMLPublic:
2536c2c66affSColin Finck * @catal: an SGML catalog hash
2537c2c66affSColin Finck * @pubID: the public ID string
2538c2c66affSColin Finck *
2539c2c66affSColin Finck * Try to lookup the catalog local reference associated to a public ID
2540c2c66affSColin Finck *
2541c2c66affSColin Finck * Returns the local resource if found or NULL otherwise.
2542c2c66affSColin Finck */
2543c2c66affSColin Finck static const xmlChar *
xmlCatalogGetSGMLPublic(xmlHashTablePtr catal,const xmlChar * pubID)2544c2c66affSColin Finck xmlCatalogGetSGMLPublic(xmlHashTablePtr catal, const xmlChar *pubID) {
2545c2c66affSColin Finck xmlCatalogEntryPtr entry;
2546c2c66affSColin Finck xmlChar *normid;
2547c2c66affSColin Finck
2548c2c66affSColin Finck if (catal == NULL)
2549c2c66affSColin Finck return(NULL);
2550c2c66affSColin Finck
2551c2c66affSColin Finck normid = xmlCatalogNormalizePublic(pubID);
2552c2c66affSColin Finck if (normid != NULL)
2553c2c66affSColin Finck pubID = (*normid != 0 ? normid : NULL);
2554c2c66affSColin Finck
2555c2c66affSColin Finck entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, pubID);
2556c2c66affSColin Finck if (entry == NULL) {
2557c2c66affSColin Finck if (normid != NULL)
2558c2c66affSColin Finck xmlFree(normid);
2559c2c66affSColin Finck return(NULL);
2560c2c66affSColin Finck }
2561c2c66affSColin Finck if (entry->type == SGML_CATA_PUBLIC) {
2562c2c66affSColin Finck if (normid != NULL)
2563c2c66affSColin Finck xmlFree(normid);
2564c2c66affSColin Finck return(entry->URL);
2565c2c66affSColin Finck }
2566c2c66affSColin Finck if (normid != NULL)
2567c2c66affSColin Finck xmlFree(normid);
2568c2c66affSColin Finck return(NULL);
2569c2c66affSColin Finck }
2570c2c66affSColin Finck
2571c2c66affSColin Finck /**
2572c2c66affSColin Finck * xmlCatalogGetSGMLSystem:
2573c2c66affSColin Finck * @catal: an SGML catalog hash
2574c2c66affSColin Finck * @sysID: the system ID string
2575c2c66affSColin Finck *
2576c2c66affSColin Finck * Try to lookup the catalog local reference for a system ID
2577c2c66affSColin Finck *
2578c2c66affSColin Finck * Returns the local resource if found or NULL otherwise.
2579c2c66affSColin Finck */
2580c2c66affSColin Finck static const xmlChar *
xmlCatalogGetSGMLSystem(xmlHashTablePtr catal,const xmlChar * sysID)2581c2c66affSColin Finck xmlCatalogGetSGMLSystem(xmlHashTablePtr catal, const xmlChar *sysID) {
2582c2c66affSColin Finck xmlCatalogEntryPtr entry;
2583c2c66affSColin Finck
2584c2c66affSColin Finck if (catal == NULL)
2585c2c66affSColin Finck return(NULL);
2586c2c66affSColin Finck
2587c2c66affSColin Finck entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, sysID);
2588c2c66affSColin Finck if (entry == NULL)
2589c2c66affSColin Finck return(NULL);
2590c2c66affSColin Finck if (entry->type == SGML_CATA_SYSTEM)
2591c2c66affSColin Finck return(entry->URL);
2592c2c66affSColin Finck return(NULL);
2593c2c66affSColin Finck }
2594c2c66affSColin Finck
2595c2c66affSColin Finck /**
2596c2c66affSColin Finck * xmlCatalogSGMLResolve:
2597c2c66affSColin Finck * @catal: the SGML catalog
2598c2c66affSColin Finck * @pubID: the public ID string
2599c2c66affSColin Finck * @sysID: the system ID string
2600c2c66affSColin Finck *
2601c2c66affSColin Finck * Do a complete resolution lookup of an External Identifier
2602c2c66affSColin Finck *
2603c2c66affSColin Finck * Returns the URI of the resource or NULL if not found
2604c2c66affSColin Finck */
2605c2c66affSColin Finck static const xmlChar *
xmlCatalogSGMLResolve(xmlCatalogPtr catal,const xmlChar * pubID,const xmlChar * sysID)2606c2c66affSColin Finck xmlCatalogSGMLResolve(xmlCatalogPtr catal, const xmlChar *pubID,
2607c2c66affSColin Finck const xmlChar *sysID) {
2608c2c66affSColin Finck const xmlChar *ret = NULL;
2609c2c66affSColin Finck
2610c2c66affSColin Finck if (catal->sgml == NULL)
2611c2c66affSColin Finck return(NULL);
2612c2c66affSColin Finck
2613c2c66affSColin Finck if (pubID != NULL)
2614c2c66affSColin Finck ret = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
2615c2c66affSColin Finck if (ret != NULL)
2616c2c66affSColin Finck return(ret);
2617c2c66affSColin Finck if (sysID != NULL)
2618c2c66affSColin Finck ret = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
2619c2c66affSColin Finck if (ret != NULL)
2620c2c66affSColin Finck return(ret);
2621c2c66affSColin Finck return(NULL);
2622c2c66affSColin Finck }
2623c2c66affSColin Finck
2624c2c66affSColin Finck /************************************************************************
2625c2c66affSColin Finck * *
2626c2c66affSColin Finck * Specific Public interfaces *
2627c2c66affSColin Finck * *
2628c2c66affSColin Finck ************************************************************************/
2629c2c66affSColin Finck
2630c2c66affSColin Finck /**
2631c2c66affSColin Finck * xmlLoadSGMLSuperCatalog:
2632c2c66affSColin Finck * @filename: a file path
2633c2c66affSColin Finck *
2634c2c66affSColin Finck * Load an SGML super catalog. It won't expand CATALOG or DELEGATE
2635c2c66affSColin Finck * references. This is only needed for manipulating SGML Super Catalogs
2636c2c66affSColin Finck * like adding and removing CATALOG or DELEGATE entries.
2637c2c66affSColin Finck *
2638c2c66affSColin Finck * Returns the catalog parsed or NULL in case of error
2639c2c66affSColin Finck */
2640c2c66affSColin Finck xmlCatalogPtr
xmlLoadSGMLSuperCatalog(const char * filename)2641c2c66affSColin Finck xmlLoadSGMLSuperCatalog(const char *filename)
2642c2c66affSColin Finck {
2643c2c66affSColin Finck xmlChar *content;
2644c2c66affSColin Finck xmlCatalogPtr catal;
2645c2c66affSColin Finck int ret;
2646c2c66affSColin Finck
2647c2c66affSColin Finck content = xmlLoadFileContent(filename);
2648c2c66affSColin Finck if (content == NULL)
2649c2c66affSColin Finck return(NULL);
2650c2c66affSColin Finck
2651c2c66affSColin Finck catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
2652c2c66affSColin Finck if (catal == NULL) {
2653c2c66affSColin Finck xmlFree(content);
2654c2c66affSColin Finck return(NULL);
2655c2c66affSColin Finck }
2656c2c66affSColin Finck
2657c2c66affSColin Finck ret = xmlParseSGMLCatalog(catal, content, filename, 1);
2658c2c66affSColin Finck xmlFree(content);
2659c2c66affSColin Finck if (ret < 0) {
2660c2c66affSColin Finck xmlFreeCatalog(catal);
2661c2c66affSColin Finck return(NULL);
2662c2c66affSColin Finck }
2663c2c66affSColin Finck return (catal);
2664c2c66affSColin Finck }
2665c2c66affSColin Finck
2666c2c66affSColin Finck /**
2667c2c66affSColin Finck * xmlLoadACatalog:
2668c2c66affSColin Finck * @filename: a file path
2669c2c66affSColin Finck *
2670c2c66affSColin Finck * Load the catalog and build the associated data structures.
2671c2c66affSColin Finck * This can be either an XML Catalog or an SGML Catalog
2672c2c66affSColin Finck * It will recurse in SGML CATALOG entries. On the other hand XML
2673c2c66affSColin Finck * Catalogs are not handled recursively.
2674c2c66affSColin Finck *
2675c2c66affSColin Finck * Returns the catalog parsed or NULL in case of error
2676c2c66affSColin Finck */
2677c2c66affSColin Finck xmlCatalogPtr
xmlLoadACatalog(const char * filename)2678c2c66affSColin Finck xmlLoadACatalog(const char *filename)
2679c2c66affSColin Finck {
2680c2c66affSColin Finck xmlChar *content;
2681c2c66affSColin Finck xmlChar *first;
2682c2c66affSColin Finck xmlCatalogPtr catal;
2683c2c66affSColin Finck int ret;
2684c2c66affSColin Finck
2685c2c66affSColin Finck content = xmlLoadFileContent(filename);
2686c2c66affSColin Finck if (content == NULL)
2687c2c66affSColin Finck return(NULL);
2688c2c66affSColin Finck
2689c2c66affSColin Finck
2690c2c66affSColin Finck first = content;
2691c2c66affSColin Finck
2692c2c66affSColin Finck while ((*first != 0) && (*first != '-') && (*first != '<') &&
2693c2c66affSColin Finck (!(((*first >= 'A') && (*first <= 'Z')) ||
2694c2c66affSColin Finck ((*first >= 'a') && (*first <= 'z')))))
2695c2c66affSColin Finck first++;
2696c2c66affSColin Finck
2697c2c66affSColin Finck if (*first != '<') {
2698c2c66affSColin Finck catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
2699c2c66affSColin Finck if (catal == NULL) {
2700c2c66affSColin Finck xmlFree(content);
2701c2c66affSColin Finck return(NULL);
2702c2c66affSColin Finck }
2703c2c66affSColin Finck ret = xmlParseSGMLCatalog(catal, content, filename, 0);
2704c2c66affSColin Finck if (ret < 0) {
2705c2c66affSColin Finck xmlFreeCatalog(catal);
2706c2c66affSColin Finck xmlFree(content);
2707c2c66affSColin Finck return(NULL);
2708c2c66affSColin Finck }
2709c2c66affSColin Finck } else {
2710c2c66affSColin Finck catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
2711c2c66affSColin Finck if (catal == NULL) {
2712c2c66affSColin Finck xmlFree(content);
2713c2c66affSColin Finck return(NULL);
2714c2c66affSColin Finck }
2715c2c66affSColin Finck catal->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
2716c2c66affSColin Finck NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
2717c2c66affSColin Finck }
2718c2c66affSColin Finck xmlFree(content);
2719c2c66affSColin Finck return (catal);
2720c2c66affSColin Finck }
2721c2c66affSColin Finck
2722c2c66affSColin Finck /**
2723c2c66affSColin Finck * xmlExpandCatalog:
2724c2c66affSColin Finck * @catal: a catalog
2725c2c66affSColin Finck * @filename: a file path
2726c2c66affSColin Finck *
2727c2c66affSColin Finck * Load the catalog and expand the existing catal structure.
2728c2c66affSColin Finck * This can be either an XML Catalog or an SGML Catalog
2729c2c66affSColin Finck *
2730c2c66affSColin Finck * Returns 0 in case of success, -1 in case of error
2731c2c66affSColin Finck */
2732c2c66affSColin Finck static int
xmlExpandCatalog(xmlCatalogPtr catal,const char * filename)2733c2c66affSColin Finck xmlExpandCatalog(xmlCatalogPtr catal, const char *filename)
2734c2c66affSColin Finck {
2735c2c66affSColin Finck int ret;
2736c2c66affSColin Finck
2737c2c66affSColin Finck if ((catal == NULL) || (filename == NULL))
2738c2c66affSColin Finck return(-1);
2739c2c66affSColin Finck
2740c2c66affSColin Finck
2741c2c66affSColin Finck if (catal->type == XML_SGML_CATALOG_TYPE) {
2742c2c66affSColin Finck xmlChar *content;
2743c2c66affSColin Finck
2744c2c66affSColin Finck content = xmlLoadFileContent(filename);
2745c2c66affSColin Finck if (content == NULL)
2746c2c66affSColin Finck return(-1);
2747c2c66affSColin Finck
2748c2c66affSColin Finck ret = xmlParseSGMLCatalog(catal, content, filename, 0);
2749c2c66affSColin Finck if (ret < 0) {
2750c2c66affSColin Finck xmlFree(content);
2751c2c66affSColin Finck return(-1);
2752c2c66affSColin Finck }
2753c2c66affSColin Finck xmlFree(content);
2754c2c66affSColin Finck } else {
2755c2c66affSColin Finck xmlCatalogEntryPtr tmp, cur;
2756c2c66affSColin Finck tmp = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
2757c2c66affSColin Finck NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
2758c2c66affSColin Finck
2759c2c66affSColin Finck cur = catal->xml;
2760c2c66affSColin Finck if (cur == NULL) {
2761c2c66affSColin Finck catal->xml = tmp;
2762c2c66affSColin Finck } else {
2763c2c66affSColin Finck while (cur->next != NULL) cur = cur->next;
2764c2c66affSColin Finck cur->next = tmp;
2765c2c66affSColin Finck }
2766c2c66affSColin Finck }
2767c2c66affSColin Finck return (0);
2768c2c66affSColin Finck }
2769c2c66affSColin Finck
2770c2c66affSColin Finck /**
2771c2c66affSColin Finck * xmlACatalogResolveSystem:
2772c2c66affSColin Finck * @catal: a Catalog
2773c2c66affSColin Finck * @sysID: the system ID string
2774c2c66affSColin Finck *
2775c2c66affSColin Finck * Try to lookup the catalog resource for a system ID
2776c2c66affSColin Finck *
2777c2c66affSColin Finck * Returns the resource if found or NULL otherwise, the value returned
2778c2c66affSColin Finck * must be freed by the caller.
2779c2c66affSColin Finck */
2780c2c66affSColin Finck xmlChar *
xmlACatalogResolveSystem(xmlCatalogPtr catal,const xmlChar * sysID)2781c2c66affSColin Finck xmlACatalogResolveSystem(xmlCatalogPtr catal, const xmlChar *sysID) {
2782c2c66affSColin Finck xmlChar *ret = NULL;
2783c2c66affSColin Finck
2784c2c66affSColin Finck if ((sysID == NULL) || (catal == NULL))
2785c2c66affSColin Finck return(NULL);
2786c2c66affSColin Finck
2787c2c66affSColin Finck if (xmlDebugCatalogs)
2788c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
2789c2c66affSColin Finck "Resolve sysID %s\n", sysID);
2790c2c66affSColin Finck
2791c2c66affSColin Finck if (catal->type == XML_XML_CATALOG_TYPE) {
2792c2c66affSColin Finck ret = xmlCatalogListXMLResolve(catal->xml, NULL, sysID);
2793c2c66affSColin Finck if (ret == XML_CATAL_BREAK)
2794c2c66affSColin Finck ret = NULL;
2795c2c66affSColin Finck } else {
2796c2c66affSColin Finck const xmlChar *sgml;
2797c2c66affSColin Finck
2798c2c66affSColin Finck sgml = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
2799c2c66affSColin Finck if (sgml != NULL)
2800c2c66affSColin Finck ret = xmlStrdup(sgml);
2801c2c66affSColin Finck }
2802c2c66affSColin Finck return(ret);
2803c2c66affSColin Finck }
2804c2c66affSColin Finck
2805c2c66affSColin Finck /**
2806c2c66affSColin Finck * xmlACatalogResolvePublic:
2807c2c66affSColin Finck * @catal: a Catalog
2808c2c66affSColin Finck * @pubID: the public ID string
2809c2c66affSColin Finck *
2810c2c66affSColin Finck * Try to lookup the catalog local reference associated to a public ID in that catalog
2811c2c66affSColin Finck *
2812c2c66affSColin Finck * Returns the local resource if found or NULL otherwise, the value returned
2813c2c66affSColin Finck * must be freed by the caller.
2814c2c66affSColin Finck */
2815c2c66affSColin Finck xmlChar *
xmlACatalogResolvePublic(xmlCatalogPtr catal,const xmlChar * pubID)2816c2c66affSColin Finck xmlACatalogResolvePublic(xmlCatalogPtr catal, const xmlChar *pubID) {
2817c2c66affSColin Finck xmlChar *ret = NULL;
2818c2c66affSColin Finck
2819c2c66affSColin Finck if ((pubID == NULL) || (catal == NULL))
2820c2c66affSColin Finck return(NULL);
2821c2c66affSColin Finck
2822c2c66affSColin Finck if (xmlDebugCatalogs)
2823c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
2824c2c66affSColin Finck "Resolve pubID %s\n", pubID);
2825c2c66affSColin Finck
2826c2c66affSColin Finck if (catal->type == XML_XML_CATALOG_TYPE) {
2827c2c66affSColin Finck ret = xmlCatalogListXMLResolve(catal->xml, pubID, NULL);
2828c2c66affSColin Finck if (ret == XML_CATAL_BREAK)
2829c2c66affSColin Finck ret = NULL;
2830c2c66affSColin Finck } else {
2831c2c66affSColin Finck const xmlChar *sgml;
2832c2c66affSColin Finck
2833c2c66affSColin Finck sgml = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
2834c2c66affSColin Finck if (sgml != NULL)
2835c2c66affSColin Finck ret = xmlStrdup(sgml);
2836c2c66affSColin Finck }
2837c2c66affSColin Finck return(ret);
2838c2c66affSColin Finck }
2839c2c66affSColin Finck
2840c2c66affSColin Finck /**
2841c2c66affSColin Finck * xmlACatalogResolve:
2842c2c66affSColin Finck * @catal: a Catalog
2843c2c66affSColin Finck * @pubID: the public ID string
2844c2c66affSColin Finck * @sysID: the system ID string
2845c2c66affSColin Finck *
2846c2c66affSColin Finck * Do a complete resolution lookup of an External Identifier
2847c2c66affSColin Finck *
2848c2c66affSColin Finck * Returns the URI of the resource or NULL if not found, it must be freed
2849c2c66affSColin Finck * by the caller.
2850c2c66affSColin Finck */
2851c2c66affSColin Finck xmlChar *
xmlACatalogResolve(xmlCatalogPtr catal,const xmlChar * pubID,const xmlChar * sysID)2852c2c66affSColin Finck xmlACatalogResolve(xmlCatalogPtr catal, const xmlChar * pubID,
2853c2c66affSColin Finck const xmlChar * sysID)
2854c2c66affSColin Finck {
2855c2c66affSColin Finck xmlChar *ret = NULL;
2856c2c66affSColin Finck
2857c2c66affSColin Finck if (((pubID == NULL) && (sysID == NULL)) || (catal == NULL))
2858c2c66affSColin Finck return (NULL);
2859c2c66affSColin Finck
2860c2c66affSColin Finck if (xmlDebugCatalogs) {
2861c2c66affSColin Finck if ((pubID != NULL) && (sysID != NULL)) {
2862c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
2863c2c66affSColin Finck "Resolve: pubID %s sysID %s\n", pubID, sysID);
2864c2c66affSColin Finck } else if (pubID != NULL) {
2865c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
2866c2c66affSColin Finck "Resolve: pubID %s\n", pubID);
2867c2c66affSColin Finck } else {
2868c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
2869c2c66affSColin Finck "Resolve: sysID %s\n", sysID);
2870c2c66affSColin Finck }
2871c2c66affSColin Finck }
2872c2c66affSColin Finck
2873c2c66affSColin Finck if (catal->type == XML_XML_CATALOG_TYPE) {
2874c2c66affSColin Finck ret = xmlCatalogListXMLResolve(catal->xml, pubID, sysID);
2875c2c66affSColin Finck if (ret == XML_CATAL_BREAK)
2876c2c66affSColin Finck ret = NULL;
2877c2c66affSColin Finck } else {
2878c2c66affSColin Finck const xmlChar *sgml;
2879c2c66affSColin Finck
2880c2c66affSColin Finck sgml = xmlCatalogSGMLResolve(catal, pubID, sysID);
2881c2c66affSColin Finck if (sgml != NULL)
2882c2c66affSColin Finck ret = xmlStrdup(sgml);
2883c2c66affSColin Finck }
2884c2c66affSColin Finck return (ret);
2885c2c66affSColin Finck }
2886c2c66affSColin Finck
2887c2c66affSColin Finck /**
2888c2c66affSColin Finck * xmlACatalogResolveURI:
2889c2c66affSColin Finck * @catal: a Catalog
2890c2c66affSColin Finck * @URI: the URI
2891c2c66affSColin Finck *
2892c2c66affSColin Finck * Do a complete resolution lookup of an URI
2893c2c66affSColin Finck *
2894c2c66affSColin Finck * Returns the URI of the resource or NULL if not found, it must be freed
2895c2c66affSColin Finck * by the caller.
2896c2c66affSColin Finck */
2897c2c66affSColin Finck xmlChar *
xmlACatalogResolveURI(xmlCatalogPtr catal,const xmlChar * URI)2898c2c66affSColin Finck xmlACatalogResolveURI(xmlCatalogPtr catal, const xmlChar *URI) {
2899c2c66affSColin Finck xmlChar *ret = NULL;
2900c2c66affSColin Finck
2901c2c66affSColin Finck if ((URI == NULL) || (catal == NULL))
2902c2c66affSColin Finck return(NULL);
2903c2c66affSColin Finck
2904c2c66affSColin Finck if (xmlDebugCatalogs)
2905c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
2906c2c66affSColin Finck "Resolve URI %s\n", URI);
2907c2c66affSColin Finck
2908c2c66affSColin Finck if (catal->type == XML_XML_CATALOG_TYPE) {
2909c2c66affSColin Finck ret = xmlCatalogListXMLResolveURI(catal->xml, URI);
2910c2c66affSColin Finck if (ret == XML_CATAL_BREAK)
2911c2c66affSColin Finck ret = NULL;
2912c2c66affSColin Finck } else {
2913c2c66affSColin Finck const xmlChar *sgml;
2914c2c66affSColin Finck
2915c2c66affSColin Finck sgml = xmlCatalogSGMLResolve(catal, NULL, URI);
2916c2c66affSColin Finck if (sgml != NULL)
2917c2c66affSColin Finck ret = xmlStrdup(sgml);
2918c2c66affSColin Finck }
2919c2c66affSColin Finck return(ret);
2920c2c66affSColin Finck }
2921c2c66affSColin Finck
2922c2c66affSColin Finck #ifdef LIBXML_OUTPUT_ENABLED
2923c2c66affSColin Finck /**
2924c2c66affSColin Finck * xmlACatalogDump:
2925c2c66affSColin Finck * @catal: a Catalog
2926c2c66affSColin Finck * @out: the file.
2927c2c66affSColin Finck *
2928c2c66affSColin Finck * Dump the given catalog to the given file.
2929c2c66affSColin Finck */
2930c2c66affSColin Finck void
xmlACatalogDump(xmlCatalogPtr catal,FILE * out)2931c2c66affSColin Finck xmlACatalogDump(xmlCatalogPtr catal, FILE *out) {
2932c2c66affSColin Finck if ((out == NULL) || (catal == NULL))
2933c2c66affSColin Finck return;
2934c2c66affSColin Finck
2935c2c66affSColin Finck if (catal->type == XML_XML_CATALOG_TYPE) {
2936c2c66affSColin Finck xmlDumpXMLCatalog(out, catal->xml);
2937c2c66affSColin Finck } else {
29385bb277a5SThomas Faber xmlHashScan(catal->sgml, xmlCatalogDumpEntry, out);
2939c2c66affSColin Finck }
2940c2c66affSColin Finck }
2941c2c66affSColin Finck #endif /* LIBXML_OUTPUT_ENABLED */
2942c2c66affSColin Finck
2943c2c66affSColin Finck /**
2944c2c66affSColin Finck * xmlACatalogAdd:
2945c2c66affSColin Finck * @catal: a Catalog
2946c2c66affSColin Finck * @type: the type of record to add to the catalog
2947c2c66affSColin Finck * @orig: the system, public or prefix to match
2948c2c66affSColin Finck * @replace: the replacement value for the match
2949c2c66affSColin Finck *
2950c2c66affSColin Finck * Add an entry in the catalog, it may overwrite existing but
2951c2c66affSColin Finck * different entries.
2952c2c66affSColin Finck *
2953c2c66affSColin Finck * Returns 0 if successful, -1 otherwise
2954c2c66affSColin Finck */
2955c2c66affSColin Finck int
xmlACatalogAdd(xmlCatalogPtr catal,const xmlChar * type,const xmlChar * orig,const xmlChar * replace)2956c2c66affSColin Finck xmlACatalogAdd(xmlCatalogPtr catal, const xmlChar * type,
2957c2c66affSColin Finck const xmlChar * orig, const xmlChar * replace)
2958c2c66affSColin Finck {
2959c2c66affSColin Finck int res = -1;
2960c2c66affSColin Finck
2961c2c66affSColin Finck if (catal == NULL)
2962c2c66affSColin Finck return(-1);
2963c2c66affSColin Finck
2964c2c66affSColin Finck if (catal->type == XML_XML_CATALOG_TYPE) {
2965c2c66affSColin Finck res = xmlAddXMLCatalog(catal->xml, type, orig, replace);
2966c2c66affSColin Finck } else {
2967c2c66affSColin Finck xmlCatalogEntryType cattype;
2968c2c66affSColin Finck
2969c2c66affSColin Finck cattype = xmlGetSGMLCatalogEntryType(type);
2970c2c66affSColin Finck if (cattype != XML_CATA_NONE) {
2971c2c66affSColin Finck xmlCatalogEntryPtr entry;
2972c2c66affSColin Finck
2973c2c66affSColin Finck entry = xmlNewCatalogEntry(cattype, orig, replace, NULL,
2974c2c66affSColin Finck XML_CATA_PREFER_NONE, NULL);
2975c2c66affSColin Finck if (catal->sgml == NULL)
2976c2c66affSColin Finck catal->sgml = xmlHashCreate(10);
2977c2c66affSColin Finck res = xmlHashAddEntry(catal->sgml, orig, entry);
2978c2c66affSColin Finck }
2979c2c66affSColin Finck }
2980c2c66affSColin Finck return (res);
2981c2c66affSColin Finck }
2982c2c66affSColin Finck
2983c2c66affSColin Finck /**
2984c2c66affSColin Finck * xmlACatalogRemove:
2985c2c66affSColin Finck * @catal: a Catalog
2986c2c66affSColin Finck * @value: the value to remove
2987c2c66affSColin Finck *
2988c2c66affSColin Finck * Remove an entry from the catalog
2989c2c66affSColin Finck *
2990c2c66affSColin Finck * Returns the number of entries removed if successful, -1 otherwise
2991c2c66affSColin Finck */
2992c2c66affSColin Finck int
xmlACatalogRemove(xmlCatalogPtr catal,const xmlChar * value)2993c2c66affSColin Finck xmlACatalogRemove(xmlCatalogPtr catal, const xmlChar *value) {
2994c2c66affSColin Finck int res = -1;
2995c2c66affSColin Finck
2996c2c66affSColin Finck if ((catal == NULL) || (value == NULL))
2997c2c66affSColin Finck return(-1);
2998c2c66affSColin Finck
2999c2c66affSColin Finck if (catal->type == XML_XML_CATALOG_TYPE) {
3000c2c66affSColin Finck res = xmlDelXMLCatalog(catal->xml, value);
3001c2c66affSColin Finck } else {
30025bb277a5SThomas Faber res = xmlHashRemoveEntry(catal->sgml, value, xmlFreeCatalogEntry);
3003c2c66affSColin Finck if (res == 0)
3004c2c66affSColin Finck res = 1;
3005c2c66affSColin Finck }
3006c2c66affSColin Finck return(res);
3007c2c66affSColin Finck }
3008c2c66affSColin Finck
3009c2c66affSColin Finck /**
3010c2c66affSColin Finck * xmlNewCatalog:
3011c2c66affSColin Finck * @sgml: should this create an SGML catalog
3012c2c66affSColin Finck *
3013c2c66affSColin Finck * create a new Catalog.
3014c2c66affSColin Finck *
3015c2c66affSColin Finck * Returns the xmlCatalogPtr or NULL in case of error
3016c2c66affSColin Finck */
3017c2c66affSColin Finck xmlCatalogPtr
xmlNewCatalog(int sgml)3018c2c66affSColin Finck xmlNewCatalog(int sgml) {
3019c2c66affSColin Finck xmlCatalogPtr catal = NULL;
3020c2c66affSColin Finck
3021c2c66affSColin Finck if (sgml) {
3022c2c66affSColin Finck catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE,
3023c2c66affSColin Finck xmlCatalogDefaultPrefer);
3024c2c66affSColin Finck if ((catal != NULL) && (catal->sgml == NULL))
3025c2c66affSColin Finck catal->sgml = xmlHashCreate(10);
3026c2c66affSColin Finck } else
3027c2c66affSColin Finck catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3028c2c66affSColin Finck xmlCatalogDefaultPrefer);
3029c2c66affSColin Finck return(catal);
3030c2c66affSColin Finck }
3031c2c66affSColin Finck
3032c2c66affSColin Finck /**
3033c2c66affSColin Finck * xmlCatalogIsEmpty:
3034c2c66affSColin Finck * @catal: should this create an SGML catalog
3035c2c66affSColin Finck *
3036c2c66affSColin Finck * Check is a catalog is empty
3037c2c66affSColin Finck *
3038c2c66affSColin Finck * Returns 1 if the catalog is empty, 0 if not, amd -1 in case of error.
3039c2c66affSColin Finck */
3040c2c66affSColin Finck int
xmlCatalogIsEmpty(xmlCatalogPtr catal)3041c2c66affSColin Finck xmlCatalogIsEmpty(xmlCatalogPtr catal) {
3042c2c66affSColin Finck if (catal == NULL)
3043c2c66affSColin Finck return(-1);
3044c2c66affSColin Finck
3045c2c66affSColin Finck if (catal->type == XML_XML_CATALOG_TYPE) {
3046c2c66affSColin Finck if (catal->xml == NULL)
3047c2c66affSColin Finck return(1);
3048c2c66affSColin Finck if ((catal->xml->type != XML_CATA_CATALOG) &&
3049c2c66affSColin Finck (catal->xml->type != XML_CATA_BROKEN_CATALOG))
3050c2c66affSColin Finck return(-1);
3051c2c66affSColin Finck if (catal->xml->children == NULL)
3052c2c66affSColin Finck return(1);
3053c2c66affSColin Finck return(0);
3054c2c66affSColin Finck } else {
3055c2c66affSColin Finck int res;
3056c2c66affSColin Finck
3057c2c66affSColin Finck if (catal->sgml == NULL)
3058c2c66affSColin Finck return(1);
3059c2c66affSColin Finck res = xmlHashSize(catal->sgml);
3060c2c66affSColin Finck if (res == 0)
3061c2c66affSColin Finck return(1);
3062c2c66affSColin Finck if (res < 0)
3063c2c66affSColin Finck return(-1);
3064c2c66affSColin Finck }
3065c2c66affSColin Finck return(0);
3066c2c66affSColin Finck }
3067c2c66affSColin Finck
3068c2c66affSColin Finck /************************************************************************
3069c2c66affSColin Finck * *
3070c2c66affSColin Finck * Public interfaces manipulating the global shared default catalog *
3071c2c66affSColin Finck * *
3072c2c66affSColin Finck ************************************************************************/
3073c2c66affSColin Finck
3074c2c66affSColin Finck /**
3075c2c66affSColin Finck * xmlInitializeCatalogData:
3076c2c66affSColin Finck *
3077c2c66affSColin Finck * Do the catalog initialization only of global data, doesn't try to load
3078c2c66affSColin Finck * any catalog actually.
3079c2c66affSColin Finck * this function is not thread safe, catalog initialization should
3080c2c66affSColin Finck * preferably be done once at startup
3081c2c66affSColin Finck */
3082c2c66affSColin Finck static void
xmlInitializeCatalogData(void)3083c2c66affSColin Finck xmlInitializeCatalogData(void) {
3084c2c66affSColin Finck if (xmlCatalogInitialized != 0)
3085c2c66affSColin Finck return;
3086c2c66affSColin Finck
3087c2c66affSColin Finck if (getenv("XML_DEBUG_CATALOG"))
3088c2c66affSColin Finck xmlDebugCatalogs = 1;
3089c2c66affSColin Finck xmlCatalogMutex = xmlNewRMutex();
3090c2c66affSColin Finck
3091c2c66affSColin Finck xmlCatalogInitialized = 1;
3092c2c66affSColin Finck }
3093c2c66affSColin Finck /**
3094c2c66affSColin Finck * xmlInitializeCatalog:
3095c2c66affSColin Finck *
3096c2c66affSColin Finck * Do the catalog initialization.
3097c2c66affSColin Finck * this function is not thread safe, catalog initialization should
3098c2c66affSColin Finck * preferably be done once at startup
3099c2c66affSColin Finck */
3100c2c66affSColin Finck void
xmlInitializeCatalog(void)3101c2c66affSColin Finck xmlInitializeCatalog(void) {
3102c2c66affSColin Finck if (xmlCatalogInitialized != 0)
3103c2c66affSColin Finck return;
3104c2c66affSColin Finck
3105c2c66affSColin Finck xmlInitializeCatalogData();
3106c2c66affSColin Finck xmlRMutexLock(xmlCatalogMutex);
3107c2c66affSColin Finck
3108c2c66affSColin Finck if (getenv("XML_DEBUG_CATALOG"))
3109c2c66affSColin Finck xmlDebugCatalogs = 1;
3110c2c66affSColin Finck
3111c2c66affSColin Finck if (xmlDefaultCatalog == NULL) {
3112c2c66affSColin Finck const char *catalogs;
3113c2c66affSColin Finck char *path;
3114c2c66affSColin Finck const char *cur, *paths;
3115c2c66affSColin Finck xmlCatalogPtr catal;
3116c2c66affSColin Finck xmlCatalogEntryPtr *nextent;
3117c2c66affSColin Finck
3118c2c66affSColin Finck catalogs = (const char *) getenv("XML_CATALOG_FILES");
3119c2c66affSColin Finck if (catalogs == NULL)
3120c2c66affSColin Finck #if defined(_WIN32) && defined(_MSC_VER)
3121c2c66affSColin Finck {
3122c2c66affSColin Finck void* hmodule;
3123c2c66affSColin Finck hmodule = GetModuleHandleA("libxml2.dll");
3124c2c66affSColin Finck if (hmodule == NULL)
3125c2c66affSColin Finck hmodule = GetModuleHandleA(NULL);
3126c2c66affSColin Finck if (hmodule != NULL) {
3127c2c66affSColin Finck char buf[256];
3128c2c66affSColin Finck unsigned long len = GetModuleFileNameA(hmodule, buf, 255);
3129c2c66affSColin Finck if (len != 0) {
3130c2c66affSColin Finck char* p = &(buf[len]);
3131c2c66affSColin Finck while (*p != '\\' && p > buf)
3132c2c66affSColin Finck p--;
3133c2c66affSColin Finck if (p != buf) {
3134c2c66affSColin Finck xmlChar* uri;
3135c2c66affSColin Finck strncpy(p, "\\..\\etc\\catalog", 255 - (p - buf));
3136c2c66affSColin Finck uri = xmlCanonicPath((const xmlChar*)buf);
3137c2c66affSColin Finck if (uri != NULL) {
3138c2c66affSColin Finck strncpy(XML_XML_DEFAULT_CATALOG, uri, 255);
3139c2c66affSColin Finck xmlFree(uri);
3140c2c66affSColin Finck }
3141c2c66affSColin Finck }
3142c2c66affSColin Finck }
3143c2c66affSColin Finck }
3144c2c66affSColin Finck catalogs = XML_XML_DEFAULT_CATALOG;
3145c2c66affSColin Finck }
3146c2c66affSColin Finck #else
3147c2c66affSColin Finck catalogs = XML_XML_DEFAULT_CATALOG;
3148c2c66affSColin Finck #endif
3149c2c66affSColin Finck
3150c2c66affSColin Finck catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3151c2c66affSColin Finck xmlCatalogDefaultPrefer);
3152c2c66affSColin Finck if (catal != NULL) {
3153c2c66affSColin Finck /* the XML_CATALOG_FILES envvar is allowed to contain a
3154c2c66affSColin Finck space-separated list of entries. */
3155c2c66affSColin Finck cur = catalogs;
3156c2c66affSColin Finck nextent = &catal->xml;
3157c2c66affSColin Finck while (*cur != '\0') {
3158c2c66affSColin Finck while (xmlIsBlank_ch(*cur))
3159c2c66affSColin Finck cur++;
3160c2c66affSColin Finck if (*cur != 0) {
3161c2c66affSColin Finck paths = cur;
3162c2c66affSColin Finck while ((*cur != 0) && (!xmlIsBlank_ch(*cur)))
3163c2c66affSColin Finck cur++;
3164c2c66affSColin Finck path = (char *) xmlStrndup((const xmlChar *)paths, cur - paths);
3165c2c66affSColin Finck if (path != NULL) {
3166c2c66affSColin Finck *nextent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
3167c2c66affSColin Finck NULL, BAD_CAST path, xmlCatalogDefaultPrefer, NULL);
3168c2c66affSColin Finck if (*nextent != NULL)
3169c2c66affSColin Finck nextent = &((*nextent)->next);
3170c2c66affSColin Finck xmlFree(path);
3171c2c66affSColin Finck }
3172c2c66affSColin Finck }
3173c2c66affSColin Finck }
3174c2c66affSColin Finck xmlDefaultCatalog = catal;
3175c2c66affSColin Finck }
3176c2c66affSColin Finck }
3177c2c66affSColin Finck
3178c2c66affSColin Finck xmlRMutexUnlock(xmlCatalogMutex);
3179c2c66affSColin Finck }
3180c2c66affSColin Finck
3181c2c66affSColin Finck
3182c2c66affSColin Finck /**
3183c2c66affSColin Finck * xmlLoadCatalog:
3184c2c66affSColin Finck * @filename: a file path
3185c2c66affSColin Finck *
3186c2c66affSColin Finck * Load the catalog and makes its definitions effective for the default
3187c2c66affSColin Finck * external entity loader. It will recurse in SGML CATALOG entries.
3188c2c66affSColin Finck * this function is not thread safe, catalog initialization should
3189c2c66affSColin Finck * preferably be done once at startup
3190c2c66affSColin Finck *
3191c2c66affSColin Finck * Returns 0 in case of success -1 in case of error
3192c2c66affSColin Finck */
3193c2c66affSColin Finck int
xmlLoadCatalog(const char * filename)3194c2c66affSColin Finck xmlLoadCatalog(const char *filename)
3195c2c66affSColin Finck {
3196c2c66affSColin Finck int ret;
3197c2c66affSColin Finck xmlCatalogPtr catal;
3198c2c66affSColin Finck
3199c2c66affSColin Finck if (!xmlCatalogInitialized)
3200c2c66affSColin Finck xmlInitializeCatalogData();
3201c2c66affSColin Finck
3202c2c66affSColin Finck xmlRMutexLock(xmlCatalogMutex);
3203c2c66affSColin Finck
3204c2c66affSColin Finck if (xmlDefaultCatalog == NULL) {
3205c2c66affSColin Finck catal = xmlLoadACatalog(filename);
3206c2c66affSColin Finck if (catal == NULL) {
3207c2c66affSColin Finck xmlRMutexUnlock(xmlCatalogMutex);
3208c2c66affSColin Finck return(-1);
3209c2c66affSColin Finck }
3210c2c66affSColin Finck
3211c2c66affSColin Finck xmlDefaultCatalog = catal;
3212c2c66affSColin Finck xmlRMutexUnlock(xmlCatalogMutex);
3213c2c66affSColin Finck return(0);
3214c2c66affSColin Finck }
3215c2c66affSColin Finck
3216c2c66affSColin Finck ret = xmlExpandCatalog(xmlDefaultCatalog, filename);
3217c2c66affSColin Finck xmlRMutexUnlock(xmlCatalogMutex);
3218c2c66affSColin Finck return(ret);
3219c2c66affSColin Finck }
3220c2c66affSColin Finck
3221c2c66affSColin Finck /**
3222c2c66affSColin Finck * xmlLoadCatalogs:
3223c2c66affSColin Finck * @pathss: a list of directories separated by a colon or a space.
3224c2c66affSColin Finck *
3225c2c66affSColin Finck * Load the catalogs and makes their definitions effective for the default
3226c2c66affSColin Finck * external entity loader.
3227c2c66affSColin Finck * this function is not thread safe, catalog initialization should
3228c2c66affSColin Finck * preferably be done once at startup
3229c2c66affSColin Finck */
3230c2c66affSColin Finck void
xmlLoadCatalogs(const char * pathss)3231c2c66affSColin Finck xmlLoadCatalogs(const char *pathss) {
3232c2c66affSColin Finck const char *cur;
3233c2c66affSColin Finck const char *paths;
3234c2c66affSColin Finck xmlChar *path;
3235c2c66affSColin Finck #ifdef _WIN32
3236c2c66affSColin Finck int i, iLen;
3237c2c66affSColin Finck #endif
3238c2c66affSColin Finck
3239c2c66affSColin Finck if (pathss == NULL)
3240c2c66affSColin Finck return;
3241c2c66affSColin Finck
3242c2c66affSColin Finck cur = pathss;
3243c2c66affSColin Finck while (*cur != 0) {
3244c2c66affSColin Finck while (xmlIsBlank_ch(*cur)) cur++;
3245c2c66affSColin Finck if (*cur != 0) {
3246c2c66affSColin Finck paths = cur;
3247c2c66affSColin Finck while ((*cur != 0) && (*cur != PATH_SEPARATOR) && (!xmlIsBlank_ch(*cur)))
3248c2c66affSColin Finck cur++;
3249c2c66affSColin Finck path = xmlStrndup((const xmlChar *)paths, cur - paths);
325040ee59d6SThomas Faber if (path != NULL) {
3251c2c66affSColin Finck #ifdef _WIN32
3252c2c66affSColin Finck iLen = strlen((const char*)path);
3253c2c66affSColin Finck for(i = 0; i < iLen; i++) {
3254c2c66affSColin Finck if(path[i] == '\\') {
3255c2c66affSColin Finck path[i] = '/';
3256c2c66affSColin Finck }
3257c2c66affSColin Finck }
3258c2c66affSColin Finck #endif
3259c2c66affSColin Finck xmlLoadCatalog((const char *) path);
3260c2c66affSColin Finck xmlFree(path);
3261c2c66affSColin Finck }
3262c2c66affSColin Finck }
3263c2c66affSColin Finck while (*cur == PATH_SEPARATOR)
3264c2c66affSColin Finck cur++;
3265c2c66affSColin Finck }
3266c2c66affSColin Finck }
3267c2c66affSColin Finck
3268c2c66affSColin Finck /**
3269c2c66affSColin Finck * xmlCatalogCleanup:
3270c2c66affSColin Finck *
3271c2c66affSColin Finck * Free up all the memory associated with catalogs
3272c2c66affSColin Finck */
3273c2c66affSColin Finck void
xmlCatalogCleanup(void)3274c2c66affSColin Finck xmlCatalogCleanup(void) {
3275c2c66affSColin Finck if (xmlCatalogInitialized == 0)
3276c2c66affSColin Finck return;
3277c2c66affSColin Finck
3278c2c66affSColin Finck xmlRMutexLock(xmlCatalogMutex);
3279c2c66affSColin Finck if (xmlDebugCatalogs)
3280c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
3281c2c66affSColin Finck "Catalogs cleanup\n");
3282c2c66affSColin Finck if (xmlCatalogXMLFiles != NULL)
32835bb277a5SThomas Faber xmlHashFree(xmlCatalogXMLFiles, xmlFreeCatalogHashEntryList);
3284c2c66affSColin Finck xmlCatalogXMLFiles = NULL;
3285c2c66affSColin Finck if (xmlDefaultCatalog != NULL)
3286c2c66affSColin Finck xmlFreeCatalog(xmlDefaultCatalog);
3287c2c66affSColin Finck xmlDefaultCatalog = NULL;
3288c2c66affSColin Finck xmlDebugCatalogs = 0;
3289c2c66affSColin Finck xmlCatalogInitialized = 0;
3290c2c66affSColin Finck xmlRMutexUnlock(xmlCatalogMutex);
3291c2c66affSColin Finck xmlFreeRMutex(xmlCatalogMutex);
3292c2c66affSColin Finck }
3293c2c66affSColin Finck
3294c2c66affSColin Finck /**
3295c2c66affSColin Finck * xmlCatalogResolveSystem:
3296c2c66affSColin Finck * @sysID: the system ID string
3297c2c66affSColin Finck *
3298c2c66affSColin Finck * Try to lookup the catalog resource for a system ID
3299c2c66affSColin Finck *
3300c2c66affSColin Finck * Returns the resource if found or NULL otherwise, the value returned
3301c2c66affSColin Finck * must be freed by the caller.
3302c2c66affSColin Finck */
3303c2c66affSColin Finck xmlChar *
xmlCatalogResolveSystem(const xmlChar * sysID)3304c2c66affSColin Finck xmlCatalogResolveSystem(const xmlChar *sysID) {
3305c2c66affSColin Finck xmlChar *ret;
3306c2c66affSColin Finck
3307c2c66affSColin Finck if (!xmlCatalogInitialized)
3308c2c66affSColin Finck xmlInitializeCatalog();
3309c2c66affSColin Finck
3310c2c66affSColin Finck ret = xmlACatalogResolveSystem(xmlDefaultCatalog, sysID);
3311c2c66affSColin Finck return(ret);
3312c2c66affSColin Finck }
3313c2c66affSColin Finck
3314c2c66affSColin Finck /**
3315c2c66affSColin Finck * xmlCatalogResolvePublic:
3316c2c66affSColin Finck * @pubID: the public ID string
3317c2c66affSColin Finck *
3318c2c66affSColin Finck * Try to lookup the catalog reference associated to a public ID
3319c2c66affSColin Finck *
3320c2c66affSColin Finck * Returns the resource if found or NULL otherwise, the value returned
3321c2c66affSColin Finck * must be freed by the caller.
3322c2c66affSColin Finck */
3323c2c66affSColin Finck xmlChar *
xmlCatalogResolvePublic(const xmlChar * pubID)3324c2c66affSColin Finck xmlCatalogResolvePublic(const xmlChar *pubID) {
3325c2c66affSColin Finck xmlChar *ret;
3326c2c66affSColin Finck
3327c2c66affSColin Finck if (!xmlCatalogInitialized)
3328c2c66affSColin Finck xmlInitializeCatalog();
3329c2c66affSColin Finck
3330c2c66affSColin Finck ret = xmlACatalogResolvePublic(xmlDefaultCatalog, pubID);
3331c2c66affSColin Finck return(ret);
3332c2c66affSColin Finck }
3333c2c66affSColin Finck
3334c2c66affSColin Finck /**
3335c2c66affSColin Finck * xmlCatalogResolve:
3336c2c66affSColin Finck * @pubID: the public ID string
3337c2c66affSColin Finck * @sysID: the system ID string
3338c2c66affSColin Finck *
3339c2c66affSColin Finck * Do a complete resolution lookup of an External Identifier
3340c2c66affSColin Finck *
3341c2c66affSColin Finck * Returns the URI of the resource or NULL if not found, it must be freed
3342c2c66affSColin Finck * by the caller.
3343c2c66affSColin Finck */
3344c2c66affSColin Finck xmlChar *
xmlCatalogResolve(const xmlChar * pubID,const xmlChar * sysID)3345c2c66affSColin Finck xmlCatalogResolve(const xmlChar *pubID, const xmlChar *sysID) {
3346c2c66affSColin Finck xmlChar *ret;
3347c2c66affSColin Finck
3348c2c66affSColin Finck if (!xmlCatalogInitialized)
3349c2c66affSColin Finck xmlInitializeCatalog();
3350c2c66affSColin Finck
3351c2c66affSColin Finck ret = xmlACatalogResolve(xmlDefaultCatalog, pubID, sysID);
3352c2c66affSColin Finck return(ret);
3353c2c66affSColin Finck }
3354c2c66affSColin Finck
3355c2c66affSColin Finck /**
3356c2c66affSColin Finck * xmlCatalogResolveURI:
3357c2c66affSColin Finck * @URI: the URI
3358c2c66affSColin Finck *
3359c2c66affSColin Finck * Do a complete resolution lookup of an URI
3360c2c66affSColin Finck *
3361c2c66affSColin Finck * Returns the URI of the resource or NULL if not found, it must be freed
3362c2c66affSColin Finck * by the caller.
3363c2c66affSColin Finck */
3364c2c66affSColin Finck xmlChar *
xmlCatalogResolveURI(const xmlChar * URI)3365c2c66affSColin Finck xmlCatalogResolveURI(const xmlChar *URI) {
3366c2c66affSColin Finck xmlChar *ret;
3367c2c66affSColin Finck
3368c2c66affSColin Finck if (!xmlCatalogInitialized)
3369c2c66affSColin Finck xmlInitializeCatalog();
3370c2c66affSColin Finck
3371c2c66affSColin Finck ret = xmlACatalogResolveURI(xmlDefaultCatalog, URI);
3372c2c66affSColin Finck return(ret);
3373c2c66affSColin Finck }
3374c2c66affSColin Finck
3375c2c66affSColin Finck #ifdef LIBXML_OUTPUT_ENABLED
3376c2c66affSColin Finck /**
3377c2c66affSColin Finck * xmlCatalogDump:
3378c2c66affSColin Finck * @out: the file.
3379c2c66affSColin Finck *
3380c2c66affSColin Finck * Dump all the global catalog content to the given file.
3381c2c66affSColin Finck */
3382c2c66affSColin Finck void
xmlCatalogDump(FILE * out)3383c2c66affSColin Finck xmlCatalogDump(FILE *out) {
3384c2c66affSColin Finck if (out == NULL)
3385c2c66affSColin Finck return;
3386c2c66affSColin Finck
3387c2c66affSColin Finck if (!xmlCatalogInitialized)
3388c2c66affSColin Finck xmlInitializeCatalog();
3389c2c66affSColin Finck
3390c2c66affSColin Finck xmlACatalogDump(xmlDefaultCatalog, out);
3391c2c66affSColin Finck }
3392c2c66affSColin Finck #endif /* LIBXML_OUTPUT_ENABLED */
3393c2c66affSColin Finck
3394c2c66affSColin Finck /**
3395c2c66affSColin Finck * xmlCatalogAdd:
3396c2c66affSColin Finck * @type: the type of record to add to the catalog
3397c2c66affSColin Finck * @orig: the system, public or prefix to match
3398c2c66affSColin Finck * @replace: the replacement value for the match
3399c2c66affSColin Finck *
3400c2c66affSColin Finck * Add an entry in the catalog, it may overwrite existing but
3401c2c66affSColin Finck * different entries.
3402c2c66affSColin Finck * If called before any other catalog routine, allows to override the
3403c2c66affSColin Finck * default shared catalog put in place by xmlInitializeCatalog();
3404c2c66affSColin Finck *
3405c2c66affSColin Finck * Returns 0 if successful, -1 otherwise
3406c2c66affSColin Finck */
3407c2c66affSColin Finck int
xmlCatalogAdd(const xmlChar * type,const xmlChar * orig,const xmlChar * replace)3408c2c66affSColin Finck xmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace) {
3409c2c66affSColin Finck int res = -1;
3410c2c66affSColin Finck
3411c2c66affSColin Finck if (!xmlCatalogInitialized)
3412c2c66affSColin Finck xmlInitializeCatalogData();
3413c2c66affSColin Finck
3414c2c66affSColin Finck xmlRMutexLock(xmlCatalogMutex);
3415c2c66affSColin Finck /*
3416c2c66affSColin Finck * Specific case where one want to override the default catalog
3417c2c66affSColin Finck * put in place by xmlInitializeCatalog();
3418c2c66affSColin Finck */
3419c2c66affSColin Finck if ((xmlDefaultCatalog == NULL) &&
3420c2c66affSColin Finck (xmlStrEqual(type, BAD_CAST "catalog"))) {
3421c2c66affSColin Finck xmlDefaultCatalog = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3422c2c66affSColin Finck xmlCatalogDefaultPrefer);
342340ee59d6SThomas Faber if (xmlDefaultCatalog != NULL) {
3424c2c66affSColin Finck xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
3425c2c66affSColin Finck orig, NULL, xmlCatalogDefaultPrefer, NULL);
342640ee59d6SThomas Faber }
3427c2c66affSColin Finck xmlRMutexUnlock(xmlCatalogMutex);
3428c2c66affSColin Finck return(0);
3429c2c66affSColin Finck }
3430c2c66affSColin Finck
3431c2c66affSColin Finck res = xmlACatalogAdd(xmlDefaultCatalog, type, orig, replace);
3432c2c66affSColin Finck xmlRMutexUnlock(xmlCatalogMutex);
3433c2c66affSColin Finck return(res);
3434c2c66affSColin Finck }
3435c2c66affSColin Finck
3436c2c66affSColin Finck /**
3437c2c66affSColin Finck * xmlCatalogRemove:
3438c2c66affSColin Finck * @value: the value to remove
3439c2c66affSColin Finck *
3440c2c66affSColin Finck * Remove an entry from the catalog
3441c2c66affSColin Finck *
3442c2c66affSColin Finck * Returns the number of entries removed if successful, -1 otherwise
3443c2c66affSColin Finck */
3444c2c66affSColin Finck int
xmlCatalogRemove(const xmlChar * value)3445c2c66affSColin Finck xmlCatalogRemove(const xmlChar *value) {
3446c2c66affSColin Finck int res;
3447c2c66affSColin Finck
3448c2c66affSColin Finck if (!xmlCatalogInitialized)
3449c2c66affSColin Finck xmlInitializeCatalog();
3450c2c66affSColin Finck
3451c2c66affSColin Finck xmlRMutexLock(xmlCatalogMutex);
3452c2c66affSColin Finck res = xmlACatalogRemove(xmlDefaultCatalog, value);
3453c2c66affSColin Finck xmlRMutexUnlock(xmlCatalogMutex);
3454c2c66affSColin Finck return(res);
3455c2c66affSColin Finck }
3456c2c66affSColin Finck
3457c2c66affSColin Finck /**
3458c2c66affSColin Finck * xmlCatalogConvert:
3459c2c66affSColin Finck *
3460c2c66affSColin Finck * Convert all the SGML catalog entries as XML ones
3461c2c66affSColin Finck *
3462c2c66affSColin Finck * Returns the number of entries converted if successful, -1 otherwise
3463c2c66affSColin Finck */
3464c2c66affSColin Finck int
xmlCatalogConvert(void)3465c2c66affSColin Finck xmlCatalogConvert(void) {
3466c2c66affSColin Finck int res = -1;
3467c2c66affSColin Finck
3468c2c66affSColin Finck if (!xmlCatalogInitialized)
3469c2c66affSColin Finck xmlInitializeCatalog();
3470c2c66affSColin Finck
3471c2c66affSColin Finck xmlRMutexLock(xmlCatalogMutex);
3472c2c66affSColin Finck res = xmlConvertSGMLCatalog(xmlDefaultCatalog);
3473c2c66affSColin Finck xmlRMutexUnlock(xmlCatalogMutex);
3474c2c66affSColin Finck return(res);
3475c2c66affSColin Finck }
3476c2c66affSColin Finck
3477c2c66affSColin Finck /************************************************************************
3478c2c66affSColin Finck * *
3479c2c66affSColin Finck * Public interface manipulating the common preferences *
3480c2c66affSColin Finck * *
3481c2c66affSColin Finck ************************************************************************/
3482c2c66affSColin Finck
3483c2c66affSColin Finck /**
3484c2c66affSColin Finck * xmlCatalogGetDefaults:
3485c2c66affSColin Finck *
3486c2c66affSColin Finck * Used to get the user preference w.r.t. to what catalogs should
3487c2c66affSColin Finck * be accepted
3488c2c66affSColin Finck *
3489c2c66affSColin Finck * Returns the current xmlCatalogAllow value
3490c2c66affSColin Finck */
3491c2c66affSColin Finck xmlCatalogAllow
xmlCatalogGetDefaults(void)3492c2c66affSColin Finck xmlCatalogGetDefaults(void) {
3493c2c66affSColin Finck return(xmlCatalogDefaultAllow);
3494c2c66affSColin Finck }
3495c2c66affSColin Finck
3496c2c66affSColin Finck /**
3497c2c66affSColin Finck * xmlCatalogSetDefaults:
3498c2c66affSColin Finck * @allow: what catalogs should be accepted
3499c2c66affSColin Finck *
3500c2c66affSColin Finck * Used to set the user preference w.r.t. to what catalogs should
3501c2c66affSColin Finck * be accepted
3502c2c66affSColin Finck */
3503c2c66affSColin Finck void
xmlCatalogSetDefaults(xmlCatalogAllow allow)3504c2c66affSColin Finck xmlCatalogSetDefaults(xmlCatalogAllow allow) {
3505c2c66affSColin Finck if (xmlDebugCatalogs) {
3506c2c66affSColin Finck switch (allow) {
3507c2c66affSColin Finck case XML_CATA_ALLOW_NONE:
3508c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
3509c2c66affSColin Finck "Disabling catalog usage\n");
3510c2c66affSColin Finck break;
3511c2c66affSColin Finck case XML_CATA_ALLOW_GLOBAL:
3512c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
3513c2c66affSColin Finck "Allowing only global catalogs\n");
3514c2c66affSColin Finck break;
3515c2c66affSColin Finck case XML_CATA_ALLOW_DOCUMENT:
3516c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
3517c2c66affSColin Finck "Allowing only catalogs from the document\n");
3518c2c66affSColin Finck break;
3519c2c66affSColin Finck case XML_CATA_ALLOW_ALL:
3520c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
3521c2c66affSColin Finck "Allowing all catalogs\n");
3522c2c66affSColin Finck break;
3523c2c66affSColin Finck }
3524c2c66affSColin Finck }
3525c2c66affSColin Finck xmlCatalogDefaultAllow = allow;
3526c2c66affSColin Finck }
3527c2c66affSColin Finck
3528c2c66affSColin Finck /**
3529c2c66affSColin Finck * xmlCatalogSetDefaultPrefer:
3530c2c66affSColin Finck * @prefer: the default preference for delegation
3531c2c66affSColin Finck *
3532c2c66affSColin Finck * Allows to set the preference between public and system for deletion
3533c2c66affSColin Finck * in XML Catalog resolution. C.f. section 4.1.1 of the spec
3534c2c66affSColin Finck * Values accepted are XML_CATA_PREFER_PUBLIC or XML_CATA_PREFER_SYSTEM
3535c2c66affSColin Finck *
3536c2c66affSColin Finck * Returns the previous value of the default preference for delegation
3537c2c66affSColin Finck */
3538c2c66affSColin Finck xmlCatalogPrefer
xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer)3539c2c66affSColin Finck xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer) {
3540c2c66affSColin Finck xmlCatalogPrefer ret = xmlCatalogDefaultPrefer;
3541c2c66affSColin Finck
3542c2c66affSColin Finck if (prefer == XML_CATA_PREFER_NONE)
3543c2c66affSColin Finck return(ret);
3544c2c66affSColin Finck
3545c2c66affSColin Finck if (xmlDebugCatalogs) {
3546c2c66affSColin Finck switch (prefer) {
3547c2c66affSColin Finck case XML_CATA_PREFER_PUBLIC:
3548c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
3549c2c66affSColin Finck "Setting catalog preference to PUBLIC\n");
3550c2c66affSColin Finck break;
3551c2c66affSColin Finck case XML_CATA_PREFER_SYSTEM:
3552c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
3553c2c66affSColin Finck "Setting catalog preference to SYSTEM\n");
3554c2c66affSColin Finck break;
3555c2c66affSColin Finck default:
3556c2c66affSColin Finck return(ret);
3557c2c66affSColin Finck }
3558c2c66affSColin Finck }
3559c2c66affSColin Finck xmlCatalogDefaultPrefer = prefer;
3560c2c66affSColin Finck return(ret);
3561c2c66affSColin Finck }
3562c2c66affSColin Finck
3563c2c66affSColin Finck /**
3564c2c66affSColin Finck * xmlCatalogSetDebug:
3565c2c66affSColin Finck * @level: the debug level of catalogs required
3566c2c66affSColin Finck *
3567c2c66affSColin Finck * Used to set the debug level for catalog operation, 0 disable
3568c2c66affSColin Finck * debugging, 1 enable it
3569c2c66affSColin Finck *
3570c2c66affSColin Finck * Returns the previous value of the catalog debugging level
3571c2c66affSColin Finck */
3572c2c66affSColin Finck int
xmlCatalogSetDebug(int level)3573c2c66affSColin Finck xmlCatalogSetDebug(int level) {
3574c2c66affSColin Finck int ret = xmlDebugCatalogs;
3575c2c66affSColin Finck
3576c2c66affSColin Finck if (level <= 0)
3577c2c66affSColin Finck xmlDebugCatalogs = 0;
3578c2c66affSColin Finck else
3579c2c66affSColin Finck xmlDebugCatalogs = level;
3580c2c66affSColin Finck return(ret);
3581c2c66affSColin Finck }
3582c2c66affSColin Finck
3583c2c66affSColin Finck /************************************************************************
3584c2c66affSColin Finck * *
3585c2c66affSColin Finck * Minimal interfaces used for per-document catalogs by the parser *
3586c2c66affSColin Finck * *
3587c2c66affSColin Finck ************************************************************************/
3588c2c66affSColin Finck
3589c2c66affSColin Finck /**
3590c2c66affSColin Finck * xmlCatalogFreeLocal:
3591c2c66affSColin Finck * @catalogs: a document's list of catalogs
3592c2c66affSColin Finck *
3593c2c66affSColin Finck * Free up the memory associated to the catalog list
3594c2c66affSColin Finck */
3595c2c66affSColin Finck void
xmlCatalogFreeLocal(void * catalogs)3596c2c66affSColin Finck xmlCatalogFreeLocal(void *catalogs) {
3597c2c66affSColin Finck xmlCatalogEntryPtr catal;
3598c2c66affSColin Finck
3599c2c66affSColin Finck if (!xmlCatalogInitialized)
3600c2c66affSColin Finck xmlInitializeCatalog();
3601c2c66affSColin Finck
3602c2c66affSColin Finck catal = (xmlCatalogEntryPtr) catalogs;
3603c2c66affSColin Finck if (catal != NULL)
3604c2c66affSColin Finck xmlFreeCatalogEntryList(catal);
3605c2c66affSColin Finck }
3606c2c66affSColin Finck
3607c2c66affSColin Finck
3608c2c66affSColin Finck /**
3609c2c66affSColin Finck * xmlCatalogAddLocal:
3610c2c66affSColin Finck * @catalogs: a document's list of catalogs
3611c2c66affSColin Finck * @URL: the URL to a new local catalog
3612c2c66affSColin Finck *
3613c2c66affSColin Finck * Add the new entry to the catalog list
3614c2c66affSColin Finck *
3615c2c66affSColin Finck * Returns the updated list
3616c2c66affSColin Finck */
3617c2c66affSColin Finck void *
xmlCatalogAddLocal(void * catalogs,const xmlChar * URL)3618c2c66affSColin Finck xmlCatalogAddLocal(void *catalogs, const xmlChar *URL) {
3619c2c66affSColin Finck xmlCatalogEntryPtr catal, add;
3620c2c66affSColin Finck
3621c2c66affSColin Finck if (!xmlCatalogInitialized)
3622c2c66affSColin Finck xmlInitializeCatalog();
3623c2c66affSColin Finck
3624c2c66affSColin Finck if (URL == NULL)
3625c2c66affSColin Finck return(catalogs);
3626c2c66affSColin Finck
3627c2c66affSColin Finck if (xmlDebugCatalogs)
3628c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
3629c2c66affSColin Finck "Adding document catalog %s\n", URL);
3630c2c66affSColin Finck
3631c2c66affSColin Finck add = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, URL, NULL,
3632c2c66affSColin Finck xmlCatalogDefaultPrefer, NULL);
3633c2c66affSColin Finck if (add == NULL)
3634c2c66affSColin Finck return(catalogs);
3635c2c66affSColin Finck
3636c2c66affSColin Finck catal = (xmlCatalogEntryPtr) catalogs;
3637c2c66affSColin Finck if (catal == NULL)
3638c2c66affSColin Finck return((void *) add);
3639c2c66affSColin Finck
3640c2c66affSColin Finck while (catal->next != NULL)
3641c2c66affSColin Finck catal = catal->next;
3642c2c66affSColin Finck catal->next = add;
3643c2c66affSColin Finck return(catalogs);
3644c2c66affSColin Finck }
3645c2c66affSColin Finck
3646c2c66affSColin Finck /**
3647c2c66affSColin Finck * xmlCatalogLocalResolve:
3648c2c66affSColin Finck * @catalogs: a document's list of catalogs
3649c2c66affSColin Finck * @pubID: the public ID string
3650c2c66affSColin Finck * @sysID: the system ID string
3651c2c66affSColin Finck *
3652c2c66affSColin Finck * Do a complete resolution lookup of an External Identifier using a
3653c2c66affSColin Finck * document's private catalog list
3654c2c66affSColin Finck *
3655c2c66affSColin Finck * Returns the URI of the resource or NULL if not found, it must be freed
3656c2c66affSColin Finck * by the caller.
3657c2c66affSColin Finck */
3658c2c66affSColin Finck xmlChar *
xmlCatalogLocalResolve(void * catalogs,const xmlChar * pubID,const xmlChar * sysID)3659c2c66affSColin Finck xmlCatalogLocalResolve(void *catalogs, const xmlChar *pubID,
3660c2c66affSColin Finck const xmlChar *sysID) {
3661c2c66affSColin Finck xmlCatalogEntryPtr catal;
3662c2c66affSColin Finck xmlChar *ret;
3663c2c66affSColin Finck
3664c2c66affSColin Finck if (!xmlCatalogInitialized)
3665c2c66affSColin Finck xmlInitializeCatalog();
3666c2c66affSColin Finck
3667c2c66affSColin Finck if ((pubID == NULL) && (sysID == NULL))
3668c2c66affSColin Finck return(NULL);
3669c2c66affSColin Finck
3670c2c66affSColin Finck if (xmlDebugCatalogs) {
3671c2c66affSColin Finck if ((pubID != NULL) && (sysID != NULL)) {
3672c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
3673c2c66affSColin Finck "Local Resolve: pubID %s sysID %s\n", pubID, sysID);
3674c2c66affSColin Finck } else if (pubID != NULL) {
3675c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
3676c2c66affSColin Finck "Local Resolve: pubID %s\n", pubID);
3677c2c66affSColin Finck } else {
3678c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
3679c2c66affSColin Finck "Local Resolve: sysID %s\n", sysID);
3680c2c66affSColin Finck }
3681c2c66affSColin Finck }
3682c2c66affSColin Finck
3683c2c66affSColin Finck catal = (xmlCatalogEntryPtr) catalogs;
3684c2c66affSColin Finck if (catal == NULL)
3685c2c66affSColin Finck return(NULL);
3686c2c66affSColin Finck ret = xmlCatalogListXMLResolve(catal, pubID, sysID);
3687c2c66affSColin Finck if ((ret != NULL) && (ret != XML_CATAL_BREAK))
3688c2c66affSColin Finck return(ret);
3689c2c66affSColin Finck return(NULL);
3690c2c66affSColin Finck }
3691c2c66affSColin Finck
3692c2c66affSColin Finck /**
3693c2c66affSColin Finck * xmlCatalogLocalResolveURI:
3694c2c66affSColin Finck * @catalogs: a document's list of catalogs
3695c2c66affSColin Finck * @URI: the URI
3696c2c66affSColin Finck *
3697c2c66affSColin Finck * Do a complete resolution lookup of an URI using a
3698c2c66affSColin Finck * document's private catalog list
3699c2c66affSColin Finck *
3700c2c66affSColin Finck * Returns the URI of the resource or NULL if not found, it must be freed
3701c2c66affSColin Finck * by the caller.
3702c2c66affSColin Finck */
3703c2c66affSColin Finck xmlChar *
xmlCatalogLocalResolveURI(void * catalogs,const xmlChar * URI)3704c2c66affSColin Finck xmlCatalogLocalResolveURI(void *catalogs, const xmlChar *URI) {
3705c2c66affSColin Finck xmlCatalogEntryPtr catal;
3706c2c66affSColin Finck xmlChar *ret;
3707c2c66affSColin Finck
3708c2c66affSColin Finck if (!xmlCatalogInitialized)
3709c2c66affSColin Finck xmlInitializeCatalog();
3710c2c66affSColin Finck
3711c2c66affSColin Finck if (URI == NULL)
3712c2c66affSColin Finck return(NULL);
3713c2c66affSColin Finck
3714c2c66affSColin Finck if (xmlDebugCatalogs)
3715c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
3716c2c66affSColin Finck "Resolve URI %s\n", URI);
3717c2c66affSColin Finck
3718c2c66affSColin Finck catal = (xmlCatalogEntryPtr) catalogs;
3719c2c66affSColin Finck if (catal == NULL)
3720c2c66affSColin Finck return(NULL);
3721c2c66affSColin Finck ret = xmlCatalogListXMLResolveURI(catal, URI);
3722c2c66affSColin Finck if ((ret != NULL) && (ret != XML_CATAL_BREAK))
3723c2c66affSColin Finck return(ret);
3724c2c66affSColin Finck return(NULL);
3725c2c66affSColin Finck }
3726c2c66affSColin Finck
3727c2c66affSColin Finck /************************************************************************
3728c2c66affSColin Finck * *
3729c2c66affSColin Finck * Deprecated interfaces *
3730c2c66affSColin Finck * *
3731c2c66affSColin Finck ************************************************************************/
3732c2c66affSColin Finck /**
3733c2c66affSColin Finck * xmlCatalogGetSystem:
3734c2c66affSColin Finck * @sysID: the system ID string
3735c2c66affSColin Finck *
3736c2c66affSColin Finck * Try to lookup the catalog reference associated to a system ID
3737c2c66affSColin Finck * DEPRECATED, use xmlCatalogResolveSystem()
3738c2c66affSColin Finck *
3739c2c66affSColin Finck * Returns the resource if found or NULL otherwise.
3740c2c66affSColin Finck */
3741c2c66affSColin Finck const xmlChar *
xmlCatalogGetSystem(const xmlChar * sysID)3742c2c66affSColin Finck xmlCatalogGetSystem(const xmlChar *sysID) {
3743c2c66affSColin Finck xmlChar *ret;
3744c2c66affSColin Finck static xmlChar result[1000];
3745c2c66affSColin Finck static int msg = 0;
3746c2c66affSColin Finck
3747c2c66affSColin Finck if (!xmlCatalogInitialized)
3748c2c66affSColin Finck xmlInitializeCatalog();
3749c2c66affSColin Finck
3750c2c66affSColin Finck if (msg == 0) {
3751c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
3752c2c66affSColin Finck "Use of deprecated xmlCatalogGetSystem() call\n");
3753c2c66affSColin Finck msg++;
3754c2c66affSColin Finck }
3755c2c66affSColin Finck
3756c2c66affSColin Finck if (sysID == NULL)
3757c2c66affSColin Finck return(NULL);
3758c2c66affSColin Finck
3759c2c66affSColin Finck /*
3760c2c66affSColin Finck * Check first the XML catalogs
3761c2c66affSColin Finck */
3762c2c66affSColin Finck if (xmlDefaultCatalog != NULL) {
3763c2c66affSColin Finck ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, NULL, sysID);
3764c2c66affSColin Finck if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
3765c2c66affSColin Finck snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
3766c2c66affSColin Finck result[sizeof(result) - 1] = 0;
3767c2c66affSColin Finck return(result);
3768c2c66affSColin Finck }
3769c2c66affSColin Finck }
3770c2c66affSColin Finck
3771c2c66affSColin Finck if (xmlDefaultCatalog != NULL)
3772c2c66affSColin Finck return(xmlCatalogGetSGMLSystem(xmlDefaultCatalog->sgml, sysID));
3773c2c66affSColin Finck return(NULL);
3774c2c66affSColin Finck }
3775c2c66affSColin Finck
3776c2c66affSColin Finck /**
3777c2c66affSColin Finck * xmlCatalogGetPublic:
3778c2c66affSColin Finck * @pubID: the public ID string
3779c2c66affSColin Finck *
3780c2c66affSColin Finck * Try to lookup the catalog reference associated to a public ID
3781c2c66affSColin Finck * DEPRECATED, use xmlCatalogResolvePublic()
3782c2c66affSColin Finck *
3783c2c66affSColin Finck * Returns the resource if found or NULL otherwise.
3784c2c66affSColin Finck */
3785c2c66affSColin Finck const xmlChar *
xmlCatalogGetPublic(const xmlChar * pubID)3786c2c66affSColin Finck xmlCatalogGetPublic(const xmlChar *pubID) {
3787c2c66affSColin Finck xmlChar *ret;
3788c2c66affSColin Finck static xmlChar result[1000];
3789c2c66affSColin Finck static int msg = 0;
3790c2c66affSColin Finck
3791c2c66affSColin Finck if (!xmlCatalogInitialized)
3792c2c66affSColin Finck xmlInitializeCatalog();
3793c2c66affSColin Finck
3794c2c66affSColin Finck if (msg == 0) {
3795c2c66affSColin Finck xmlGenericError(xmlGenericErrorContext,
3796c2c66affSColin Finck "Use of deprecated xmlCatalogGetPublic() call\n");
3797c2c66affSColin Finck msg++;
3798c2c66affSColin Finck }
3799c2c66affSColin Finck
3800c2c66affSColin Finck if (pubID == NULL)
3801c2c66affSColin Finck return(NULL);
3802c2c66affSColin Finck
3803c2c66affSColin Finck /*
3804c2c66affSColin Finck * Check first the XML catalogs
3805c2c66affSColin Finck */
3806c2c66affSColin Finck if (xmlDefaultCatalog != NULL) {
3807c2c66affSColin Finck ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, pubID, NULL);
3808c2c66affSColin Finck if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
3809c2c66affSColin Finck snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
3810c2c66affSColin Finck result[sizeof(result) - 1] = 0;
3811c2c66affSColin Finck return(result);
3812c2c66affSColin Finck }
3813c2c66affSColin Finck }
3814c2c66affSColin Finck
3815c2c66affSColin Finck if (xmlDefaultCatalog != NULL)
3816c2c66affSColin Finck return(xmlCatalogGetSGMLPublic(xmlDefaultCatalog->sgml, pubID));
3817c2c66affSColin Finck return(NULL);
3818c2c66affSColin Finck }
3819c2c66affSColin Finck
3820c2c66affSColin Finck #endif /* LIBXML_CATALOG_ENABLED */
3821