xref: /reactos/sdk/lib/3rdparty/libxml2/catalog.c (revision 911153da)
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