blob: f33a0aa99097d135d247fde42481152a25fa51d9 [file] [log] [blame]
Daniel Veillarda7374592001-05-10 14:17:55 +00001/**
2 * catalog.c: set of generic Catalog related routines
3 *
4 * Reference: SGML Open Technical Resolution TR9401:1997.
5 * http://www.jclark.com/sp/catalog.htm
6 *
Daniel Veillard344cee72001-08-20 00:08:40 +00007 * XML Catalogs Working Draft 06 August 2001
8 * http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
9 *
Daniel Veillarda7374592001-05-10 14:17:55 +000010 * See Copyright for the status of this software.
11 *
12 * Daniel.Veillard@imag.fr
13 */
14
Daniel Veillard34ce8be2002-03-18 19:37:11 +000015#define IN_LIBXML
Daniel Veillarda7374592001-05-10 14:17:55 +000016#include "libxml.h"
17
18#ifdef LIBXML_CATALOG_ENABLED
19#ifdef HAVE_SYS_TYPES_H
20#include <sys/types.h>
21#endif
22#ifdef HAVE_SYS_STAT_H
23#include <sys/stat.h>
24#endif
25#ifdef HAVE_UNISTD_H
26#include <unistd.h>
27#endif
28#ifdef HAVE_FCNTL_H
29#include <fcntl.h>
30#endif
Daniel Veillardc0631a62001-09-20 13:56:06 +000031#ifdef HAVE_STDLIB_H
32#include <stdlib.h>
33#endif
Daniel Veillarda7374592001-05-10 14:17:55 +000034#include <string.h>
35#include <libxml/xmlmemory.h>
36#include <libxml/hash.h>
37#include <libxml/uri.h>
38#include <libxml/parserInternals.h>
39#include <libxml/catalog.h>
40#include <libxml/xmlerror.h>
Daniel Veillard81463942001-10-16 12:34:39 +000041#include <libxml/threads.h>
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000042#include <libxml/globals.h>
Daniel Veillarda7374592001-05-10 14:17:55 +000043
Daniel Veillard6990bf32001-08-23 21:17:48 +000044#define MAX_DELEGATE 50
Daniel Veillard5ee43b02003-08-04 00:58:46 +000045#define MAX_CATAL_DEPTH 50
Daniel Veillard6990bf32001-08-23 21:17:48 +000046
Daniel Veillarded121382007-04-17 12:33:19 +000047#ifdef _WIN32
48# define PATH_SEAPARATOR ';'
49#else
50# define PATH_SEAPARATOR ':'
51#endif
52
Daniel Veillard344cee72001-08-20 00:08:40 +000053/**
54 * TODO:
55 *
56 * macro to flag unimplemented blocks
Daniel Veillard3e59fc52003-04-18 12:34:58 +000057 * XML_CATALOG_PREFER user env to select between system/public prefered
58 * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk>
59 *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
60 *> values "system" and "public". I have made the default be "system" to
61 *> match yours.
Daniel Veillard344cee72001-08-20 00:08:40 +000062 */
63#define TODO \
64 xmlGenericError(xmlGenericErrorContext, \
65 "Unimplemented block at %s:%d\n", \
66 __FILE__, __LINE__);
67
Daniel Veillardcda96922001-08-21 10:56:31 +000068#define XML_URN_PUBID "urn:publicid:"
Daniel Veillarde2940dd2001-08-22 00:06:49 +000069#define XML_CATAL_BREAK ((xmlChar *) -1)
Daniel Veillard75b96822001-10-11 18:59:45 +000070#ifndef XML_XML_DEFAULT_CATALOG
Daniel Veillardf7b094f2001-11-15 13:54:39 +000071#define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog"
Daniel Veillard6c5f9d12001-08-25 13:33:14 +000072#endif
Daniel Veillard75b96822001-10-11 18:59:45 +000073#ifndef XML_SGML_DEFAULT_CATALOG
Daniel Veillardf7b094f2001-11-15 13:54:39 +000074#define XML_SGML_DEFAULT_CATALOG "file:///etc/sgml/catalog"
Daniel Veillard75b96822001-10-11 18:59:45 +000075#endif
76
Daniel Veillardfb382b82004-06-14 12:13:12 +000077#if defined(_WIN32) && defined(_MSC_VER)
78#undef XML_XML_DEFAULT_CATALOG
79static char XML_XML_DEFAULT_CATALOG[256] = "file:///etc/xml/catalog";
Daniel Veillard59d3ed82007-04-17 12:44:58 +000080#if defined(_WIN32_WCE)
81/* Windows CE don't have a A variant */
82#define GetModuleHandleA GetModuleHandle
83#define GetModuleFileNameA GetModuleFileName
84#else
Daniel Veillardfb382b82004-06-14 12:13:12 +000085void* __stdcall GetModuleHandleA(const char*);
86unsigned long __stdcall GetModuleFileNameA(void*, char*, unsigned long);
87#endif
Daniel Veillard59d3ed82007-04-17 12:44:58 +000088#endif
Daniel Veillardfb382b82004-06-14 12:13:12 +000089
Daniel Veillardc8155052004-07-16 09:03:08 +000090static xmlChar *xmlCatalogNormalizePublic(const xmlChar *pubID);
Daniel Veillard85c11fa2001-10-16 21:03:08 +000091static int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename);
Daniel Veillard344cee72001-08-20 00:08:40 +000092
Daniel Veillarda7374592001-05-10 14:17:55 +000093/************************************************************************
94 * *
95 * Types, all private *
96 * *
97 ************************************************************************/
98
99typedef enum {
Daniel Veillardc853b322001-11-06 15:24:37 +0000100 XML_CATA_REMOVED = -1,
Daniel Veillarda7374592001-05-10 14:17:55 +0000101 XML_CATA_NONE = 0,
Daniel Veillarda7374592001-05-10 14:17:55 +0000102 XML_CATA_CATALOG,
Daniel Veillard9f7b84b2001-08-23 15:31:19 +0000103 XML_CATA_BROKEN_CATALOG,
Daniel Veillard344cee72001-08-20 00:08:40 +0000104 XML_CATA_NEXT_CATALOG,
William M. Brackb7b54de2004-10-06 16:38:01 +0000105 XML_CATA_GROUP,
Daniel Veillard344cee72001-08-20 00:08:40 +0000106 XML_CATA_PUBLIC,
107 XML_CATA_SYSTEM,
108 XML_CATA_REWRITE_SYSTEM,
109 XML_CATA_DELEGATE_PUBLIC,
110 XML_CATA_DELEGATE_SYSTEM,
111 XML_CATA_URI,
112 XML_CATA_REWRITE_URI,
113 XML_CATA_DELEGATE_URI,
114 SGML_CATA_SYSTEM,
115 SGML_CATA_PUBLIC,
116 SGML_CATA_ENTITY,
117 SGML_CATA_PENTITY,
118 SGML_CATA_DOCTYPE,
119 SGML_CATA_LINKTYPE,
120 SGML_CATA_NOTATION,
121 SGML_CATA_DELEGATE,
122 SGML_CATA_BASE,
123 SGML_CATA_CATALOG,
124 SGML_CATA_DOCUMENT,
125 SGML_CATA_SGMLDECL
Daniel Veillarda7374592001-05-10 14:17:55 +0000126} xmlCatalogEntryType;
127
128typedef struct _xmlCatalogEntry xmlCatalogEntry;
129typedef xmlCatalogEntry *xmlCatalogEntryPtr;
130struct _xmlCatalogEntry {
Daniel Veillard344cee72001-08-20 00:08:40 +0000131 struct _xmlCatalogEntry *next;
132 struct _xmlCatalogEntry *parent;
133 struct _xmlCatalogEntry *children;
Daniel Veillarda7374592001-05-10 14:17:55 +0000134 xmlCatalogEntryType type;
135 xmlChar *name;
136 xmlChar *value;
Daniel Veillardc853b322001-11-06 15:24:37 +0000137 xmlChar *URL; /* The expanded URL using the base */
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000138 xmlCatalogPrefer prefer;
Daniel Veillard6990bf32001-08-23 21:17:48 +0000139 int dealloc;
Daniel Veillard5ee43b02003-08-04 00:58:46 +0000140 int depth;
William M. Brackb7b54de2004-10-06 16:38:01 +0000141 struct _xmlCatalogEntry *group;
Daniel Veillarda7374592001-05-10 14:17:55 +0000142};
143
Daniel Veillard75b96822001-10-11 18:59:45 +0000144typedef enum {
145 XML_XML_CATALOG_TYPE = 1,
146 XML_SGML_CATALOG_TYPE
147} xmlCatalogType;
148
149#define XML_MAX_SGML_CATA_DEPTH 10
150struct _xmlCatalog {
151 xmlCatalogType type; /* either XML or SGML */
152
153 /*
154 * SGML Catalogs are stored as a simple hash table of catalog entries
155 * Catalog stack to check against overflows when building the
156 * SGML catalog
157 */
158 char *catalTab[XML_MAX_SGML_CATA_DEPTH]; /* stack of catals */
159 int catalNr; /* Number of current catal streams */
160 int catalMax; /* Max number of catal streams */
161 xmlHashTablePtr sgml;
162
163 /*
164 * XML Catalogs are stored as a tree of Catalog entries
165 */
166 xmlCatalogPrefer prefer;
167 xmlCatalogEntryPtr xml;
168};
169
170/************************************************************************
171 * *
172 * Global variables *
173 * *
174 ************************************************************************/
175
Daniel Veillard81463942001-10-16 12:34:39 +0000176/*
177 * Those are preferences
178 */
179static int xmlDebugCatalogs = 0; /* used for debugging */
Daniel Veillard5d90b6c2001-08-22 14:29:45 +0000180static xmlCatalogAllow xmlCatalogDefaultAllow = XML_CATA_ALLOW_ALL;
Daniel Veillard6990bf32001-08-23 21:17:48 +0000181static xmlCatalogPrefer xmlCatalogDefaultPrefer = XML_CATA_PREFER_PUBLIC;
Daniel Veillard75b96822001-10-11 18:59:45 +0000182
183/*
184 * Hash table containing all the trees of XML catalogs parsed by
185 * the application.
186 */
Daniel Veillard6990bf32001-08-23 21:17:48 +0000187static xmlHashTablePtr xmlCatalogXMLFiles = NULL;
Daniel Veillard75b96822001-10-11 18:59:45 +0000188
189/*
190 * The default catalog in use by the application
191 */
192static xmlCatalogPtr xmlDefaultCatalog = NULL;
193
194/*
Daniel Veillard81463942001-10-16 12:34:39 +0000195 * A mutex for modifying the shared global catalog(s)
196 * xmlDefaultCatalog tree.
197 * It also protects xmlCatalogXMLFiles
198 * The core of this readers/writer scheme is in xmlFetchXMLCatalogFile()
199 */
200static xmlRMutexPtr xmlCatalogMutex = NULL;
201
202/*
Daniel Veillard75b96822001-10-11 18:59:45 +0000203 * Whether the catalog support was initialized.
204 */
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000205static int xmlCatalogInitialized = 0;
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000206
Daniel Veillard69d2c172003-10-09 11:46:07 +0000207/************************************************************************
208 * *
209 * Catalog error handlers *
210 * *
211 ************************************************************************/
212
213/**
214 * xmlCatalogErrMemory:
215 * @extra: extra informations
216 *
217 * Handle an out of memory condition
218 */
219static void
220xmlCatalogErrMemory(const char *extra)
221{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000222 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_CATALOG,
Daniel Veillard69d2c172003-10-09 11:46:07 +0000223 XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0,
224 extra, NULL, NULL, 0, 0,
225 "Memory allocation failed : %s\n", extra);
226}
227
228/**
229 * xmlCatalogErr:
230 * @catal: the Catalog entry
231 * @node: the context node
232 * @msg: the error message
233 * @extra: extra informations
234 *
235 * Handle a catalog error
236 */
237static void
238xmlCatalogErr(xmlCatalogEntryPtr catal, xmlNodePtr node, int error,
239 const char *msg, const xmlChar *str1, const xmlChar *str2,
240 const xmlChar *str3)
241{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000242 __xmlRaiseError(NULL, NULL, NULL, catal, node, XML_FROM_CATALOG,
Daniel Veillard69d2c172003-10-09 11:46:07 +0000243 error, XML_ERR_ERROR, NULL, 0,
244 (const char *) str1, (const char *) str2,
245 (const char *) str3, 0, 0,
246 msg, str1, str2, str3);
247}
248
Daniel Veillarda7374592001-05-10 14:17:55 +0000249
250/************************************************************************
251 * *
Daniel Veillard75b96822001-10-11 18:59:45 +0000252 * Allocation and Freeing *
Daniel Veillarda7374592001-05-10 14:17:55 +0000253 * *
254 ************************************************************************/
255
Daniel Veillard75b96822001-10-11 18:59:45 +0000256/**
257 * xmlNewCatalogEntry:
258 * @type: type of entry
259 * @name: name of the entry
260 * @value: value of the entry
261 * @prefer: the PUBLIC vs. SYSTEM current preference value
William M. Brackb7b54de2004-10-06 16:38:01 +0000262 * @group: for members of a group, the group entry
Daniel Veillard75b96822001-10-11 18:59:45 +0000263 *
264 * create a new Catalog entry, this type is shared both by XML and
265 * SGML catalogs, but the acceptable types values differs.
266 *
267 * Returns the xmlCatalogEntryPtr or NULL in case of error
268 */
Daniel Veillarda7374592001-05-10 14:17:55 +0000269static xmlCatalogEntryPtr
Daniel Veillard344cee72001-08-20 00:08:40 +0000270xmlNewCatalogEntry(xmlCatalogEntryType type, const xmlChar *name,
William M. Brackb7b54de2004-10-06 16:38:01 +0000271 const xmlChar *value, const xmlChar *URL, xmlCatalogPrefer prefer,
272 xmlCatalogEntryPtr group) {
Daniel Veillarda7374592001-05-10 14:17:55 +0000273 xmlCatalogEntryPtr ret;
Daniel Veillardc8155052004-07-16 09:03:08 +0000274 xmlChar *normid = NULL;
Daniel Veillarda7374592001-05-10 14:17:55 +0000275
276 ret = (xmlCatalogEntryPtr) xmlMalloc(sizeof(xmlCatalogEntry));
277 if (ret == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +0000278 xmlCatalogErrMemory("allocating catalog entry");
Daniel Veillarda7374592001-05-10 14:17:55 +0000279 return(NULL);
280 }
Daniel Veillard344cee72001-08-20 00:08:40 +0000281 ret->next = NULL;
282 ret->parent = NULL;
283 ret->children = NULL;
Daniel Veillarda7374592001-05-10 14:17:55 +0000284 ret->type = type;
Daniel Veillardc8155052004-07-16 09:03:08 +0000285 if (type == XML_CATA_PUBLIC || type == XML_CATA_DELEGATE_PUBLIC) {
286 normid = xmlCatalogNormalizePublic(name);
287 if (normid != NULL)
288 name = (*normid != 0 ? normid : NULL);
289 }
Daniel Veillard344cee72001-08-20 00:08:40 +0000290 if (name != NULL)
291 ret->name = xmlStrdup(name);
292 else
293 ret->name = NULL;
Daniel Veillardc8155052004-07-16 09:03:08 +0000294 if (normid != NULL)
295 xmlFree(normid);
Daniel Veillard344cee72001-08-20 00:08:40 +0000296 if (value != NULL)
297 ret->value = xmlStrdup(value);
298 else
299 ret->value = NULL;
Daniel Veillardc853b322001-11-06 15:24:37 +0000300 if (URL == NULL)
301 URL = value;
302 if (URL != NULL)
303 ret->URL = xmlStrdup(URL);
304 else
305 ret->URL = NULL;
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000306 ret->prefer = prefer;
Daniel Veillard85c11fa2001-10-16 21:03:08 +0000307 ret->dealloc = 0;
Daniel Veillard5ee43b02003-08-04 00:58:46 +0000308 ret->depth = 0;
William M. Brackb7b54de2004-10-06 16:38:01 +0000309 ret->group = group;
Daniel Veillarda7374592001-05-10 14:17:55 +0000310 return(ret);
311}
312
313static void
Daniel Veillard344cee72001-08-20 00:08:40 +0000314xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret);
315
Daniel Veillard75b96822001-10-11 18:59:45 +0000316/**
317 * xmlFreeCatalogEntry:
318 * @ret: a Catalog entry
319 *
320 * Free the memory allocated to a Catalog entry
321 */
Daniel Veillard344cee72001-08-20 00:08:40 +0000322static void
Daniel Veillarda7374592001-05-10 14:17:55 +0000323xmlFreeCatalogEntry(xmlCatalogEntryPtr ret) {
324 if (ret == NULL)
325 return;
Daniel Veillard85c11fa2001-10-16 21:03:08 +0000326 /*
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000327 * Entries stored in the file hash must be deallocated
Daniel Veillard85c11fa2001-10-16 21:03:08 +0000328 * only by the file hash cleaner !
329 */
330 if (ret->dealloc == 1)
331 return;
332
333 if (xmlDebugCatalogs) {
334 if (ret->name != NULL)
335 xmlGenericError(xmlGenericErrorContext,
336 "Free catalog entry %s\n", ret->name);
337 else if (ret->value != NULL)
338 xmlGenericError(xmlGenericErrorContext,
339 "Free catalog entry %s\n", ret->value);
340 else
341 xmlGenericError(xmlGenericErrorContext,
342 "Free catalog entry\n");
343 }
344
Daniel Veillarda7374592001-05-10 14:17:55 +0000345 if (ret->name != NULL)
346 xmlFree(ret->name);
347 if (ret->value != NULL)
348 xmlFree(ret->value);
Daniel Veillardc853b322001-11-06 15:24:37 +0000349 if (ret->URL != NULL)
350 xmlFree(ret->URL);
Daniel Veillarda7374592001-05-10 14:17:55 +0000351 xmlFree(ret);
352}
353
Daniel Veillard75b96822001-10-11 18:59:45 +0000354/**
355 * xmlFreeCatalogEntryList:
356 * @ret: a Catalog entry list
357 *
358 * Free the memory allocated to a full chained list of Catalog entries
359 */
Daniel Veillard344cee72001-08-20 00:08:40 +0000360static void
361xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret) {
362 xmlCatalogEntryPtr next;
363
364 while (ret != NULL) {
365 next = ret->next;
366 xmlFreeCatalogEntry(ret);
367 ret = next;
368 }
369}
370
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000371/**
Daniel Veillard85c11fa2001-10-16 21:03:08 +0000372 * xmlFreeCatalogHashEntryList:
373 * @ret: a Catalog entry list
374 *
375 * Free the memory allocated to list of Catalog entries from the
376 * catalog file hash.
377 */
378static void
379xmlFreeCatalogHashEntryList(xmlCatalogEntryPtr catal) {
380 xmlCatalogEntryPtr children, next;
381
382 if (catal == NULL)
383 return;
384
385 children = catal->children;
386 while (children != NULL) {
387 next = children->next;
388 children->dealloc = 0;
389 children->children = NULL;
390 xmlFreeCatalogEntry(children);
391 children = next;
392 }
393 catal->dealloc = 0;
394 xmlFreeCatalogEntry(catal);
395}
396
397/**
Daniel Veillardcd21dc72001-11-04 20:03:38 +0000398 * xmlCreateNewCatalog:
Daniel Veillard75b96822001-10-11 18:59:45 +0000399 * @type: type of catalog
400 * @prefer: the PUBLIC vs. SYSTEM current preference value
401 *
402 * create a new Catalog, this type is shared both by XML and
403 * SGML catalogs, but the acceptable types values differs.
404 *
405 * Returns the xmlCatalogPtr or NULL in case of error
406 */
407static xmlCatalogPtr
Daniel Veillardcd21dc72001-11-04 20:03:38 +0000408xmlCreateNewCatalog(xmlCatalogType type, xmlCatalogPrefer prefer) {
Daniel Veillard75b96822001-10-11 18:59:45 +0000409 xmlCatalogPtr ret;
410
411 ret = (xmlCatalogPtr) xmlMalloc(sizeof(xmlCatalog));
412 if (ret == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +0000413 xmlCatalogErrMemory("allocating catalog");
Daniel Veillard75b96822001-10-11 18:59:45 +0000414 return(NULL);
415 }
416 memset(ret, 0, sizeof(xmlCatalog));
417 ret->type = type;
418 ret->catalNr = 0;
419 ret->catalMax = XML_MAX_SGML_CATA_DEPTH;
420 ret->prefer = prefer;
Daniel Veillardcd21dc72001-11-04 20:03:38 +0000421 if (ret->type == XML_SGML_CATALOG_TYPE)
422 ret->sgml = xmlHashCreate(10);
Daniel Veillard75b96822001-10-11 18:59:45 +0000423 return(ret);
424}
425
426/**
427 * xmlFreeCatalog:
Daniel Veillard06d25242004-02-25 13:01:42 +0000428 * @catal: a Catalog
Daniel Veillard75b96822001-10-11 18:59:45 +0000429 *
430 * Free the memory allocated to a Catalog
431 */
432void
433xmlFreeCatalog(xmlCatalogPtr catal) {
434 if (catal == NULL)
435 return;
436 if (catal->xml != NULL)
437 xmlFreeCatalogEntryList(catal->xml);
438 if (catal->sgml != NULL)
439 xmlHashFree(catal->sgml,
440 (xmlHashDeallocator) xmlFreeCatalogEntry);
441 xmlFree(catal);
442}
443
444/************************************************************************
445 * *
446 * Serializing Catalogs *
447 * *
448 ************************************************************************/
449
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000450#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard75b96822001-10-11 18:59:45 +0000451/**
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000452 * xmlCatalogDumpEntry:
Daniel Veillard06d25242004-02-25 13:01:42 +0000453 * @entry: the catalog entry
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000454 * @out: the file.
455 *
Daniel Veillard75b96822001-10-11 18:59:45 +0000456 * Serialize an SGML Catalog entry
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000457 */
458static void
459xmlCatalogDumpEntry(xmlCatalogEntryPtr entry, FILE *out) {
460 if ((entry == NULL) || (out == NULL))
461 return;
462 switch (entry->type) {
Daniel Veillard344cee72001-08-20 00:08:40 +0000463 case SGML_CATA_ENTITY:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000464 fprintf(out, "ENTITY "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000465 case SGML_CATA_PENTITY:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000466 fprintf(out, "ENTITY %%"); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000467 case SGML_CATA_DOCTYPE:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000468 fprintf(out, "DOCTYPE "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000469 case SGML_CATA_LINKTYPE:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000470 fprintf(out, "LINKTYPE "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000471 case SGML_CATA_NOTATION:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000472 fprintf(out, "NOTATION "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000473 case SGML_CATA_PUBLIC:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000474 fprintf(out, "PUBLIC "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000475 case SGML_CATA_SYSTEM:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000476 fprintf(out, "SYSTEM "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000477 case SGML_CATA_DELEGATE:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000478 fprintf(out, "DELEGATE "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000479 case SGML_CATA_BASE:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000480 fprintf(out, "BASE "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000481 case SGML_CATA_CATALOG:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000482 fprintf(out, "CATALOG "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000483 case SGML_CATA_DOCUMENT:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000484 fprintf(out, "DOCUMENT "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000485 case SGML_CATA_SGMLDECL:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000486 fprintf(out, "SGMLDECL "); break;
487 default:
488 return;
489 }
490 switch (entry->type) {
Daniel Veillard344cee72001-08-20 00:08:40 +0000491 case SGML_CATA_ENTITY:
492 case SGML_CATA_PENTITY:
493 case SGML_CATA_DOCTYPE:
494 case SGML_CATA_LINKTYPE:
495 case SGML_CATA_NOTATION:
Daniel Veillard580ced82003-03-21 21:22:48 +0000496 fprintf(out, "%s", (const char *) entry->name); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000497 case SGML_CATA_PUBLIC:
498 case SGML_CATA_SYSTEM:
499 case SGML_CATA_SGMLDECL:
500 case SGML_CATA_DOCUMENT:
501 case SGML_CATA_CATALOG:
502 case SGML_CATA_BASE:
503 case SGML_CATA_DELEGATE:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000504 fprintf(out, "\"%s\"", entry->name); break;
505 default:
506 break;
507 }
508 switch (entry->type) {
Daniel Veillard344cee72001-08-20 00:08:40 +0000509 case SGML_CATA_ENTITY:
510 case SGML_CATA_PENTITY:
511 case SGML_CATA_DOCTYPE:
512 case SGML_CATA_LINKTYPE:
513 case SGML_CATA_NOTATION:
514 case SGML_CATA_PUBLIC:
515 case SGML_CATA_SYSTEM:
516 case SGML_CATA_DELEGATE:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000517 fprintf(out, " \"%s\"", entry->value); break;
518 default:
519 break;
520 }
521 fprintf(out, "\n");
522}
523
William M. Brackb7b54de2004-10-06 16:38:01 +0000524/**
525 * xmlDumpXMLCatalogNode:
526 * @catal: top catalog entry
527 * @catalog: pointer to the xml tree
528 * @doc: the containing document
529 * @ns: the current namespace
530 * @cgroup: group node for group members
531 *
532 * Serializes a Catalog entry, called by xmlDumpXMLCatalog and recursively
533 * for group entries
534 */
535static void xmlDumpXMLCatalogNode(xmlCatalogEntryPtr catal, xmlNodePtr catalog,
536 xmlDocPtr doc, xmlNsPtr ns, xmlCatalogEntryPtr cgroup) {
537 xmlNodePtr node;
538 xmlCatalogEntryPtr cur;
539 /*
540 * add all the catalog entries
541 */
542 cur = catal;
543 while (cur != NULL) {
544 if (cur->group == cgroup) {
545 switch (cur->type) {
546 case XML_CATA_REMOVED:
547 break;
548 case XML_CATA_BROKEN_CATALOG:
549 case XML_CATA_CATALOG:
550 if (cur == catal) {
551 cur = cur->children;
552 continue;
553 }
554 break;
555 case XML_CATA_NEXT_CATALOG:
556 node = xmlNewDocNode(doc, ns, BAD_CAST "nextCatalog", NULL);
557 xmlSetProp(node, BAD_CAST "catalog", cur->value);
558 xmlAddChild(catalog, node);
559 break;
560 case XML_CATA_NONE:
561 break;
562 case XML_CATA_GROUP:
563 node = xmlNewDocNode(doc, ns, BAD_CAST "group", NULL);
564 xmlSetProp(node, BAD_CAST "id", cur->name);
William M. Brack6218b312004-10-06 17:52:32 +0000565 if (cur->value != NULL) {
566 xmlNsPtr xns;
567 xns = xmlSearchNsByHref(doc, node, XML_XML_NAMESPACE);
568 if (xns != NULL)
569 xmlSetNsProp(node, xns, BAD_CAST "base",
570 cur->value);
571 }
William M. Brackb7b54de2004-10-06 16:38:01 +0000572 switch (cur->prefer) {
573 case XML_CATA_PREFER_NONE:
574 break;
575 case XML_CATA_PREFER_PUBLIC:
576 xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "public");
577 break;
578 case XML_CATA_PREFER_SYSTEM:
579 xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "system");
580 break;
581 }
582 xmlDumpXMLCatalogNode(cur->next, node, doc, ns, cur);
583 xmlAddChild(catalog, node);
584 break;
585 case XML_CATA_PUBLIC:
586 node = xmlNewDocNode(doc, ns, BAD_CAST "public", NULL);
587 xmlSetProp(node, BAD_CAST "publicId", cur->name);
588 xmlSetProp(node, BAD_CAST "uri", cur->value);
589 xmlAddChild(catalog, node);
590 break;
591 case XML_CATA_SYSTEM:
592 node = xmlNewDocNode(doc, ns, BAD_CAST "system", NULL);
593 xmlSetProp(node, BAD_CAST "systemId", cur->name);
594 xmlSetProp(node, BAD_CAST "uri", cur->value);
595 xmlAddChild(catalog, node);
596 break;
597 case XML_CATA_REWRITE_SYSTEM:
598 node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteSystem", NULL);
599 xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
600 xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
601 xmlAddChild(catalog, node);
602 break;
603 case XML_CATA_DELEGATE_PUBLIC:
604 node = xmlNewDocNode(doc, ns, BAD_CAST "delegatePublic", NULL);
605 xmlSetProp(node, BAD_CAST "publicIdStartString", cur->name);
606 xmlSetProp(node, BAD_CAST "catalog", cur->value);
607 xmlAddChild(catalog, node);
608 break;
609 case XML_CATA_DELEGATE_SYSTEM:
610 node = xmlNewDocNode(doc, ns, BAD_CAST "delegateSystem", NULL);
611 xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
612 xmlSetProp(node, BAD_CAST "catalog", cur->value);
613 xmlAddChild(catalog, node);
614 break;
615 case XML_CATA_URI:
616 node = xmlNewDocNode(doc, ns, BAD_CAST "uri", NULL);
617 xmlSetProp(node, BAD_CAST "name", cur->name);
618 xmlSetProp(node, BAD_CAST "uri", cur->value);
619 xmlAddChild(catalog, node);
620 break;
621 case XML_CATA_REWRITE_URI:
622 node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteURI", NULL);
623 xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
624 xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
625 xmlAddChild(catalog, node);
626 break;
627 case XML_CATA_DELEGATE_URI:
628 node = xmlNewDocNode(doc, ns, BAD_CAST "delegateURI", NULL);
629 xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
630 xmlSetProp(node, BAD_CAST "catalog", cur->value);
631 xmlAddChild(catalog, node);
632 break;
633 case SGML_CATA_SYSTEM:
634 case SGML_CATA_PUBLIC:
635 case SGML_CATA_ENTITY:
636 case SGML_CATA_PENTITY:
637 case SGML_CATA_DOCTYPE:
638 case SGML_CATA_LINKTYPE:
639 case SGML_CATA_NOTATION:
640 case SGML_CATA_DELEGATE:
641 case SGML_CATA_BASE:
642 case SGML_CATA_CATALOG:
643 case SGML_CATA_DOCUMENT:
644 case SGML_CATA_SGMLDECL:
645 break;
646 }
647 }
648 cur = cur->next;
649 }
650}
651
Daniel Veillard75b96822001-10-11 18:59:45 +0000652static int
653xmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) {
654 int ret;
655 xmlDocPtr doc;
656 xmlNsPtr ns;
657 xmlDtdPtr dtd;
William M. Brackb7b54de2004-10-06 16:38:01 +0000658 xmlNodePtr catalog;
Daniel Veillard75b96822001-10-11 18:59:45 +0000659 xmlOutputBufferPtr buf;
Daniel Veillard75b96822001-10-11 18:59:45 +0000660
661 /*
662 * Rebuild a catalog
663 */
664 doc = xmlNewDoc(NULL);
665 if (doc == NULL)
666 return(-1);
667 dtd = xmlNewDtd(doc, BAD_CAST "catalog",
668 BAD_CAST "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN",
669BAD_CAST "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd");
670
671 xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd);
672
673 ns = xmlNewNs(NULL, XML_CATALOGS_NAMESPACE, NULL);
674 if (ns == NULL) {
675 xmlFreeDoc(doc);
676 return(-1);
677 }
678 catalog = xmlNewDocNode(doc, ns, BAD_CAST "catalog", NULL);
679 if (catalog == NULL) {
680 xmlFreeNs(ns);
681 xmlFreeDoc(doc);
682 return(-1);
683 }
684 catalog->nsDef = ns;
685 xmlAddChild((xmlNodePtr) doc, catalog);
686
William M. Brackb7b54de2004-10-06 16:38:01 +0000687 xmlDumpXMLCatalogNode(catal, catalog, doc, ns, NULL);
688
Daniel Veillard75b96822001-10-11 18:59:45 +0000689 /*
690 * reserialize it
691 */
692 buf = xmlOutputBufferCreateFile(out, NULL);
693 if (buf == NULL) {
694 xmlFreeDoc(doc);
695 return(-1);
696 }
697 ret = xmlSaveFormatFileTo(buf, doc, NULL, 1);
698
699 /*
700 * Free it
701 */
702 xmlFreeDoc(doc);
703
704 return(ret);
705}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000706#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard75b96822001-10-11 18:59:45 +0000707
708/************************************************************************
709 * *
710 * Converting SGML Catalogs to XML *
711 * *
712 ************************************************************************/
713
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000714/**
715 * xmlCatalogConvertEntry:
716 * @entry: the entry
Daniel Veillard75b96822001-10-11 18:59:45 +0000717 * @catal: pointer to the catalog being converted
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000718 *
Daniel Veillard75b96822001-10-11 18:59:45 +0000719 * Convert one entry from the catalog
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000720 */
721static void
Daniel Veillard75b96822001-10-11 18:59:45 +0000722xmlCatalogConvertEntry(xmlCatalogEntryPtr entry, xmlCatalogPtr catal) {
723 if ((entry == NULL) || (catal == NULL) || (catal->sgml == NULL) ||
724 (catal->xml == NULL))
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000725 return;
726 switch (entry->type) {
727 case SGML_CATA_ENTITY:
728 entry->type = XML_CATA_PUBLIC;
729 break;
730 case SGML_CATA_PENTITY:
731 entry->type = XML_CATA_PUBLIC;
732 break;
733 case SGML_CATA_DOCTYPE:
734 entry->type = XML_CATA_PUBLIC;
735 break;
736 case SGML_CATA_LINKTYPE:
737 entry->type = XML_CATA_PUBLIC;
738 break;
739 case SGML_CATA_NOTATION:
740 entry->type = XML_CATA_PUBLIC;
741 break;
742 case SGML_CATA_PUBLIC:
743 entry->type = XML_CATA_PUBLIC;
744 break;
745 case SGML_CATA_SYSTEM:
746 entry->type = XML_CATA_SYSTEM;
747 break;
748 case SGML_CATA_DELEGATE:
749 entry->type = XML_CATA_DELEGATE_PUBLIC;
750 break;
751 case SGML_CATA_CATALOG:
752 entry->type = XML_CATA_CATALOG;
753 break;
754 default:
Daniel Veillard75b96822001-10-11 18:59:45 +0000755 xmlHashRemoveEntry(catal->sgml, entry->name,
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000756 (xmlHashDeallocator) xmlFreeCatalogEntry);
757 return;
758 }
759 /*
760 * Conversion successful, remove from the SGML catalog
761 * and add it to the default XML one
762 */
Daniel Veillard75b96822001-10-11 18:59:45 +0000763 xmlHashRemoveEntry(catal->sgml, entry->name, NULL);
764 entry->parent = catal->xml;
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000765 entry->next = NULL;
Daniel Veillard75b96822001-10-11 18:59:45 +0000766 if (catal->xml->children == NULL)
767 catal->xml->children = entry;
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000768 else {
769 xmlCatalogEntryPtr prev;
770
Daniel Veillard75b96822001-10-11 18:59:45 +0000771 prev = catal->xml->children;
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000772 while (prev->next != NULL)
773 prev = prev->next;
774 prev->next = entry;
775 }
Daniel Veillard75b96822001-10-11 18:59:45 +0000776}
777
778/**
779 * xmlConvertSGMLCatalog:
780 * @catal: the catalog
781 *
782 * Convert all the SGML catalog entries as XML ones
783 *
784 * Returns the number of entries converted if successful, -1 otherwise
785 */
786int
787xmlConvertSGMLCatalog(xmlCatalogPtr catal) {
788
789 if ((catal == NULL) || (catal->type != XML_SGML_CATALOG_TYPE))
790 return(-1);
791
792 if (xmlDebugCatalogs) {
793 xmlGenericError(xmlGenericErrorContext,
794 "Converting SGML catalog to XML\n");
795 }
796 xmlHashScan(catal->sgml,
797 (xmlHashScanner) xmlCatalogConvertEntry,
798 &catal);
799 return(0);
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000800}
801
Daniel Veillarda7374592001-05-10 14:17:55 +0000802/************************************************************************
803 * *
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000804 * Helper function *
805 * *
806 ************************************************************************/
807
808/**
809 * xmlCatalogUnWrapURN:
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000810 * @urn: an "urn:publicid:" to unwrap
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000811 *
812 * Expand the URN into the equivalent Public Identifier
813 *
814 * Returns the new identifier or NULL, the string must be deallocated
815 * by the caller.
816 */
817static xmlChar *
818xmlCatalogUnWrapURN(const xmlChar *urn) {
819 xmlChar result[2000];
820 unsigned int i = 0;
821
822 if (xmlStrncmp(urn, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1))
823 return(NULL);
824 urn += sizeof(XML_URN_PUBID) - 1;
825
826 while (*urn != 0) {
Daniel Veillard770075b2004-02-25 10:44:30 +0000827 if (i > sizeof(result) - 4)
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000828 break;
829 if (*urn == '+') {
830 result[i++] = ' ';
831 urn++;
832 } else if (*urn == ':') {
833 result[i++] = '/';
834 result[i++] = '/';
835 urn++;
836 } else if (*urn == ';') {
837 result[i++] = ':';
838 result[i++] = ':';
839 urn++;
840 } else if (*urn == '%') {
Daniel Veillard770075b2004-02-25 10:44:30 +0000841 if ((urn[1] == '2') && (urn[2] == 'B'))
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000842 result[i++] = '+';
Daniel Veillard770075b2004-02-25 10:44:30 +0000843 else if ((urn[1] == '3') && (urn[2] == 'A'))
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000844 result[i++] = ':';
Daniel Veillard770075b2004-02-25 10:44:30 +0000845 else if ((urn[1] == '2') && (urn[2] == 'F'))
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000846 result[i++] = '/';
Daniel Veillard770075b2004-02-25 10:44:30 +0000847 else if ((urn[1] == '3') && (urn[2] == 'B'))
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000848 result[i++] = ';';
Daniel Veillard770075b2004-02-25 10:44:30 +0000849 else if ((urn[1] == '2') && (urn[2] == '7'))
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000850 result[i++] = '\'';
Daniel Veillard770075b2004-02-25 10:44:30 +0000851 else if ((urn[1] == '3') && (urn[2] == 'F'))
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000852 result[i++] = '?';
Daniel Veillard770075b2004-02-25 10:44:30 +0000853 else if ((urn[1] == '2') && (urn[2] == '3'))
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000854 result[i++] = '#';
Daniel Veillard770075b2004-02-25 10:44:30 +0000855 else if ((urn[1] == '2') && (urn[2] == '5'))
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000856 result[i++] = '%';
857 else {
858 result[i++] = *urn;
859 urn++;
860 continue;
861 }
862 urn += 3;
863 } else {
864 result[i++] = *urn;
865 urn++;
866 }
867 }
868 result[i] = 0;
869
870 return(xmlStrdup(result));
871}
872
Daniel Veillard9f7b84b2001-08-23 15:31:19 +0000873/**
874 * xmlParseCatalogFile:
875 * @filename: the filename
876 *
877 * parse an XML file and build a tree. It's like xmlParseFile()
878 * except it bypass all catalog lookups.
879 *
880 * Returns the resulting document tree or NULL in case of error
881 */
882
883xmlDocPtr
884xmlParseCatalogFile(const char *filename) {
885 xmlDocPtr ret;
886 xmlParserCtxtPtr ctxt;
887 char *directory = NULL;
888 xmlParserInputPtr inputStream;
889 xmlParserInputBufferPtr buf;
890
891 ctxt = xmlNewParserCtxt();
892 if (ctxt == NULL) {
Daniel Veillardd0cf7f62004-11-09 16:17:02 +0000893#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard9f7b84b2001-08-23 15:31:19 +0000894 if (xmlDefaultSAXHandler.error != NULL) {
895 xmlDefaultSAXHandler.error(NULL, "out of memory\n");
896 }
Daniel Veillardd0cf7f62004-11-09 16:17:02 +0000897#endif
Daniel Veillard9f7b84b2001-08-23 15:31:19 +0000898 return(NULL);
899 }
900
901 buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
902 if (buf == NULL) {
903 xmlFreeParserCtxt(ctxt);
904 return(NULL);
905 }
906
907 inputStream = xmlNewInputStream(ctxt);
908 if (inputStream == NULL) {
909 xmlFreeParserCtxt(ctxt);
910 return(NULL);
911 }
912
Daniel Veillardc3ca5ba2003-05-09 22:26:28 +0000913 inputStream->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
Daniel Veillard9f7b84b2001-08-23 15:31:19 +0000914 inputStream->buf = buf;
915 inputStream->base = inputStream->buf->buffer->content;
916 inputStream->cur = inputStream->buf->buffer->content;
917 inputStream->end =
918 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
919
920 inputPush(ctxt, inputStream);
921 if ((ctxt->directory == NULL) && (directory == NULL))
922 directory = xmlParserGetDirectory(filename);
923 if ((ctxt->directory == NULL) && (directory != NULL))
924 ctxt->directory = directory;
Daniel Veillard6990bf32001-08-23 21:17:48 +0000925 ctxt->valid = 0;
926 ctxt->validate = 0;
927 ctxt->loadsubset = 0;
928 ctxt->pedantic = 0;
Daniel Veillard03a53c32004-10-26 16:06:51 +0000929 ctxt->dictNames = 1;
Daniel Veillard9f7b84b2001-08-23 15:31:19 +0000930
931 xmlParseDocument(ctxt);
932
933 if (ctxt->wellFormed)
934 ret = ctxt->myDoc;
935 else {
936 ret = NULL;
937 xmlFreeDoc(ctxt->myDoc);
938 ctxt->myDoc = NULL;
939 }
940 xmlFreeParserCtxt(ctxt);
941
942 return(ret);
943}
944
Daniel Veillard75b96822001-10-11 18:59:45 +0000945/**
946 * xmlLoadFileContent:
947 * @filename: a file path
948 *
949 * Load a file content into memory.
950 *
951 * Returns a pointer to the 0 terminated string or NULL in case of error
952 */
953static xmlChar *
954xmlLoadFileContent(const char *filename)
955{
956#ifdef HAVE_STAT
957 int fd;
958#else
959 FILE *fd;
960#endif
961 int len;
962 long size;
963
964#ifdef HAVE_STAT
965 struct stat info;
966#endif
967 xmlChar *content;
968
969 if (filename == NULL)
970 return (NULL);
971
972#ifdef HAVE_STAT
973 if (stat(filename, &info) < 0)
974 return (NULL);
975#endif
976
977#ifdef HAVE_STAT
Daniel Veillard5aad8322002-12-11 15:59:44 +0000978 if ((fd = open(filename, O_RDONLY)) < 0)
Daniel Veillard75b96822001-10-11 18:59:45 +0000979#else
Daniel Veillard5aad8322002-12-11 15:59:44 +0000980 if ((fd = fopen(filename, "rb")) == NULL)
Daniel Veillard75b96822001-10-11 18:59:45 +0000981#endif
Daniel Veillard5aad8322002-12-11 15:59:44 +0000982 {
Daniel Veillard75b96822001-10-11 18:59:45 +0000983 return (NULL);
984 }
985#ifdef HAVE_STAT
986 size = info.st_size;
987#else
988 if (fseek(fd, 0, SEEK_END) || (size = ftell(fd)) == EOF || fseek(fd, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */
989 fclose(fd);
990 return (NULL);
991 }
992#endif
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000993 content = xmlMallocAtomic(size + 10);
Daniel Veillard75b96822001-10-11 18:59:45 +0000994 if (content == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +0000995 xmlCatalogErrMemory("allocating catalog data");
Daniel Veillard75b96822001-10-11 18:59:45 +0000996 return (NULL);
997 }
998#ifdef HAVE_STAT
999 len = read(fd, content, size);
Carlo Braminic43ac662010-10-14 14:27:54 +02001000 close(fd);
Daniel Veillard75b96822001-10-11 18:59:45 +00001001#else
1002 len = fread(content, 1, size, fd);
Carlo Braminic43ac662010-10-14 14:27:54 +02001003 fclose(fd);
Daniel Veillard75b96822001-10-11 18:59:45 +00001004#endif
1005 if (len < 0) {
1006 xmlFree(content);
1007 return (NULL);
1008 }
Daniel Veillard75b96822001-10-11 18:59:45 +00001009 content[len] = 0;
1010
1011 return(content);
1012}
1013
Daniel Veillardc8155052004-07-16 09:03:08 +00001014/**
1015 * xmlCatalogNormalizePublic:
1016 * @pubID: the public ID string
1017 *
1018 * Normalizes the Public Identifier
1019 *
1020 * Implements 6.2. Public Identifier Normalization
1021 * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1022 *
1023 * Returns the new string or NULL, the string must be deallocated
1024 * by the caller.
1025 */
1026static xmlChar *
1027xmlCatalogNormalizePublic(const xmlChar *pubID)
1028{
1029 int ok = 1;
1030 int white;
1031 const xmlChar *p;
1032 xmlChar *ret;
1033 xmlChar *q;
1034
1035 if (pubID == NULL)
1036 return(NULL);
1037
1038 white = 1;
1039 for (p = pubID;*p != 0 && ok;p++) {
1040 if (!xmlIsBlank_ch(*p))
1041 white = 0;
1042 else if (*p == 0x20 && !white)
1043 white = 1;
1044 else
1045 ok = 0;
1046 }
1047 if (ok && !white) /* is normalized */
1048 return(NULL);
1049
1050 ret = xmlStrdup(pubID);
1051 q = ret;
1052 white = 0;
1053 for (p = pubID;*p != 0;p++) {
1054 if (xmlIsBlank_ch(*p)) {
1055 if (q != ret)
1056 white = 1;
1057 } else {
1058 if (white) {
1059 *(q++) = 0x20;
1060 white = 0;
1061 }
1062 *(q++) = *p;
1063 }
1064 }
1065 *q = 0;
1066 return(ret);
1067}
1068
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001069/************************************************************************
1070 * *
Daniel Veillard344cee72001-08-20 00:08:40 +00001071 * The XML Catalog parser *
1072 * *
1073 ************************************************************************/
1074
1075static xmlCatalogEntryPtr
1076xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename);
Daniel Veillard344cee72001-08-20 00:08:40 +00001077static void
1078xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
William M. Brackb7b54de2004-10-06 16:38:01 +00001079 xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup);
Daniel Veillardcda96922001-08-21 10:56:31 +00001080static xmlChar *
1081xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1082 const xmlChar *sysID);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001083static xmlChar *
1084xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI);
1085
Daniel Veillard344cee72001-08-20 00:08:40 +00001086
Daniel Veillard75b96822001-10-11 18:59:45 +00001087/**
1088 * xmlGetXMLCatalogEntryType:
1089 * @name: the name
1090 *
1091 * lookup the internal type associated to an XML catalog entry name
1092 *
Daniel Veillard06d25242004-02-25 13:01:42 +00001093 * Returns the type associated with that name
Daniel Veillard75b96822001-10-11 18:59:45 +00001094 */
Daniel Veillard344cee72001-08-20 00:08:40 +00001095static xmlCatalogEntryType
1096xmlGetXMLCatalogEntryType(const xmlChar *name) {
1097 xmlCatalogEntryType type = XML_CATA_NONE;
1098 if (xmlStrEqual(name, (const xmlChar *) "system"))
1099 type = XML_CATA_SYSTEM;
1100 else if (xmlStrEqual(name, (const xmlChar *) "public"))
1101 type = XML_CATA_PUBLIC;
1102 else if (xmlStrEqual(name, (const xmlChar *) "rewriteSystem"))
1103 type = XML_CATA_REWRITE_SYSTEM;
1104 else if (xmlStrEqual(name, (const xmlChar *) "delegatePublic"))
1105 type = XML_CATA_DELEGATE_PUBLIC;
1106 else if (xmlStrEqual(name, (const xmlChar *) "delegateSystem"))
1107 type = XML_CATA_DELEGATE_SYSTEM;
1108 else if (xmlStrEqual(name, (const xmlChar *) "uri"))
1109 type = XML_CATA_URI;
1110 else if (xmlStrEqual(name, (const xmlChar *) "rewriteURI"))
1111 type = XML_CATA_REWRITE_URI;
1112 else if (xmlStrEqual(name, (const xmlChar *) "delegateURI"))
1113 type = XML_CATA_DELEGATE_URI;
1114 else if (xmlStrEqual(name, (const xmlChar *) "nextCatalog"))
1115 type = XML_CATA_NEXT_CATALOG;
1116 else if (xmlStrEqual(name, (const xmlChar *) "catalog"))
1117 type = XML_CATA_CATALOG;
1118 return(type);
1119}
1120
Daniel Veillard75b96822001-10-11 18:59:45 +00001121/**
1122 * xmlParseXMLCatalogOneNode:
1123 * @cur: the XML node
1124 * @type: the type of Catalog entry
1125 * @name: the name of the node
1126 * @attrName: the attribute holding the value
1127 * @uriAttrName: the attribute holding the URI-Reference
1128 * @prefer: the PUBLIC vs. SYSTEM current preference value
William M. Brackb7b54de2004-10-06 16:38:01 +00001129 * @cgroup: the group which includes this node
Daniel Veillard75b96822001-10-11 18:59:45 +00001130 *
1131 * Finishes the examination of an XML tree node of a catalog and build
1132 * a Catalog entry from it.
1133 *
1134 * Returns the new Catalog entry node or NULL in case of error.
1135 */
Daniel Veillard344cee72001-08-20 00:08:40 +00001136static xmlCatalogEntryPtr
1137xmlParseXMLCatalogOneNode(xmlNodePtr cur, xmlCatalogEntryType type,
1138 const xmlChar *name, const xmlChar *attrName,
William M. Brackb7b54de2004-10-06 16:38:01 +00001139 const xmlChar *uriAttrName, xmlCatalogPrefer prefer,
1140 xmlCatalogEntryPtr cgroup) {
Daniel Veillard344cee72001-08-20 00:08:40 +00001141 int ok = 1;
1142 xmlChar *uriValue;
1143 xmlChar *nameValue = NULL;
1144 xmlChar *base = NULL;
1145 xmlChar *URL = NULL;
1146 xmlCatalogEntryPtr ret = NULL;
1147
1148 if (attrName != NULL) {
1149 nameValue = xmlGetProp(cur, attrName);
1150 if (nameValue == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001151 xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
1152 "%s entry lacks '%s'\n", name, attrName, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001153 ok = 0;
1154 }
1155 }
1156 uriValue = xmlGetProp(cur, uriAttrName);
1157 if (uriValue == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001158 xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
1159 "%s entry lacks '%s'\n", name, uriAttrName, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001160 ok = 0;
1161 }
1162 if (!ok) {
1163 if (nameValue != NULL)
1164 xmlFree(nameValue);
1165 if (uriValue != NULL)
1166 xmlFree(uriValue);
1167 return(NULL);
1168 }
1169
1170 base = xmlNodeGetBase(cur->doc, cur);
1171 URL = xmlBuildURI(uriValue, base);
1172 if (URL != NULL) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001173 if (xmlDebugCatalogs > 1) {
Daniel Veillard344cee72001-08-20 00:08:40 +00001174 if (nameValue != NULL)
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001175 xmlGenericError(xmlGenericErrorContext,
1176 "Found %s: '%s' '%s'\n", name, nameValue, URL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001177 else
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001178 xmlGenericError(xmlGenericErrorContext,
1179 "Found %s: '%s'\n", name, URL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001180 }
William M. Brackb7b54de2004-10-06 16:38:01 +00001181 ret = xmlNewCatalogEntry(type, nameValue, uriValue, URL, prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001182 } else {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001183 xmlCatalogErr(ret, cur, XML_CATALOG_ENTRY_BROKEN,
Daniel Veillard344cee72001-08-20 00:08:40 +00001184 "%s entry '%s' broken ?: %s\n", name, uriAttrName, uriValue);
1185 }
1186 if (nameValue != NULL)
1187 xmlFree(nameValue);
1188 if (uriValue != NULL)
1189 xmlFree(uriValue);
1190 if (base != NULL)
1191 xmlFree(base);
1192 if (URL != NULL)
1193 xmlFree(URL);
1194 return(ret);
1195}
1196
Daniel Veillard75b96822001-10-11 18:59:45 +00001197/**
1198 * xmlParseXMLCatalogNode:
1199 * @cur: the XML node
1200 * @prefer: the PUBLIC vs. SYSTEM current preference value
1201 * @parent: the parent Catalog entry
William M. Brackb7b54de2004-10-06 16:38:01 +00001202 * @cgroup: the group which includes this node
Daniel Veillard75b96822001-10-11 18:59:45 +00001203 *
1204 * Examines an XML tree node of a catalog and build
1205 * a Catalog entry from it adding it to its parent. The examination can
1206 * be recursive.
1207 */
Daniel Veillard344cee72001-08-20 00:08:40 +00001208static void
1209xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer,
William M. Brackb7b54de2004-10-06 16:38:01 +00001210 xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup)
Daniel Veillard344cee72001-08-20 00:08:40 +00001211{
Daniel Veillard344cee72001-08-20 00:08:40 +00001212 xmlChar *base = NULL;
1213 xmlCatalogEntryPtr entry = NULL;
1214
1215 if (cur == NULL)
1216 return;
1217 if (xmlStrEqual(cur->name, BAD_CAST "group")) {
1218 xmlChar *prop;
William M. Brackb7b54de2004-10-06 16:38:01 +00001219 xmlCatalogPrefer pref = XML_CATA_PREFER_NONE;
Daniel Veillard344cee72001-08-20 00:08:40 +00001220
1221 prop = xmlGetProp(cur, BAD_CAST "prefer");
1222 if (prop != NULL) {
1223 if (xmlStrEqual(prop, BAD_CAST "system")) {
1224 prefer = XML_CATA_PREFER_SYSTEM;
1225 } else if (xmlStrEqual(prop, BAD_CAST "public")) {
1226 prefer = XML_CATA_PREFER_PUBLIC;
1227 } else {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001228 xmlCatalogErr(parent, cur, XML_CATALOG_PREFER_VALUE,
1229 "Invalid value for prefer: '%s'\n",
1230 prop, NULL, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001231 }
1232 xmlFree(prop);
William M. Brackb7b54de2004-10-06 16:38:01 +00001233 pref = prefer;
Daniel Veillard344cee72001-08-20 00:08:40 +00001234 }
William M. Brackb7b54de2004-10-06 16:38:01 +00001235 prop = xmlGetProp(cur, BAD_CAST "id");
1236 base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE);
1237 entry = xmlNewCatalogEntry(XML_CATA_GROUP, prop, base, NULL, pref, cgroup);
William M. Brack181a1ca2004-10-06 18:00:29 +00001238 xmlFree(prop);
Daniel Veillard344cee72001-08-20 00:08:40 +00001239 } else if (xmlStrEqual(cur->name, BAD_CAST "public")) {
1240 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_PUBLIC,
William M. Brackb7b54de2004-10-06 16:38:01 +00001241 BAD_CAST "public", BAD_CAST "publicId", BAD_CAST "uri", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001242 } else if (xmlStrEqual(cur->name, BAD_CAST "system")) {
1243 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_SYSTEM,
William M. Brackb7b54de2004-10-06 16:38:01 +00001244 BAD_CAST "system", BAD_CAST "systemId", BAD_CAST "uri", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001245 } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteSystem")) {
1246 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_SYSTEM,
1247 BAD_CAST "rewriteSystem", BAD_CAST "systemIdStartString",
William M. Brackb7b54de2004-10-06 16:38:01 +00001248 BAD_CAST "rewritePrefix", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001249 } else if (xmlStrEqual(cur->name, BAD_CAST "delegatePublic")) {
1250 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_PUBLIC,
1251 BAD_CAST "delegatePublic", BAD_CAST "publicIdStartString",
William M. Brackb7b54de2004-10-06 16:38:01 +00001252 BAD_CAST "catalog", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001253 } else if (xmlStrEqual(cur->name, BAD_CAST "delegateSystem")) {
1254 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_SYSTEM,
1255 BAD_CAST "delegateSystem", BAD_CAST "systemIdStartString",
William M. Brackb7b54de2004-10-06 16:38:01 +00001256 BAD_CAST "catalog", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001257 } else if (xmlStrEqual(cur->name, BAD_CAST "uri")) {
1258 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_URI,
1259 BAD_CAST "uri", BAD_CAST "name",
William M. Brackb7b54de2004-10-06 16:38:01 +00001260 BAD_CAST "uri", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001261 } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteURI")) {
1262 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_URI,
1263 BAD_CAST "rewriteURI", BAD_CAST "uriStartString",
William M. Brackb7b54de2004-10-06 16:38:01 +00001264 BAD_CAST "rewritePrefix", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001265 } else if (xmlStrEqual(cur->name, BAD_CAST "delegateURI")) {
1266 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_URI,
1267 BAD_CAST "delegateURI", BAD_CAST "uriStartString",
William M. Brackb7b54de2004-10-06 16:38:01 +00001268 BAD_CAST "catalog", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001269 } else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) {
1270 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG,
1271 BAD_CAST "nextCatalog", NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00001272 BAD_CAST "catalog", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001273 }
William M. Brackb031cef2004-11-05 16:34:22 +00001274 if (entry != NULL) {
1275 if (parent != NULL) {
1276 entry->parent = parent;
1277 if (parent->children == NULL)
1278 parent->children = entry;
1279 else {
1280 xmlCatalogEntryPtr prev;
Daniel Veillard344cee72001-08-20 00:08:40 +00001281
William M. Brackb031cef2004-11-05 16:34:22 +00001282 prev = parent->children;
1283 while (prev->next != NULL)
1284 prev = prev->next;
1285 prev->next = entry;
1286 }
Daniel Veillard344cee72001-08-20 00:08:40 +00001287 }
William M. Brackb031cef2004-11-05 16:34:22 +00001288 if (entry->type == XML_CATA_GROUP) {
1289 /*
1290 * Recurse to propagate prefer to the subtree
1291 * (xml:base handling is automated)
1292 */
1293 xmlParseXMLCatalogNodeList(cur->children, prefer, parent, entry);
1294 }
William M. Brackb7b54de2004-10-06 16:38:01 +00001295 }
Daniel Veillard344cee72001-08-20 00:08:40 +00001296 if (base != NULL)
1297 xmlFree(base);
Daniel Veillard344cee72001-08-20 00:08:40 +00001298}
1299
Daniel Veillard75b96822001-10-11 18:59:45 +00001300/**
1301 * xmlParseXMLCatalogNodeList:
1302 * @cur: the XML node list of siblings
1303 * @prefer: the PUBLIC vs. SYSTEM current preference value
1304 * @parent: the parent Catalog entry
William M. Brackb7b54de2004-10-06 16:38:01 +00001305 * @cgroup: the group which includes this list
Daniel Veillard75b96822001-10-11 18:59:45 +00001306 *
1307 * Examines a list of XML sibling nodes of a catalog and build
1308 * a list of Catalog entry from it adding it to the parent.
1309 * The examination will recurse to examine node subtrees.
1310 */
Daniel Veillard344cee72001-08-20 00:08:40 +00001311static void
1312xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
William M. Brackb7b54de2004-10-06 16:38:01 +00001313 xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup) {
Daniel Veillard344cee72001-08-20 00:08:40 +00001314 while (cur != NULL) {
1315 if ((cur->ns != NULL) && (cur->ns->href != NULL) &&
1316 (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) {
William M. Brackb7b54de2004-10-06 16:38:01 +00001317 xmlParseXMLCatalogNode(cur, prefer, parent, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001318 }
1319 cur = cur->next;
1320 }
1321 /* TODO: sort the list according to REWRITE lengths and prefer value */
1322}
1323
Daniel Veillard75b96822001-10-11 18:59:45 +00001324/**
Daniel Veillard75b96822001-10-11 18:59:45 +00001325 * xmlParseXMLCatalogFile:
1326 * @prefer: the PUBLIC vs. SYSTEM current preference value
1327 * @filename: the filename for the catalog
1328 *
1329 * Parses the catalog file to extract the XML tree and then analyze the
1330 * tree to build a list of Catalog entries corresponding to this catalog
1331 *
1332 * Returns the resulting Catalog entries list
1333 */
Daniel Veillard344cee72001-08-20 00:08:40 +00001334static xmlCatalogEntryPtr
1335xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename) {
1336 xmlDocPtr doc;
1337 xmlNodePtr cur;
1338 xmlChar *prop;
1339 xmlCatalogEntryPtr parent = NULL;
1340
1341 if (filename == NULL)
1342 return(NULL);
1343
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00001344 doc = xmlParseCatalogFile((const char *) filename);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001345 if (doc == NULL) {
1346 if (xmlDebugCatalogs)
1347 xmlGenericError(xmlGenericErrorContext,
1348 "Failed to parse catalog %s\n", filename);
Daniel Veillard344cee72001-08-20 00:08:40 +00001349 return(NULL);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001350 }
1351
1352 if (xmlDebugCatalogs)
1353 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard3c01b1d2001-10-17 15:58:35 +00001354 "%d Parsing catalog %s\n", xmlGetThreadId(), filename);
Daniel Veillard344cee72001-08-20 00:08:40 +00001355
1356 cur = xmlDocGetRootElement(doc);
1357 if ((cur != NULL) && (xmlStrEqual(cur->name, BAD_CAST "catalog")) &&
1358 (cur->ns != NULL) && (cur->ns->href != NULL) &&
1359 (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) {
1360
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001361 parent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00001362 (const xmlChar *)filename, NULL, prefer, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001363 if (parent == NULL) {
1364 xmlFreeDoc(doc);
1365 return(NULL);
1366 }
1367
1368 prop = xmlGetProp(cur, BAD_CAST "prefer");
1369 if (prop != NULL) {
1370 if (xmlStrEqual(prop, BAD_CAST "system")) {
1371 prefer = XML_CATA_PREFER_SYSTEM;
1372 } else if (xmlStrEqual(prop, BAD_CAST "public")) {
1373 prefer = XML_CATA_PREFER_PUBLIC;
1374 } else {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001375 xmlCatalogErr(NULL, cur, XML_CATALOG_PREFER_VALUE,
1376 "Invalid value for prefer: '%s'\n",
1377 prop, NULL, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001378 }
1379 xmlFree(prop);
1380 }
1381 cur = cur->children;
William M. Brackb7b54de2004-10-06 16:38:01 +00001382 xmlParseXMLCatalogNodeList(cur, prefer, parent, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001383 } else {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001384 xmlCatalogErr(NULL, (xmlNodePtr) doc, XML_CATALOG_NOT_CATALOG,
1385 "File %s is not an XML Catalog\n",
1386 filename, NULL, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001387 xmlFreeDoc(doc);
1388 return(NULL);
1389 }
1390 xmlFreeDoc(doc);
1391 return(parent);
1392}
1393
Daniel Veillardcda96922001-08-21 10:56:31 +00001394/**
1395 * xmlFetchXMLCatalogFile:
1396 * @catal: an existing but incomplete catalog entry
1397 *
1398 * Fetch and parse the subcatalog referenced by an entry
Daniel Veillardcda96922001-08-21 10:56:31 +00001399 *
1400 * Returns 0 in case of success, -1 otherwise
1401 */
1402static int
1403xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) {
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001404 xmlCatalogEntryPtr doc;
Daniel Veillardcda96922001-08-21 10:56:31 +00001405
1406 if (catal == NULL)
1407 return(-1);
Daniel Veillardc853b322001-11-06 15:24:37 +00001408 if (catal->URL == NULL)
Daniel Veillardcda96922001-08-21 10:56:31 +00001409 return(-1);
1410 if (catal->children != NULL)
1411 return(-1);
1412
Daniel Veillard81463942001-10-16 12:34:39 +00001413 /*
1414 * lock the whole catalog for modification
1415 */
1416 xmlRMutexLock(xmlCatalogMutex);
1417 if (catal->children != NULL) {
1418 /* Okay someone else did it in the meantime */
1419 xmlRMutexUnlock(xmlCatalogMutex);
1420 return(0);
Daniel Veillard81463942001-10-16 12:34:39 +00001421 }
1422
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001423 if (xmlCatalogXMLFiles != NULL) {
1424 doc = (xmlCatalogEntryPtr)
Daniel Veillardc853b322001-11-06 15:24:37 +00001425 xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001426 if (doc != NULL) {
1427 if (xmlDebugCatalogs)
1428 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001429 "Found %s in file hash\n", catal->URL);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001430
1431 if (catal->type == XML_CATA_CATALOG)
1432 catal->children = doc->children;
1433 else
1434 catal->children = doc;
1435 catal->dealloc = 0;
1436 xmlRMutexUnlock(xmlCatalogMutex);
1437 return(0);
1438 }
1439 if (xmlDebugCatalogs)
1440 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001441 "%s not found in file hash\n", catal->URL);
Daniel Veillard6990bf32001-08-23 21:17:48 +00001442 }
1443
Daniel Veillardcda96922001-08-21 10:56:31 +00001444 /*
Daniel Veillard75b96822001-10-11 18:59:45 +00001445 * Fetch and parse. Note that xmlParseXMLCatalogFile does not
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001446 * use the existing catalog, there is no recursion allowed at
Daniel Veillard75b96822001-10-11 18:59:45 +00001447 * that level.
Daniel Veillardcda96922001-08-21 10:56:31 +00001448 */
Daniel Veillardc853b322001-11-06 15:24:37 +00001449 doc = xmlParseXMLCatalogFile(catal->prefer, catal->URL);
Daniel Veillard6990bf32001-08-23 21:17:48 +00001450 if (doc == NULL) {
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00001451 catal->type = XML_CATA_BROKEN_CATALOG;
Daniel Veillard81463942001-10-16 12:34:39 +00001452 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillardcda96922001-08-21 10:56:31 +00001453 return(-1);
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00001454 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001455
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001456 if (catal->type == XML_CATA_CATALOG)
1457 catal->children = doc->children;
1458 else
1459 catal->children = doc;
1460
1461 doc->dealloc = 1;
1462
Daniel Veillard81463942001-10-16 12:34:39 +00001463 if (xmlCatalogXMLFiles == NULL)
1464 xmlCatalogXMLFiles = xmlHashCreate(10);
1465 if (xmlCatalogXMLFiles != NULL) {
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001466 if (xmlDebugCatalogs)
1467 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001468 "%s added to file hash\n", catal->URL);
1469 xmlHashAddEntry(xmlCatalogXMLFiles, catal->URL, doc);
Daniel Veillardcda96922001-08-21 10:56:31 +00001470 }
Daniel Veillard81463942001-10-16 12:34:39 +00001471 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillardcda96922001-08-21 10:56:31 +00001472 return(0);
1473}
1474
Daniel Veillard75b96822001-10-11 18:59:45 +00001475/************************************************************************
1476 * *
1477 * XML Catalog handling *
1478 * *
1479 ************************************************************************/
Daniel Veillard344cee72001-08-20 00:08:40 +00001480
1481/**
1482 * xmlAddXMLCatalog:
1483 * @catal: top of an XML catalog
1484 * @type: the type of record to add to the catalog
Daniel Veillardcda96922001-08-21 10:56:31 +00001485 * @orig: the system, public or prefix to match (or NULL)
Daniel Veillard344cee72001-08-20 00:08:40 +00001486 * @replace: the replacement value for the match
1487 *
1488 * Add an entry in the XML catalog, it may overwrite existing but
1489 * different entries.
1490 *
1491 * Returns 0 if successful, -1 otherwise
1492 */
1493static int
1494xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type,
1495 const xmlChar *orig, const xmlChar *replace) {
1496 xmlCatalogEntryPtr cur;
1497 xmlCatalogEntryType typ;
Daniel Veillardc853b322001-11-06 15:24:37 +00001498 int doregister = 0;
Daniel Veillard344cee72001-08-20 00:08:40 +00001499
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00001500 if ((catal == NULL) ||
1501 ((catal->type != XML_CATA_CATALOG) &&
1502 (catal->type != XML_CATA_BROKEN_CATALOG)))
Daniel Veillard344cee72001-08-20 00:08:40 +00001503 return(-1);
Daniel Veillardffe09c92001-11-05 14:21:47 +00001504 if (catal->children == NULL) {
1505 xmlFetchXMLCatalogFile(catal);
1506 }
Daniel Veillardc853b322001-11-06 15:24:37 +00001507 if (catal->children == NULL)
1508 doregister = 1;
1509
Daniel Veillard344cee72001-08-20 00:08:40 +00001510 typ = xmlGetXMLCatalogEntryType(type);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001511 if (typ == XML_CATA_NONE) {
1512 if (xmlDebugCatalogs)
1513 xmlGenericError(xmlGenericErrorContext,
1514 "Failed to add unknown element %s to catalog\n", type);
Daniel Veillard344cee72001-08-20 00:08:40 +00001515 return(-1);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001516 }
Daniel Veillard344cee72001-08-20 00:08:40 +00001517
1518 cur = catal->children;
1519 /*
1520 * Might be a simple "update in place"
1521 */
1522 if (cur != NULL) {
1523 while (cur != NULL) {
Daniel Veillardcda96922001-08-21 10:56:31 +00001524 if ((orig != NULL) && (cur->type == typ) &&
1525 (xmlStrEqual(orig, cur->name))) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001526 if (xmlDebugCatalogs)
1527 xmlGenericError(xmlGenericErrorContext,
1528 "Updating element %s to catalog\n", type);
Daniel Veillard344cee72001-08-20 00:08:40 +00001529 if (cur->value != NULL)
1530 xmlFree(cur->value);
Daniel Veillardc853b322001-11-06 15:24:37 +00001531 if (cur->URL != NULL)
1532 xmlFree(cur->URL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001533 cur->value = xmlStrdup(replace);
Daniel Veillardc853b322001-11-06 15:24:37 +00001534 cur->URL = xmlStrdup(replace);
Daniel Veillardcda96922001-08-21 10:56:31 +00001535 return(0);
Daniel Veillard344cee72001-08-20 00:08:40 +00001536 }
1537 if (cur->next == NULL)
1538 break;
1539 cur = cur->next;
1540 }
1541 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001542 if (xmlDebugCatalogs)
1543 xmlGenericError(xmlGenericErrorContext,
1544 "Adding element %s to catalog\n", type);
Daniel Veillard344cee72001-08-20 00:08:40 +00001545 if (cur == NULL)
Daniel Veillardc853b322001-11-06 15:24:37 +00001546 catal->children = xmlNewCatalogEntry(typ, orig, replace,
William M. Brackb7b54de2004-10-06 16:38:01 +00001547 NULL, catal->prefer, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001548 else
Daniel Veillardc853b322001-11-06 15:24:37 +00001549 cur->next = xmlNewCatalogEntry(typ, orig, replace,
William M. Brackb7b54de2004-10-06 16:38:01 +00001550 NULL, catal->prefer, NULL);
Daniel Veillardc853b322001-11-06 15:24:37 +00001551 if (doregister) {
Daniel Veillard27bec142006-02-24 20:22:27 +00001552 catal->type = XML_CATA_CATALOG;
Daniel Veillardc853b322001-11-06 15:24:37 +00001553 cur = xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
1554 if (cur != NULL)
1555 cur->children = catal->children;
1556 }
1557
Daniel Veillardcda96922001-08-21 10:56:31 +00001558 return(0);
1559}
1560
1561/**
1562 * xmlDelXMLCatalog:
1563 * @catal: top of an XML catalog
Daniel Veillard60087f32001-10-10 09:45:09 +00001564 * @value: the value to remove from the catalog
Daniel Veillardcda96922001-08-21 10:56:31 +00001565 *
1566 * Remove entries in the XML catalog where the value or the URI
1567 * is equal to @value
1568 *
1569 * Returns the number of entries removed if successful, -1 otherwise
1570 */
1571static int
1572xmlDelXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *value) {
Daniel Veillardc853b322001-11-06 15:24:37 +00001573 xmlCatalogEntryPtr cur;
Daniel Veillardcda96922001-08-21 10:56:31 +00001574 int ret = 0;
1575
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00001576 if ((catal == NULL) ||
1577 ((catal->type != XML_CATA_CATALOG) &&
1578 (catal->type != XML_CATA_BROKEN_CATALOG)))
Daniel Veillardcda96922001-08-21 10:56:31 +00001579 return(-1);
1580 if (value == NULL)
1581 return(-1);
Daniel Veillardffe09c92001-11-05 14:21:47 +00001582 if (catal->children == NULL) {
1583 xmlFetchXMLCatalogFile(catal);
1584 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001585
1586 /*
1587 * Scan the children
1588 */
1589 cur = catal->children;
Daniel Veillardcda96922001-08-21 10:56:31 +00001590 while (cur != NULL) {
1591 if (((cur->name != NULL) && (xmlStrEqual(value, cur->name))) ||
1592 (xmlStrEqual(value, cur->value))) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001593 if (xmlDebugCatalogs) {
1594 if (cur->name != NULL)
1595 xmlGenericError(xmlGenericErrorContext,
1596 "Removing element %s from catalog\n", cur->name);
1597 else
1598 xmlGenericError(xmlGenericErrorContext,
1599 "Removing element %s from catalog\n", cur->value);
1600 }
Daniel Veillardc853b322001-11-06 15:24:37 +00001601 cur->type = XML_CATA_REMOVED;
Daniel Veillardcda96922001-08-21 10:56:31 +00001602 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001603 cur = cur->next;
1604 }
1605 return(ret);
1606}
1607
1608/**
Daniel Veillardcda96922001-08-21 10:56:31 +00001609 * xmlCatalogXMLResolve:
1610 * @catal: a catalog list
Daniel Veillard06d25242004-02-25 13:01:42 +00001611 * @pubID: the public ID string
1612 * @sysID: the system ID string
Daniel Veillardcda96922001-08-21 10:56:31 +00001613 *
1614 * Do a complete resolution lookup of an External Identifier for a
1615 * list of catalog entries.
1616 *
1617 * Implements (or tries to) 7.1. External Identifier Resolution
1618 * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1619 *
1620 * Returns the URI of the resource or NULL if not found
1621 */
1622static xmlChar *
1623xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1624 const xmlChar *sysID) {
1625 xmlChar *ret = NULL;
1626 xmlCatalogEntryPtr cur;
1627 int haveDelegate = 0;
1628 int haveNext = 0;
1629
1630 /*
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001631 * protection against loops
1632 */
1633 if (catal->depth > MAX_CATAL_DEPTH) {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001634 xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
1635 "Detected recursion in catalog %s\n",
1636 catal->name, NULL, NULL);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001637 return(NULL);
1638 }
1639 catal->depth++;
1640
1641 /*
Daniel Veillardcda96922001-08-21 10:56:31 +00001642 * First tries steps 2/ 3/ 4/ if a system ID is provided.
1643 */
1644 if (sysID != NULL) {
1645 xmlCatalogEntryPtr rewrite = NULL;
1646 int lenrewrite = 0, len;
1647 cur = catal;
1648 haveDelegate = 0;
1649 while (cur != NULL) {
1650 switch (cur->type) {
1651 case XML_CATA_SYSTEM:
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001652 if (xmlStrEqual(sysID, cur->name)) {
1653 if (xmlDebugCatalogs)
1654 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard890b5492006-02-23 08:14:00 +00001655 "Found system match %s, using %s\n",
1656 cur->name, cur->URL);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001657 catal->depth--;
Daniel Veillardc853b322001-11-06 15:24:37 +00001658 return(xmlStrdup(cur->URL));
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001659 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001660 break;
1661 case XML_CATA_REWRITE_SYSTEM:
1662 len = xmlStrlen(cur->name);
1663 if ((len > lenrewrite) &&
1664 (!xmlStrncmp(sysID, cur->name, len))) {
1665 lenrewrite = len;
1666 rewrite = cur;
1667 }
1668 break;
1669 case XML_CATA_DELEGATE_SYSTEM:
1670 if (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))
1671 haveDelegate++;
1672 break;
1673 case XML_CATA_NEXT_CATALOG:
1674 haveNext++;
1675 break;
1676 default:
1677 break;
1678 }
1679 cur = cur->next;
1680 }
1681 if (rewrite != NULL) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001682 if (xmlDebugCatalogs)
1683 xmlGenericError(xmlGenericErrorContext,
1684 "Using rewriting rule %s\n", rewrite->name);
Daniel Veillardc853b322001-11-06 15:24:37 +00001685 ret = xmlStrdup(rewrite->URL);
Daniel Veillardcda96922001-08-21 10:56:31 +00001686 if (ret != NULL)
1687 ret = xmlStrcat(ret, &sysID[lenrewrite]);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001688 catal->depth--;
Daniel Veillardcda96922001-08-21 10:56:31 +00001689 return(ret);
1690 }
1691 if (haveDelegate) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001692 const xmlChar *delegates[MAX_DELEGATE];
1693 int nbList = 0, i;
1694
Daniel Veillardcda96922001-08-21 10:56:31 +00001695 /*
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001696 * Assume the entries have been sorted by decreasing substring
Daniel Veillardcda96922001-08-21 10:56:31 +00001697 * matches when the list was produced.
1698 */
1699 cur = catal;
1700 while (cur != NULL) {
1701 if ((cur->type == XML_CATA_DELEGATE_SYSTEM) &&
1702 (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001703 for (i = 0;i < nbList;i++)
Daniel Veillardc853b322001-11-06 15:24:37 +00001704 if (xmlStrEqual(cur->URL, delegates[i]))
Daniel Veillard6990bf32001-08-23 21:17:48 +00001705 break;
1706 if (i < nbList) {
1707 cur = cur->next;
1708 continue;
1709 }
1710 if (nbList < MAX_DELEGATE)
Daniel Veillardc853b322001-11-06 15:24:37 +00001711 delegates[nbList++] = cur->URL;
Daniel Veillard6990bf32001-08-23 21:17:48 +00001712
Daniel Veillardcda96922001-08-21 10:56:31 +00001713 if (cur->children == NULL) {
1714 xmlFetchXMLCatalogFile(cur);
1715 }
1716 if (cur->children != NULL) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001717 if (xmlDebugCatalogs)
1718 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001719 "Trying system delegate %s\n", cur->URL);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001720 ret = xmlCatalogListXMLResolve(
1721 cur->children, NULL, sysID);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001722 if (ret != NULL) {
1723 catal->depth--;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001724 return(ret);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001725 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001726 }
1727 }
1728 cur = cur->next;
1729 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001730 /*
1731 * Apply the cut algorithm explained in 4/
1732 */
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001733 catal->depth--;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001734 return(XML_CATAL_BREAK);
Daniel Veillardcda96922001-08-21 10:56:31 +00001735 }
1736 }
1737 /*
1738 * Then tries 5/ 6/ if a public ID is provided
1739 */
1740 if (pubID != NULL) {
1741 cur = catal;
1742 haveDelegate = 0;
1743 while (cur != NULL) {
1744 switch (cur->type) {
1745 case XML_CATA_PUBLIC:
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001746 if (xmlStrEqual(pubID, cur->name)) {
1747 if (xmlDebugCatalogs)
1748 xmlGenericError(xmlGenericErrorContext,
1749 "Found public match %s\n", cur->name);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001750 catal->depth--;
Daniel Veillardc853b322001-11-06 15:24:37 +00001751 return(xmlStrdup(cur->URL));
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001752 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001753 break;
1754 case XML_CATA_DELEGATE_PUBLIC:
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001755 if (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)) &&
1756 (cur->prefer == XML_CATA_PREFER_PUBLIC))
Daniel Veillardcda96922001-08-21 10:56:31 +00001757 haveDelegate++;
1758 break;
1759 case XML_CATA_NEXT_CATALOG:
1760 if (sysID == NULL)
1761 haveNext++;
1762 break;
1763 default:
1764 break;
1765 }
1766 cur = cur->next;
1767 }
1768 if (haveDelegate) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001769 const xmlChar *delegates[MAX_DELEGATE];
1770 int nbList = 0, i;
1771
Daniel Veillardcda96922001-08-21 10:56:31 +00001772 /*
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001773 * Assume the entries have been sorted by decreasing substring
Daniel Veillardcda96922001-08-21 10:56:31 +00001774 * matches when the list was produced.
1775 */
1776 cur = catal;
1777 while (cur != NULL) {
1778 if ((cur->type == XML_CATA_DELEGATE_PUBLIC) &&
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001779 (cur->prefer == XML_CATA_PREFER_PUBLIC) &&
1780 (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)))) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001781
1782 for (i = 0;i < nbList;i++)
Daniel Veillardc853b322001-11-06 15:24:37 +00001783 if (xmlStrEqual(cur->URL, delegates[i]))
Daniel Veillard6990bf32001-08-23 21:17:48 +00001784 break;
1785 if (i < nbList) {
1786 cur = cur->next;
1787 continue;
1788 }
1789 if (nbList < MAX_DELEGATE)
Daniel Veillardc853b322001-11-06 15:24:37 +00001790 delegates[nbList++] = cur->URL;
Daniel Veillard6990bf32001-08-23 21:17:48 +00001791
Daniel Veillardcda96922001-08-21 10:56:31 +00001792 if (cur->children == NULL) {
1793 xmlFetchXMLCatalogFile(cur);
1794 }
1795 if (cur->children != NULL) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001796 if (xmlDebugCatalogs)
1797 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001798 "Trying public delegate %s\n", cur->URL);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001799 ret = xmlCatalogListXMLResolve(
1800 cur->children, pubID, NULL);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001801 if (ret != NULL) {
1802 catal->depth--;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001803 return(ret);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001804 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001805 }
1806 }
1807 cur = cur->next;
1808 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001809 /*
1810 * Apply the cut algorithm explained in 4/
1811 */
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001812 catal->depth--;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001813 return(XML_CATAL_BREAK);
Daniel Veillardcda96922001-08-21 10:56:31 +00001814 }
1815 }
1816 if (haveNext) {
1817 cur = catal;
1818 while (cur != NULL) {
1819 if (cur->type == XML_CATA_NEXT_CATALOG) {
1820 if (cur->children == NULL) {
1821 xmlFetchXMLCatalogFile(cur);
1822 }
1823 if (cur->children != NULL) {
Daniel Veillard64339542001-08-21 12:57:59 +00001824 ret = xmlCatalogListXMLResolve(cur->children, pubID, sysID);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001825 if (ret != NULL) {
1826 catal->depth--;
Daniel Veillard64339542001-08-21 12:57:59 +00001827 return(ret);
Daniel Veillardbe8d9d32007-06-12 09:14:11 +00001828 } else if (catal->depth > MAX_CATAL_DEPTH) {
1829 return(NULL);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001830 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001831 }
1832 }
1833 cur = cur->next;
1834 }
1835 }
1836
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001837 catal->depth--;
Daniel Veillardcda96922001-08-21 10:56:31 +00001838 return(NULL);
1839}
1840
1841/**
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001842 * xmlCatalogXMLResolveURI:
1843 * @catal: a catalog list
1844 * @URI: the URI
Daniel Veillard06d25242004-02-25 13:01:42 +00001845 * @sysID: the system ID string
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001846 *
1847 * Do a complete resolution lookup of an External Identifier for a
1848 * list of catalog entries.
1849 *
1850 * Implements (or tries to) 7.2.2. URI Resolution
1851 * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1852 *
1853 * Returns the URI of the resource or NULL if not found
1854 */
1855static xmlChar *
1856xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
1857 xmlChar *ret = NULL;
1858 xmlCatalogEntryPtr cur;
1859 int haveDelegate = 0;
1860 int haveNext = 0;
1861 xmlCatalogEntryPtr rewrite = NULL;
1862 int lenrewrite = 0, len;
1863
1864 if (catal == NULL)
1865 return(NULL);
1866
1867 if (URI == NULL)
1868 return(NULL);
1869
Daniel Veillardbe8d9d32007-06-12 09:14:11 +00001870 if (catal->depth > MAX_CATAL_DEPTH) {
1871 xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
1872 "Detected recursion in catalog %s\n",
1873 catal->name, NULL, NULL);
1874 return(NULL);
1875 }
1876
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001877 /*
1878 * First tries steps 2/ 3/ 4/ if a system ID is provided.
1879 */
1880 cur = catal;
1881 haveDelegate = 0;
1882 while (cur != NULL) {
1883 switch (cur->type) {
1884 case XML_CATA_URI:
1885 if (xmlStrEqual(URI, cur->name)) {
1886 if (xmlDebugCatalogs)
1887 xmlGenericError(xmlGenericErrorContext,
1888 "Found URI match %s\n", cur->name);
Daniel Veillardc853b322001-11-06 15:24:37 +00001889 return(xmlStrdup(cur->URL));
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001890 }
1891 break;
1892 case XML_CATA_REWRITE_URI:
1893 len = xmlStrlen(cur->name);
1894 if ((len > lenrewrite) &&
1895 (!xmlStrncmp(URI, cur->name, len))) {
1896 lenrewrite = len;
1897 rewrite = cur;
1898 }
1899 break;
1900 case XML_CATA_DELEGATE_URI:
1901 if (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))
1902 haveDelegate++;
1903 break;
1904 case XML_CATA_NEXT_CATALOG:
1905 haveNext++;
1906 break;
1907 default:
1908 break;
1909 }
1910 cur = cur->next;
1911 }
1912 if (rewrite != NULL) {
1913 if (xmlDebugCatalogs)
1914 xmlGenericError(xmlGenericErrorContext,
1915 "Using rewriting rule %s\n", rewrite->name);
Daniel Veillardc853b322001-11-06 15:24:37 +00001916 ret = xmlStrdup(rewrite->URL);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001917 if (ret != NULL)
1918 ret = xmlStrcat(ret, &URI[lenrewrite]);
1919 return(ret);
1920 }
1921 if (haveDelegate) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001922 const xmlChar *delegates[MAX_DELEGATE];
1923 int nbList = 0, i;
1924
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001925 /*
1926 * Assume the entries have been sorted by decreasing substring
1927 * matches when the list was produced.
1928 */
1929 cur = catal;
1930 while (cur != NULL) {
Daniel Veillard652d8a92003-02-04 19:28:49 +00001931 if (((cur->type == XML_CATA_DELEGATE_SYSTEM) ||
1932 (cur->type == XML_CATA_DELEGATE_URI)) &&
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001933 (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001934 for (i = 0;i < nbList;i++)
Daniel Veillardc853b322001-11-06 15:24:37 +00001935 if (xmlStrEqual(cur->URL, delegates[i]))
Daniel Veillard6990bf32001-08-23 21:17:48 +00001936 break;
1937 if (i < nbList) {
1938 cur = cur->next;
1939 continue;
1940 }
1941 if (nbList < MAX_DELEGATE)
Daniel Veillardc853b322001-11-06 15:24:37 +00001942 delegates[nbList++] = cur->URL;
Daniel Veillard6990bf32001-08-23 21:17:48 +00001943
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001944 if (cur->children == NULL) {
1945 xmlFetchXMLCatalogFile(cur);
1946 }
1947 if (cur->children != NULL) {
1948 if (xmlDebugCatalogs)
1949 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001950 "Trying URI delegate %s\n", cur->URL);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001951 ret = xmlCatalogListXMLResolveURI(
1952 cur->children, URI);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001953 if (ret != NULL)
1954 return(ret);
1955 }
1956 }
1957 cur = cur->next;
1958 }
1959 /*
1960 * Apply the cut algorithm explained in 4/
1961 */
1962 return(XML_CATAL_BREAK);
1963 }
1964 if (haveNext) {
1965 cur = catal;
1966 while (cur != NULL) {
1967 if (cur->type == XML_CATA_NEXT_CATALOG) {
1968 if (cur->children == NULL) {
1969 xmlFetchXMLCatalogFile(cur);
1970 }
1971 if (cur->children != NULL) {
1972 ret = xmlCatalogListXMLResolveURI(cur->children, URI);
1973 if (ret != NULL)
1974 return(ret);
1975 }
1976 }
1977 cur = cur->next;
1978 }
1979 }
1980
1981 return(NULL);
1982}
1983
1984/**
Daniel Veillardcda96922001-08-21 10:56:31 +00001985 * xmlCatalogListXMLResolve:
1986 * @catal: a catalog list
Daniel Veillard06d25242004-02-25 13:01:42 +00001987 * @pubID: the public ID string
1988 * @sysID: the system ID string
Daniel Veillardcda96922001-08-21 10:56:31 +00001989 *
1990 * Do a complete resolution lookup of an External Identifier for a
1991 * list of catalogs
1992 *
1993 * Implements (or tries to) 7.1. External Identifier Resolution
1994 * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1995 *
1996 * Returns the URI of the resource or NULL if not found
1997 */
1998static xmlChar *
1999xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
2000 const xmlChar *sysID) {
2001 xmlChar *ret = NULL;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002002 xmlChar *urnID = NULL;
Daniel Veillardc8155052004-07-16 09:03:08 +00002003 xmlChar *normid;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002004
2005 if (catal == NULL)
2006 return(NULL);
2007 if ((pubID == NULL) && (sysID == NULL))
2008 return(NULL);
2009
Daniel Veillardc8155052004-07-16 09:03:08 +00002010 normid = xmlCatalogNormalizePublic(pubID);
2011 if (normid != NULL)
2012 pubID = (*normid != 0 ? normid : NULL);
2013
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002014 if (!xmlStrncmp(pubID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2015 urnID = xmlCatalogUnWrapURN(pubID);
2016 if (xmlDebugCatalogs) {
2017 if (urnID == NULL)
2018 xmlGenericError(xmlGenericErrorContext,
2019 "Public URN ID %s expanded to NULL\n", pubID);
2020 else
2021 xmlGenericError(xmlGenericErrorContext,
2022 "Public URN ID expanded to %s\n", urnID);
2023 }
2024 ret = xmlCatalogListXMLResolve(catal, urnID, sysID);
2025 if (urnID != NULL)
2026 xmlFree(urnID);
Daniel Veillardc8155052004-07-16 09:03:08 +00002027 if (normid != NULL)
2028 xmlFree(normid);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002029 return(ret);
Daniel Veillardcda96922001-08-21 10:56:31 +00002030 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002031 if (!xmlStrncmp(sysID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2032 urnID = xmlCatalogUnWrapURN(sysID);
2033 if (xmlDebugCatalogs) {
2034 if (urnID == NULL)
2035 xmlGenericError(xmlGenericErrorContext,
2036 "System URN ID %s expanded to NULL\n", sysID);
2037 else
2038 xmlGenericError(xmlGenericErrorContext,
2039 "System URN ID expanded to %s\n", urnID);
2040 }
2041 if (pubID == NULL)
2042 ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
2043 else if (xmlStrEqual(pubID, urnID))
2044 ret = xmlCatalogListXMLResolve(catal, pubID, NULL);
2045 else {
Daniel Veillard770075b2004-02-25 10:44:30 +00002046 ret = xmlCatalogListXMLResolve(catal, pubID, urnID);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002047 }
2048 if (urnID != NULL)
2049 xmlFree(urnID);
Daniel Veillardc8155052004-07-16 09:03:08 +00002050 if (normid != NULL)
2051 xmlFree(normid);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002052 return(ret);
Daniel Veillardcda96922001-08-21 10:56:31 +00002053 }
2054 while (catal != NULL) {
2055 if (catal->type == XML_CATA_CATALOG) {
2056 if (catal->children == NULL) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002057 xmlFetchXMLCatalogFile(catal);
Daniel Veillardcda96922001-08-21 10:56:31 +00002058 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002059 if (catal->children != NULL) {
2060 ret = xmlCatalogXMLResolve(catal->children, pubID, sysID);
Daniel Veillardc8155052004-07-16 09:03:08 +00002061 if (ret != NULL) {
Daniel Veillardbe8d9d32007-06-12 09:14:11 +00002062 break;
2063 } else if ((catal->children != NULL) &&
2064 (catal->children->depth > MAX_CATAL_DEPTH)) {
2065 ret = NULL;
2066 break;
2067 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002068 }
Daniel Veillardcda96922001-08-21 10:56:31 +00002069 }
2070 catal = catal->next;
2071 }
Daniel Veillardbe8d9d32007-06-12 09:14:11 +00002072 if (normid != NULL)
2073 xmlFree(normid);
Daniel Veillardcda96922001-08-21 10:56:31 +00002074 return(ret);
Daniel Veillard344cee72001-08-20 00:08:40 +00002075}
2076
Daniel Veillarddc2cee22001-08-22 16:30:37 +00002077/**
2078 * xmlCatalogListXMLResolveURI:
2079 * @catal: a catalog list
2080 * @URI: the URI
2081 *
2082 * Do a complete resolution lookup of an URI for a list of catalogs
2083 *
2084 * Implements (or tries to) 7.2. URI Resolution
2085 * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
2086 *
2087 * Returns the URI of the resource or NULL if not found
2088 */
2089static xmlChar *
2090xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
2091 xmlChar *ret = NULL;
2092 xmlChar *urnID = NULL;
2093
2094 if (catal == NULL)
2095 return(NULL);
2096 if (URI == NULL)
2097 return(NULL);
2098
2099 if (!xmlStrncmp(URI, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2100 urnID = xmlCatalogUnWrapURN(URI);
2101 if (xmlDebugCatalogs) {
2102 if (urnID == NULL)
2103 xmlGenericError(xmlGenericErrorContext,
2104 "URN ID %s expanded to NULL\n", URI);
2105 else
2106 xmlGenericError(xmlGenericErrorContext,
2107 "URN ID expanded to %s\n", urnID);
2108 }
2109 ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
2110 if (urnID != NULL)
2111 xmlFree(urnID);
2112 return(ret);
2113 }
2114 while (catal != NULL) {
2115 if (catal->type == XML_CATA_CATALOG) {
2116 if (catal->children == NULL) {
2117 xmlFetchXMLCatalogFile(catal);
2118 }
2119 if (catal->children != NULL) {
2120 ret = xmlCatalogXMLResolveURI(catal->children, URI);
2121 if (ret != NULL)
2122 return(ret);
2123 }
2124 }
2125 catal = catal->next;
2126 }
2127 return(ret);
2128}
2129
Daniel Veillard344cee72001-08-20 00:08:40 +00002130/************************************************************************
2131 * *
2132 * The SGML Catalog parser *
Daniel Veillarda7374592001-05-10 14:17:55 +00002133 * *
2134 ************************************************************************/
2135
2136
2137#define RAW *cur
2138#define NEXT cur++;
2139#define SKIP(x) cur += x;
2140
William M. Brack272693c2003-11-14 16:20:34 +00002141#define SKIP_BLANKS while (IS_BLANK_CH(*cur)) NEXT;
Daniel Veillarda7374592001-05-10 14:17:55 +00002142
Daniel Veillard75b96822001-10-11 18:59:45 +00002143/**
2144 * xmlParseSGMLCatalogComment:
2145 * @cur: the current character
2146 *
2147 * Skip a comment in an SGML catalog
2148 *
2149 * Returns new current character
2150 */
Daniel Veillarda7374592001-05-10 14:17:55 +00002151static const xmlChar *
Daniel Veillardcda96922001-08-21 10:56:31 +00002152xmlParseSGMLCatalogComment(const xmlChar *cur) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002153 if ((cur[0] != '-') || (cur[1] != '-'))
2154 return(cur);
2155 SKIP(2);
2156 while ((cur[0] != 0) && ((cur[0] != '-') || ((cur[1] != '-'))))
2157 NEXT;
2158 if (cur[0] == 0) {
2159 return(NULL);
2160 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002161 return(cur + 2);
Daniel Veillarda7374592001-05-10 14:17:55 +00002162}
2163
Daniel Veillard75b96822001-10-11 18:59:45 +00002164/**
2165 * xmlParseSGMLCatalogPubid:
2166 * @cur: the current character
2167 * @id: the return location
2168 *
2169 * Parse an SGML catalog ID
2170 *
2171 * Returns new current character and store the value in @id
2172 */
Daniel Veillarda7374592001-05-10 14:17:55 +00002173static const xmlChar *
Daniel Veillardcda96922001-08-21 10:56:31 +00002174xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) {
Daniel Veillard69d2c172003-10-09 11:46:07 +00002175 xmlChar *buf = NULL, *tmp;
Daniel Veillarda7374592001-05-10 14:17:55 +00002176 int len = 0;
2177 int size = 50;
2178 xmlChar stop;
2179 int count = 0;
2180
2181 *id = NULL;
2182
2183 if (RAW == '"') {
2184 NEXT;
2185 stop = '"';
2186 } else if (RAW == '\'') {
2187 NEXT;
2188 stop = '\'';
2189 } else {
2190 stop = ' ';
2191 }
Daniel Veillard3c908dc2003-04-19 00:07:51 +00002192 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
Daniel Veillarda7374592001-05-10 14:17:55 +00002193 if (buf == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +00002194 xmlCatalogErrMemory("allocating public ID");
Daniel Veillarda7374592001-05-10 14:17:55 +00002195 return(NULL);
2196 }
William M. Brack76e95df2003-10-18 16:20:14 +00002197 while (IS_PUBIDCHAR_CH(*cur) || (*cur == '?')) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002198 if ((*cur == stop) && (stop != ' '))
2199 break;
William M. Brack76e95df2003-10-18 16:20:14 +00002200 if ((stop == ' ') && (IS_BLANK_CH(*cur)))
Daniel Veillarda7374592001-05-10 14:17:55 +00002201 break;
2202 if (len + 1 >= size) {
2203 size *= 2;
Daniel Veillard69d2c172003-10-09 11:46:07 +00002204 tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
2205 if (tmp == NULL) {
2206 xmlCatalogErrMemory("allocating public ID");
2207 xmlFree(buf);
Daniel Veillarda7374592001-05-10 14:17:55 +00002208 return(NULL);
2209 }
Daniel Veillard69d2c172003-10-09 11:46:07 +00002210 buf = tmp;
Daniel Veillarda7374592001-05-10 14:17:55 +00002211 }
2212 buf[len++] = *cur;
2213 count++;
2214 NEXT;
2215 }
2216 buf[len] = 0;
2217 if (stop == ' ') {
William M. Brack76e95df2003-10-18 16:20:14 +00002218 if (!IS_BLANK_CH(*cur)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002219 xmlFree(buf);
2220 return(NULL);
2221 }
2222 } else {
2223 if (*cur != stop) {
2224 xmlFree(buf);
2225 return(NULL);
2226 }
2227 NEXT;
2228 }
2229 *id = buf;
2230 return(cur);
2231}
2232
Daniel Veillard75b96822001-10-11 18:59:45 +00002233/**
2234 * xmlParseSGMLCatalogName:
2235 * @cur: the current character
2236 * @name: the return location
2237 *
2238 * Parse an SGML catalog name
2239 *
2240 * Returns new current character and store the value in @name
2241 */
Daniel Veillarda7374592001-05-10 14:17:55 +00002242static const xmlChar *
Daniel Veillardcda96922001-08-21 10:56:31 +00002243xmlParseSGMLCatalogName(const xmlChar *cur, xmlChar **name) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002244 xmlChar buf[XML_MAX_NAMELEN + 5];
2245 int len = 0;
2246 int c;
2247
2248 *name = NULL;
2249
2250 /*
2251 * Handler for more complex cases
2252 */
2253 c = *cur;
2254 if ((!IS_LETTER(c) && (c != '_') && (c != ':'))) {
2255 return(NULL);
2256 }
2257
2258 while (((IS_LETTER(c)) || (IS_DIGIT(c)) ||
2259 (c == '.') || (c == '-') ||
2260 (c == '_') || (c == ':'))) {
2261 buf[len++] = c;
2262 cur++;
2263 c = *cur;
2264 if (len >= XML_MAX_NAMELEN)
2265 return(NULL);
2266 }
2267 *name = xmlStrndup(buf, len);
2268 return(cur);
2269}
2270
Daniel Veillard75b96822001-10-11 18:59:45 +00002271/**
2272 * xmlGetSGMLCatalogEntryType:
2273 * @name: the entry name
2274 *
2275 * Get the Catalog entry type for a given SGML Catalog name
2276 *
2277 * Returns Catalog entry type
2278 */
Daniel Veillard344cee72001-08-20 00:08:40 +00002279static xmlCatalogEntryType
Daniel Veillardcda96922001-08-21 10:56:31 +00002280xmlGetSGMLCatalogEntryType(const xmlChar *name) {
Daniel Veillard344cee72001-08-20 00:08:40 +00002281 xmlCatalogEntryType type = XML_CATA_NONE;
2282 if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
2283 type = SGML_CATA_SYSTEM;
2284 else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
2285 type = SGML_CATA_PUBLIC;
2286 else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
2287 type = SGML_CATA_DELEGATE;
2288 else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
2289 type = SGML_CATA_ENTITY;
2290 else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
2291 type = SGML_CATA_DOCTYPE;
2292 else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
2293 type = SGML_CATA_LINKTYPE;
2294 else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
2295 type = SGML_CATA_NOTATION;
2296 else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
2297 type = SGML_CATA_SGMLDECL;
2298 else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
2299 type = SGML_CATA_DOCUMENT;
2300 else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
2301 type = SGML_CATA_CATALOG;
2302 else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
2303 type = SGML_CATA_BASE;
Daniel Veillard344cee72001-08-20 00:08:40 +00002304 return(type);
2305}
2306
Daniel Veillard75b96822001-10-11 18:59:45 +00002307/**
2308 * xmlParseSGMLCatalog:
2309 * @catal: the SGML Catalog
2310 * @value: the content of the SGML Catalog serialization
2311 * @file: the filepath for the catalog
2312 * @super: should this be handled as a Super Catalog in which case
2313 * parsing is not recursive
2314 *
2315 * Parse an SGML catalog content and fill up the @catal hash table with
2316 * the new entries found.
2317 *
2318 * Returns 0 in case of success, -1 in case of error.
2319 */
Daniel Veillarda7374592001-05-10 14:17:55 +00002320static int
Daniel Veillard75b96822001-10-11 18:59:45 +00002321xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value,
2322 const char *file, int super) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002323 const xmlChar *cur = value;
2324 xmlChar *base = NULL;
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002325 int res;
Daniel Veillarda7374592001-05-10 14:17:55 +00002326
2327 if ((cur == NULL) || (file == NULL))
2328 return(-1);
2329 base = xmlStrdup((const xmlChar *) file);
2330
Daniel Veillardbc2ddbe2001-08-23 10:24:27 +00002331 while ((cur != NULL) && (cur[0] != 0)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002332 SKIP_BLANKS;
Daniel Veillardbc2ddbe2001-08-23 10:24:27 +00002333 if (cur[0] == 0)
2334 break;
Daniel Veillarda7374592001-05-10 14:17:55 +00002335 if ((cur[0] == '-') && (cur[1] == '-')) {
Daniel Veillardcda96922001-08-21 10:56:31 +00002336 cur = xmlParseSGMLCatalogComment(cur);
Daniel Veillarda7374592001-05-10 14:17:55 +00002337 if (cur == NULL) {
2338 /* error */
2339 break;
2340 }
2341 } else {
2342 xmlChar *sysid = NULL;
2343 xmlChar *name = NULL;
2344 xmlCatalogEntryType type = XML_CATA_NONE;
2345
Daniel Veillardcda96922001-08-21 10:56:31 +00002346 cur = xmlParseSGMLCatalogName(cur, &name);
Daniel Veillarda7374592001-05-10 14:17:55 +00002347 if (name == NULL) {
2348 /* error */
2349 break;
2350 }
William M. Brack76e95df2003-10-18 16:20:14 +00002351 if (!IS_BLANK_CH(*cur)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002352 /* error */
2353 break;
2354 }
2355 SKIP_BLANKS;
2356 if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002357 type = SGML_CATA_SYSTEM;
Daniel Veillarda7374592001-05-10 14:17:55 +00002358 else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002359 type = SGML_CATA_PUBLIC;
Daniel Veillarda7374592001-05-10 14:17:55 +00002360 else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002361 type = SGML_CATA_DELEGATE;
Daniel Veillarda7374592001-05-10 14:17:55 +00002362 else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002363 type = SGML_CATA_ENTITY;
Daniel Veillarda7374592001-05-10 14:17:55 +00002364 else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002365 type = SGML_CATA_DOCTYPE;
Daniel Veillarda7374592001-05-10 14:17:55 +00002366 else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002367 type = SGML_CATA_LINKTYPE;
Daniel Veillarda7374592001-05-10 14:17:55 +00002368 else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002369 type = SGML_CATA_NOTATION;
Daniel Veillarda7374592001-05-10 14:17:55 +00002370 else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002371 type = SGML_CATA_SGMLDECL;
Daniel Veillarda7374592001-05-10 14:17:55 +00002372 else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002373 type = SGML_CATA_DOCUMENT;
Daniel Veillarda7374592001-05-10 14:17:55 +00002374 else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002375 type = SGML_CATA_CATALOG;
Daniel Veillarda7374592001-05-10 14:17:55 +00002376 else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002377 type = SGML_CATA_BASE;
Daniel Veillarda7374592001-05-10 14:17:55 +00002378 else if (xmlStrEqual(name, (const xmlChar *) "OVERRIDE")) {
2379 xmlFree(name);
Daniel Veillardcda96922001-08-21 10:56:31 +00002380 cur = xmlParseSGMLCatalogName(cur, &name);
Daniel Veillarda7374592001-05-10 14:17:55 +00002381 if (name == NULL) {
2382 /* error */
2383 break;
2384 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002385 xmlFree(name);
Daniel Veillarda7374592001-05-10 14:17:55 +00002386 continue;
2387 }
2388 xmlFree(name);
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002389 name = NULL;
Daniel Veillarda7374592001-05-10 14:17:55 +00002390
2391 switch(type) {
Daniel Veillard344cee72001-08-20 00:08:40 +00002392 case SGML_CATA_ENTITY:
Daniel Veillarda7374592001-05-10 14:17:55 +00002393 if (*cur == '%')
Daniel Veillard344cee72001-08-20 00:08:40 +00002394 type = SGML_CATA_PENTITY;
2395 case SGML_CATA_PENTITY:
2396 case SGML_CATA_DOCTYPE:
2397 case SGML_CATA_LINKTYPE:
2398 case SGML_CATA_NOTATION:
Daniel Veillardcda96922001-08-21 10:56:31 +00002399 cur = xmlParseSGMLCatalogName(cur, &name);
Daniel Veillarda7374592001-05-10 14:17:55 +00002400 if (cur == NULL) {
2401 /* error */
2402 break;
2403 }
William M. Brack76e95df2003-10-18 16:20:14 +00002404 if (!IS_BLANK_CH(*cur)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002405 /* error */
2406 break;
2407 }
2408 SKIP_BLANKS;
Daniel Veillardcda96922001-08-21 10:56:31 +00002409 cur = xmlParseSGMLCatalogPubid(cur, &sysid);
Daniel Veillarda7374592001-05-10 14:17:55 +00002410 if (cur == NULL) {
2411 /* error */
2412 break;
2413 }
2414 break;
Daniel Veillard344cee72001-08-20 00:08:40 +00002415 case SGML_CATA_PUBLIC:
2416 case SGML_CATA_SYSTEM:
2417 case SGML_CATA_DELEGATE:
Daniel Veillardcda96922001-08-21 10:56:31 +00002418 cur = xmlParseSGMLCatalogPubid(cur, &name);
Daniel Veillarda7374592001-05-10 14:17:55 +00002419 if (cur == NULL) {
2420 /* error */
2421 break;
2422 }
Daniel Veillardc8155052004-07-16 09:03:08 +00002423 if (type != SGML_CATA_SYSTEM) {
2424 xmlChar *normid;
2425
2426 normid = xmlCatalogNormalizePublic(name);
2427 if (normid != NULL) {
2428 if (name != NULL)
2429 xmlFree(name);
2430 if (*normid != 0)
2431 name = normid;
2432 else {
2433 xmlFree(normid);
2434 name = NULL;
2435 }
2436 }
2437 }
William M. Brack76e95df2003-10-18 16:20:14 +00002438 if (!IS_BLANK_CH(*cur)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002439 /* error */
2440 break;
2441 }
2442 SKIP_BLANKS;
Daniel Veillardcda96922001-08-21 10:56:31 +00002443 cur = xmlParseSGMLCatalogPubid(cur, &sysid);
Daniel Veillarda7374592001-05-10 14:17:55 +00002444 if (cur == NULL) {
2445 /* error */
2446 break;
2447 }
2448 break;
Daniel Veillard344cee72001-08-20 00:08:40 +00002449 case SGML_CATA_BASE:
2450 case SGML_CATA_CATALOG:
2451 case SGML_CATA_DOCUMENT:
2452 case SGML_CATA_SGMLDECL:
Daniel Veillardcda96922001-08-21 10:56:31 +00002453 cur = xmlParseSGMLCatalogPubid(cur, &sysid);
Daniel Veillarda7374592001-05-10 14:17:55 +00002454 if (cur == NULL) {
2455 /* error */
2456 break;
2457 }
2458 break;
2459 default:
2460 break;
2461 }
2462 if (cur == NULL) {
2463 if (name != NULL)
2464 xmlFree(name);
2465 if (sysid != NULL)
2466 xmlFree(sysid);
2467 break;
Daniel Veillard344cee72001-08-20 00:08:40 +00002468 } else if (type == SGML_CATA_BASE) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002469 if (base != NULL)
2470 xmlFree(base);
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002471 base = xmlStrdup(sysid);
Daniel Veillard344cee72001-08-20 00:08:40 +00002472 } else if ((type == SGML_CATA_PUBLIC) ||
2473 (type == SGML_CATA_SYSTEM)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002474 xmlChar *filename;
2475
2476 filename = xmlBuildURI(sysid, base);
2477 if (filename != NULL) {
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002478 xmlCatalogEntryPtr entry;
Daniel Veillarda7374592001-05-10 14:17:55 +00002479
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002480 entry = xmlNewCatalogEntry(type, name, filename,
William M. Brackb7b54de2004-10-06 16:38:01 +00002481 NULL, XML_CATA_PREFER_NONE, NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00002482 res = xmlHashAddEntry(catal->sgml, name, entry);
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002483 if (res < 0) {
2484 xmlFreeCatalogEntry(entry);
2485 }
2486 xmlFree(filename);
Daniel Veillarda7374592001-05-10 14:17:55 +00002487 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002488
Daniel Veillard344cee72001-08-20 00:08:40 +00002489 } else if (type == SGML_CATA_CATALOG) {
Daniel Veillard82d75332001-10-08 15:01:59 +00002490 if (super) {
2491 xmlCatalogEntryPtr entry;
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002492
Daniel Veillardc853b322001-11-06 15:24:37 +00002493 entry = xmlNewCatalogEntry(type, sysid, NULL, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00002494 XML_CATA_PREFER_NONE, NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00002495 res = xmlHashAddEntry(catal->sgml, sysid, entry);
Daniel Veillard82d75332001-10-08 15:01:59 +00002496 if (res < 0) {
2497 xmlFreeCatalogEntry(entry);
2498 }
2499 } else {
2500 xmlChar *filename;
2501
2502 filename = xmlBuildURI(sysid, base);
2503 if (filename != NULL) {
Daniel Veillard75b96822001-10-11 18:59:45 +00002504 xmlExpandCatalog(catal, (const char *)filename);
Daniel Veillard82d75332001-10-08 15:01:59 +00002505 xmlFree(filename);
2506 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002507 }
Daniel Veillarda7374592001-05-10 14:17:55 +00002508 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002509 /*
2510 * drop anything else we won't handle it
2511 */
2512 if (name != NULL)
2513 xmlFree(name);
2514 if (sysid != NULL)
2515 xmlFree(sysid);
Daniel Veillarda7374592001-05-10 14:17:55 +00002516 }
2517 }
2518 if (base != NULL)
2519 xmlFree(base);
2520 if (cur == NULL)
2521 return(-1);
2522 return(0);
2523}
2524
Daniel Veillard75b96822001-10-11 18:59:45 +00002525/************************************************************************
2526 * *
2527 * SGML Catalog handling *
2528 * *
2529 ************************************************************************/
2530
Daniel Veillardcda96922001-08-21 10:56:31 +00002531/**
2532 * xmlCatalogGetSGMLPublic:
2533 * @catal: an SGML catalog hash
Daniel Veillard06d25242004-02-25 13:01:42 +00002534 * @pubID: the public ID string
Daniel Veillardcda96922001-08-21 10:56:31 +00002535 *
Daniel Veillard06d25242004-02-25 13:01:42 +00002536 * Try to lookup the catalog local reference associated to a public ID
Daniel Veillardcda96922001-08-21 10:56:31 +00002537 *
Daniel Veillard06d25242004-02-25 13:01:42 +00002538 * Returns the local resource if found or NULL otherwise.
Daniel Veillardcda96922001-08-21 10:56:31 +00002539 */
2540static const xmlChar *
2541xmlCatalogGetSGMLPublic(xmlHashTablePtr catal, const xmlChar *pubID) {
2542 xmlCatalogEntryPtr entry;
Daniel Veillardc8155052004-07-16 09:03:08 +00002543 xmlChar *normid;
Daniel Veillardcda96922001-08-21 10:56:31 +00002544
2545 if (catal == NULL)
2546 return(NULL);
2547
Daniel Veillardc8155052004-07-16 09:03:08 +00002548 normid = xmlCatalogNormalizePublic(pubID);
2549 if (normid != NULL)
2550 pubID = (*normid != 0 ? normid : NULL);
2551
Daniel Veillardcda96922001-08-21 10:56:31 +00002552 entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, pubID);
Daniel Veillardc8155052004-07-16 09:03:08 +00002553 if (entry == NULL) {
2554 if (normid != NULL)
2555 xmlFree(normid);
Daniel Veillardcda96922001-08-21 10:56:31 +00002556 return(NULL);
Daniel Veillardc8155052004-07-16 09:03:08 +00002557 }
2558 if (entry->type == SGML_CATA_PUBLIC) {
2559 if (normid != NULL)
2560 xmlFree(normid);
Daniel Veillardc853b322001-11-06 15:24:37 +00002561 return(entry->URL);
Daniel Veillardc8155052004-07-16 09:03:08 +00002562 }
2563 if (normid != NULL)
2564 xmlFree(normid);
Daniel Veillardcda96922001-08-21 10:56:31 +00002565 return(NULL);
2566}
2567
2568/**
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002569 * xmlCatalogGetSGMLSystem:
2570 * @catal: an SGML catalog hash
Daniel Veillard06d25242004-02-25 13:01:42 +00002571 * @sysID: the system ID string
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002572 *
2573 * Try to lookup the catalog local reference for a system ID
2574 *
Daniel Veillard770075b2004-02-25 10:44:30 +00002575 * Returns the local resource if found or NULL otherwise.
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002576 */
2577static const xmlChar *
2578xmlCatalogGetSGMLSystem(xmlHashTablePtr catal, const xmlChar *sysID) {
2579 xmlCatalogEntryPtr entry;
2580
2581 if (catal == NULL)
2582 return(NULL);
2583
2584 entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, sysID);
2585 if (entry == NULL)
2586 return(NULL);
2587 if (entry->type == SGML_CATA_SYSTEM)
Daniel Veillardc853b322001-11-06 15:24:37 +00002588 return(entry->URL);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002589 return(NULL);
2590}
2591
2592/**
Daniel Veillardcda96922001-08-21 10:56:31 +00002593 * xmlCatalogSGMLResolve:
Daniel Veillard75b96822001-10-11 18:59:45 +00002594 * @catal: the SGML catalog
Daniel Veillard06d25242004-02-25 13:01:42 +00002595 * @pubID: the public ID string
2596 * @sysID: the system ID string
Daniel Veillardcda96922001-08-21 10:56:31 +00002597 *
2598 * Do a complete resolution lookup of an External Identifier
2599 *
2600 * Returns the URI of the resource or NULL if not found
2601 */
2602static const xmlChar *
Daniel Veillard75b96822001-10-11 18:59:45 +00002603xmlCatalogSGMLResolve(xmlCatalogPtr catal, const xmlChar *pubID,
2604 const xmlChar *sysID) {
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00002605 const xmlChar *ret = NULL;
2606
Daniel Veillard75b96822001-10-11 18:59:45 +00002607 if (catal->sgml == NULL)
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00002608 return(NULL);
2609
2610 if (pubID != NULL)
Daniel Veillard75b96822001-10-11 18:59:45 +00002611 ret = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00002612 if (ret != NULL)
2613 return(ret);
2614 if (sysID != NULL)
Daniel Veillard75b96822001-10-11 18:59:45 +00002615 ret = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
Daniel Veillard63806b52008-06-10 14:56:11 +00002616 if (ret != NULL)
2617 return(ret);
Daniel Veillardcda96922001-08-21 10:56:31 +00002618 return(NULL);
2619}
2620
Daniel Veillarda7374592001-05-10 14:17:55 +00002621/************************************************************************
2622 * *
Daniel Veillard75b96822001-10-11 18:59:45 +00002623 * Specific Public interfaces *
2624 * *
2625 ************************************************************************/
2626
2627/**
2628 * xmlLoadSGMLSuperCatalog:
2629 * @filename: a file path
2630 *
2631 * Load an SGML super catalog. It won't expand CATALOG or DELEGATE
2632 * references. This is only needed for manipulating SGML Super Catalogs
2633 * like adding and removing CATALOG or DELEGATE entries.
2634 *
2635 * Returns the catalog parsed or NULL in case of error
2636 */
2637xmlCatalogPtr
2638xmlLoadSGMLSuperCatalog(const char *filename)
2639{
2640 xmlChar *content;
2641 xmlCatalogPtr catal;
2642 int ret;
2643
2644 content = xmlLoadFileContent(filename);
2645 if (content == NULL)
2646 return(NULL);
2647
Daniel Veillardcd21dc72001-11-04 20:03:38 +00002648 catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
Daniel Veillard75b96822001-10-11 18:59:45 +00002649 if (catal == NULL) {
2650 xmlFree(content);
2651 return(NULL);
2652 }
2653
2654 ret = xmlParseSGMLCatalog(catal, content, filename, 1);
2655 xmlFree(content);
2656 if (ret < 0) {
2657 xmlFreeCatalog(catal);
2658 return(NULL);
2659 }
2660 return (catal);
2661}
2662
2663/**
2664 * xmlLoadACatalog:
2665 * @filename: a file path
2666 *
2667 * Load the catalog and build the associated data structures.
2668 * This can be either an XML Catalog or an SGML Catalog
2669 * It will recurse in SGML CATALOG entries. On the other hand XML
2670 * Catalogs are not handled recursively.
2671 *
2672 * Returns the catalog parsed or NULL in case of error
2673 */
2674xmlCatalogPtr
2675xmlLoadACatalog(const char *filename)
2676{
2677 xmlChar *content;
2678 xmlChar *first;
2679 xmlCatalogPtr catal;
2680 int ret;
2681
2682 content = xmlLoadFileContent(filename);
2683 if (content == NULL)
2684 return(NULL);
2685
2686
2687 first = content;
2688
2689 while ((*first != 0) && (*first != '-') && (*first != '<') &&
2690 (!(((*first >= 'A') && (*first <= 'Z')) ||
2691 ((*first >= 'a') && (*first <= 'z')))))
2692 first++;
2693
2694 if (*first != '<') {
Daniel Veillardcd21dc72001-11-04 20:03:38 +00002695 catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
Daniel Veillard75b96822001-10-11 18:59:45 +00002696 if (catal == NULL) {
2697 xmlFree(content);
2698 return(NULL);
2699 }
2700 ret = xmlParseSGMLCatalog(catal, content, filename, 0);
2701 if (ret < 0) {
2702 xmlFreeCatalog(catal);
2703 xmlFree(content);
2704 return(NULL);
2705 }
2706 } else {
Daniel Veillardcd21dc72001-11-04 20:03:38 +00002707 catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
Daniel Veillard75b96822001-10-11 18:59:45 +00002708 if (catal == NULL) {
2709 xmlFree(content);
2710 return(NULL);
2711 }
Daniel Veillardc853b322001-11-06 15:24:37 +00002712 catal->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00002713 NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00002714 }
2715 xmlFree(content);
2716 return (catal);
2717}
2718
2719/**
2720 * xmlExpandCatalog:
2721 * @catal: a catalog
2722 * @filename: a file path
2723 *
2724 * Load the catalog and expand the existing catal structure.
2725 * This can be either an XML Catalog or an SGML Catalog
2726 *
2727 * Returns 0 in case of success, -1 in case of error
2728 */
Daniel Veillard85c11fa2001-10-16 21:03:08 +00002729static int
Daniel Veillard75b96822001-10-11 18:59:45 +00002730xmlExpandCatalog(xmlCatalogPtr catal, const char *filename)
2731{
Daniel Veillard75b96822001-10-11 18:59:45 +00002732 int ret;
2733
2734 if ((catal == NULL) || (filename == NULL))
2735 return(-1);
2736
Daniel Veillard75b96822001-10-11 18:59:45 +00002737
2738 if (catal->type == XML_SGML_CATALOG_TYPE) {
Daniel Veillard85c11fa2001-10-16 21:03:08 +00002739 xmlChar *content;
2740
2741 content = xmlLoadFileContent(filename);
2742 if (content == NULL)
2743 return(-1);
2744
Daniel Veillard75b96822001-10-11 18:59:45 +00002745 ret = xmlParseSGMLCatalog(catal, content, filename, 0);
2746 if (ret < 0) {
2747 xmlFree(content);
2748 return(-1);
2749 }
Daniel Veillard85c11fa2001-10-16 21:03:08 +00002750 xmlFree(content);
Daniel Veillard75b96822001-10-11 18:59:45 +00002751 } else {
2752 xmlCatalogEntryPtr tmp, cur;
Daniel Veillardc853b322001-11-06 15:24:37 +00002753 tmp = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00002754 NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00002755
Daniel Veillard75b96822001-10-11 18:59:45 +00002756 cur = catal->xml;
2757 if (cur == NULL) {
2758 catal->xml = tmp;
2759 } else {
2760 while (cur->next != NULL) cur = cur->next;
2761 cur->next = tmp;
2762 }
Daniel Veillard75b96822001-10-11 18:59:45 +00002763 }
Daniel Veillard75b96822001-10-11 18:59:45 +00002764 return (0);
2765}
2766
2767/**
2768 * xmlACatalogResolveSystem:
2769 * @catal: a Catalog
Daniel Veillard06d25242004-02-25 13:01:42 +00002770 * @sysID: the system ID string
Daniel Veillard75b96822001-10-11 18:59:45 +00002771 *
2772 * Try to lookup the catalog resource for a system ID
2773 *
Daniel Veillard06d25242004-02-25 13:01:42 +00002774 * Returns the resource if found or NULL otherwise, the value returned
Daniel Veillard75b96822001-10-11 18:59:45 +00002775 * must be freed by the caller.
2776 */
2777xmlChar *
2778xmlACatalogResolveSystem(xmlCatalogPtr catal, const xmlChar *sysID) {
2779 xmlChar *ret = NULL;
2780
2781 if ((sysID == NULL) || (catal == NULL))
2782 return(NULL);
2783
2784 if (xmlDebugCatalogs)
2785 xmlGenericError(xmlGenericErrorContext,
2786 "Resolve sysID %s\n", sysID);
2787
2788 if (catal->type == XML_XML_CATALOG_TYPE) {
2789 ret = xmlCatalogListXMLResolve(catal->xml, NULL, sysID);
2790 if (ret == XML_CATAL_BREAK)
2791 ret = NULL;
2792 } else {
2793 const xmlChar *sgml;
2794
2795 sgml = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
2796 if (sgml != NULL)
2797 ret = xmlStrdup(sgml);
2798 }
2799 return(ret);
2800}
2801
2802/**
2803 * xmlACatalogResolvePublic:
2804 * @catal: a Catalog
Daniel Veillard5aad8322002-12-11 15:59:44 +00002805 * @pubID: the public ID string
Daniel Veillard75b96822001-10-11 18:59:45 +00002806 *
Daniel Veillard06d25242004-02-25 13:01:42 +00002807 * Try to lookup the catalog local reference associated to a public ID in that catalog
Daniel Veillard75b96822001-10-11 18:59:45 +00002808 *
Daniel Veillard06d25242004-02-25 13:01:42 +00002809 * Returns the local resource if found or NULL otherwise, the value returned
Daniel Veillard75b96822001-10-11 18:59:45 +00002810 * must be freed by the caller.
2811 */
2812xmlChar *
2813xmlACatalogResolvePublic(xmlCatalogPtr catal, const xmlChar *pubID) {
2814 xmlChar *ret = NULL;
2815
2816 if ((pubID == NULL) || (catal == NULL))
2817 return(NULL);
2818
2819 if (xmlDebugCatalogs)
2820 xmlGenericError(xmlGenericErrorContext,
2821 "Resolve pubID %s\n", pubID);
2822
2823 if (catal->type == XML_XML_CATALOG_TYPE) {
2824 ret = xmlCatalogListXMLResolve(catal->xml, pubID, NULL);
2825 if (ret == XML_CATAL_BREAK)
2826 ret = NULL;
2827 } else {
2828 const xmlChar *sgml;
2829
2830 sgml = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
2831 if (sgml != NULL)
2832 ret = xmlStrdup(sgml);
2833 }
2834 return(ret);
2835}
2836
2837/**
2838 * xmlACatalogResolve:
2839 * @catal: a Catalog
Daniel Veillard5aad8322002-12-11 15:59:44 +00002840 * @pubID: the public ID string
2841 * @sysID: the system ID string
Daniel Veillard75b96822001-10-11 18:59:45 +00002842 *
2843 * Do a complete resolution lookup of an External Identifier
2844 *
2845 * Returns the URI of the resource or NULL if not found, it must be freed
2846 * by the caller.
2847 */
2848xmlChar *
2849xmlACatalogResolve(xmlCatalogPtr catal, const xmlChar * pubID,
2850 const xmlChar * sysID)
2851{
2852 xmlChar *ret = NULL;
2853
2854 if (((pubID == NULL) && (sysID == NULL)) || (catal == NULL))
2855 return (NULL);
2856
2857 if (xmlDebugCatalogs) {
Daniel Veillard770075b2004-02-25 10:44:30 +00002858 if ((pubID != NULL) && (sysID != NULL)) {
2859 xmlGenericError(xmlGenericErrorContext,
2860 "Resolve: pubID %s sysID %s\n", pubID, sysID);
2861 } else if (pubID != NULL) {
2862 xmlGenericError(xmlGenericErrorContext,
2863 "Resolve: pubID %s\n", pubID);
2864 } else {
2865 xmlGenericError(xmlGenericErrorContext,
2866 "Resolve: sysID %s\n", sysID);
2867 }
Daniel Veillard75b96822001-10-11 18:59:45 +00002868 }
2869
2870 if (catal->type == XML_XML_CATALOG_TYPE) {
2871 ret = xmlCatalogListXMLResolve(catal->xml, pubID, sysID);
2872 if (ret == XML_CATAL_BREAK)
2873 ret = NULL;
2874 } else {
2875 const xmlChar *sgml;
2876
2877 sgml = xmlCatalogSGMLResolve(catal, pubID, sysID);
2878 if (sgml != NULL)
2879 ret = xmlStrdup(sgml);
2880 }
2881 return (ret);
2882}
2883
2884/**
2885 * xmlACatalogResolveURI:
2886 * @catal: a Catalog
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002887 * @URI: the URI
Daniel Veillard75b96822001-10-11 18:59:45 +00002888 *
2889 * Do a complete resolution lookup of an URI
2890 *
2891 * Returns the URI of the resource or NULL if not found, it must be freed
2892 * by the caller.
2893 */
2894xmlChar *
2895xmlACatalogResolveURI(xmlCatalogPtr catal, const xmlChar *URI) {
2896 xmlChar *ret = NULL;
2897
2898 if ((URI == NULL) || (catal == NULL))
2899 return(NULL);
2900
Daniel Veillardb44025c2001-10-11 22:55:55 +00002901 if (xmlDebugCatalogs)
Daniel Veillard75b96822001-10-11 18:59:45 +00002902 xmlGenericError(xmlGenericErrorContext,
2903 "Resolve URI %s\n", URI);
2904
2905 if (catal->type == XML_XML_CATALOG_TYPE) {
2906 ret = xmlCatalogListXMLResolveURI(catal->xml, URI);
2907 if (ret == XML_CATAL_BREAK)
2908 ret = NULL;
2909 } else {
2910 const xmlChar *sgml;
2911
2912 sgml = xmlCatalogSGMLResolve(catal, NULL, URI);
2913 if (sgml != NULL)
Daniel Veillard63806b52008-06-10 14:56:11 +00002914 ret = xmlStrdup(sgml);
Daniel Veillard75b96822001-10-11 18:59:45 +00002915 }
2916 return(ret);
2917}
2918
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002919#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard75b96822001-10-11 18:59:45 +00002920/**
2921 * xmlACatalogDump:
2922 * @catal: a Catalog
2923 * @out: the file.
2924 *
Daniel Veillarda8dc2882004-03-29 12:21:26 +00002925 * Dump the given catalog to the given file.
Daniel Veillard75b96822001-10-11 18:59:45 +00002926 */
2927void
2928xmlACatalogDump(xmlCatalogPtr catal, FILE *out) {
Daniel Veillardcd21dc72001-11-04 20:03:38 +00002929 if ((out == NULL) || (catal == NULL))
Daniel Veillard75b96822001-10-11 18:59:45 +00002930 return;
2931
2932 if (catal->type == XML_XML_CATALOG_TYPE) {
2933 xmlDumpXMLCatalog(out, catal->xml);
2934 } else {
2935 xmlHashScan(catal->sgml,
2936 (xmlHashScanner) xmlCatalogDumpEntry, out);
2937 }
2938}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002939#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard75b96822001-10-11 18:59:45 +00002940
2941/**
2942 * xmlACatalogAdd:
2943 * @catal: a Catalog
2944 * @type: the type of record to add to the catalog
2945 * @orig: the system, public or prefix to match
2946 * @replace: the replacement value for the match
2947 *
2948 * Add an entry in the catalog, it may overwrite existing but
2949 * different entries.
2950 *
2951 * Returns 0 if successful, -1 otherwise
2952 */
2953int
2954xmlACatalogAdd(xmlCatalogPtr catal, const xmlChar * type,
2955 const xmlChar * orig, const xmlChar * replace)
2956{
2957 int res = -1;
2958
2959 if (catal == NULL)
2960 return(-1);
2961
2962 if (catal->type == XML_XML_CATALOG_TYPE) {
2963 res = xmlAddXMLCatalog(catal->xml, type, orig, replace);
2964 } else {
2965 xmlCatalogEntryType cattype;
2966
2967 cattype = xmlGetSGMLCatalogEntryType(type);
2968 if (cattype != XML_CATA_NONE) {
2969 xmlCatalogEntryPtr entry;
2970
Daniel Veillardc853b322001-11-06 15:24:37 +00002971 entry = xmlNewCatalogEntry(cattype, orig, replace, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00002972 XML_CATA_PREFER_NONE, NULL);
Daniel Veillardcd21dc72001-11-04 20:03:38 +00002973 if (catal->sgml == NULL)
2974 catal->sgml = xmlHashCreate(10);
Daniel Veillard75b96822001-10-11 18:59:45 +00002975 res = xmlHashAddEntry(catal->sgml, orig, entry);
2976 }
2977 }
2978 return (res);
2979}
2980
2981/**
2982 * xmlACatalogRemove:
2983 * @catal: a Catalog
2984 * @value: the value to remove
2985 *
2986 * Remove an entry from the catalog
2987 *
2988 * Returns the number of entries removed if successful, -1 otherwise
2989 */
2990int
2991xmlACatalogRemove(xmlCatalogPtr catal, const xmlChar *value) {
2992 int res = -1;
2993
2994 if ((catal == NULL) || (value == NULL))
2995 return(-1);
2996
2997 if (catal->type == XML_XML_CATALOG_TYPE) {
2998 res = xmlDelXMLCatalog(catal->xml, value);
2999 } else {
3000 res = xmlHashRemoveEntry(catal->sgml, value,
3001 (xmlHashDeallocator) xmlFreeCatalogEntry);
3002 if (res == 0)
3003 res = 1;
3004 }
3005 return(res);
3006}
3007
Daniel Veillardcd21dc72001-11-04 20:03:38 +00003008/**
3009 * xmlNewCatalog:
3010 * @sgml: should this create an SGML catalog
3011 *
3012 * create a new Catalog.
3013 *
3014 * Returns the xmlCatalogPtr or NULL in case of error
3015 */
3016xmlCatalogPtr
3017xmlNewCatalog(int sgml) {
3018 xmlCatalogPtr catal = NULL;
3019
3020 if (sgml) {
3021 catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE,
3022 xmlCatalogDefaultPrefer);
3023 if ((catal != NULL) && (catal->sgml == NULL))
3024 catal->sgml = xmlHashCreate(10);
3025 } else
3026 catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3027 xmlCatalogDefaultPrefer);
3028 return(catal);
3029}
3030
3031/**
3032 * xmlCatalogIsEmpty:
3033 * @catal: should this create an SGML catalog
3034 *
3035 * Check is a catalog is empty
3036 *
3037 * Returns 1 if the catalog is empty, 0 if not, amd -1 in case of error.
3038 */
3039int
3040xmlCatalogIsEmpty(xmlCatalogPtr catal) {
3041 if (catal == NULL)
3042 return(-1);
3043
3044 if (catal->type == XML_XML_CATALOG_TYPE) {
3045 if (catal->xml == NULL)
3046 return(1);
3047 if ((catal->xml->type != XML_CATA_CATALOG) &&
3048 (catal->xml->type != XML_CATA_BROKEN_CATALOG))
3049 return(-1);
3050 if (catal->xml->children == NULL)
3051 return(1);
3052 return(0);
3053 } else {
3054 int res;
3055
3056 if (catal->sgml == NULL)
3057 return(1);
3058 res = xmlHashSize(catal->sgml);
3059 if (res == 0)
3060 return(1);
3061 if (res < 0)
3062 return(-1);
3063 }
3064 return(0);
3065}
3066
Daniel Veillard75b96822001-10-11 18:59:45 +00003067/************************************************************************
3068 * *
3069 * Public interfaces manipulating the global shared default catalog *
Daniel Veillarda7374592001-05-10 14:17:55 +00003070 * *
3071 ************************************************************************/
3072
Daniel Veillard5e2dace2001-07-18 19:30:27 +00003073/**
Daniel Veillard81463942001-10-16 12:34:39 +00003074 * xmlInitializeCatalogData:
3075 *
3076 * Do the catalog initialization only of global data, doesn't try to load
3077 * any catalog actually.
3078 * this function is not thread safe, catalog initialization should
3079 * preferably be done once at startup
3080 */
3081static void
3082xmlInitializeCatalogData(void) {
3083 if (xmlCatalogInitialized != 0)
3084 return;
3085
3086 if (getenv("XML_DEBUG_CATALOG"))
3087 xmlDebugCatalogs = 1;
3088 xmlCatalogMutex = xmlNewRMutex();
3089
3090 xmlCatalogInitialized = 1;
3091}
3092/**
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003093 * xmlInitializeCatalog:
3094 *
3095 * Do the catalog initialization.
Daniel Veillard81463942001-10-16 12:34:39 +00003096 * this function is not thread safe, catalog initialization should
3097 * preferably be done once at startup
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003098 */
3099void
3100xmlInitializeCatalog(void) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003101 if (xmlCatalogInitialized != 0)
3102 return;
3103
Daniel Veillard81463942001-10-16 12:34:39 +00003104 xmlInitializeCatalogData();
3105 xmlRMutexLock(xmlCatalogMutex);
3106
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003107 if (getenv("XML_DEBUG_CATALOG"))
3108 xmlDebugCatalogs = 1;
Daniel Veillard81463942001-10-16 12:34:39 +00003109
Daniel Veillard75b96822001-10-11 18:59:45 +00003110 if (xmlDefaultCatalog == NULL) {
3111 const char *catalogs;
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003112 char *path;
3113 const char *cur, *paths;
Daniel Veillard75b96822001-10-11 18:59:45 +00003114 xmlCatalogPtr catal;
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003115 xmlCatalogEntryPtr *nextent;
Daniel Veillard75b96822001-10-11 18:59:45 +00003116
Daniel Veillardb44025c2001-10-11 22:55:55 +00003117 catalogs = (const char *) getenv("XML_CATALOG_FILES");
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003118 if (catalogs == NULL)
Daniel Veillardfb382b82004-06-14 12:13:12 +00003119#if defined(_WIN32) && defined(_MSC_VER)
3120 {
3121 void* hmodule;
3122 hmodule = GetModuleHandleA("libxml2.dll");
3123 if (hmodule == NULL)
3124 hmodule = GetModuleHandleA(NULL);
3125 if (hmodule != NULL) {
3126 char buf[256];
3127 unsigned long len = GetModuleFileNameA(hmodule, buf, 255);
3128 if (len != 0) {
3129 char* p = &(buf[len]);
3130 while (*p != '\\' && p > buf)
3131 p--;
3132 if (p != buf) {
3133 xmlChar* uri;
3134 strncpy(p, "\\..\\etc\\catalog", 255 - (p - buf));
3135 uri = xmlCanonicPath(buf);
3136 if (uri != NULL) {
3137 strncpy(XML_XML_DEFAULT_CATALOG, uri, 255);
3138 xmlFree(uri);
3139 }
3140 }
3141 }
3142 }
3143 catalogs = XML_XML_DEFAULT_CATALOG;
3144 }
3145#else
Daniel Veillard75b96822001-10-11 18:59:45 +00003146 catalogs = XML_XML_DEFAULT_CATALOG;
Daniel Veillardfb382b82004-06-14 12:13:12 +00003147#endif
Daniel Veillard75b96822001-10-11 18:59:45 +00003148
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003149 catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3150 xmlCatalogDefaultPrefer);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00003151 if (catal != NULL) {
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003152 /* the XML_CATALOG_FILES envvar is allowed to contain a
3153 space-separated list of entries. */
3154 cur = catalogs;
3155 nextent = &catal->xml;
3156 while (*cur != '\0') {
William M. Brack68aca052003-10-11 15:22:13 +00003157 while (xmlIsBlank_ch(*cur))
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003158 cur++;
3159 if (*cur != 0) {
3160 paths = cur;
William M. Brack68aca052003-10-11 15:22:13 +00003161 while ((*cur != 0) && (!xmlIsBlank_ch(*cur)))
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003162 cur++;
Daniel Veillarde645e8c2002-10-22 17:35:37 +00003163 path = (char *) xmlStrndup((const xmlChar *)paths, cur - paths);
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003164 if (path != NULL) {
3165 *nextent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00003166 NULL, BAD_CAST path, xmlCatalogDefaultPrefer, NULL);
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003167 if (*nextent != NULL)
3168 nextent = &((*nextent)->next);
3169 xmlFree(path);
3170 }
3171 }
3172 }
Daniel Veillard85c11fa2001-10-16 21:03:08 +00003173 xmlDefaultCatalog = catal;
3174 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003175 }
3176
Daniel Veillard81463942001-10-16 12:34:39 +00003177 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003178}
3179
Daniel Veillard82d75332001-10-08 15:01:59 +00003180
3181/**
Daniel Veillarda7374592001-05-10 14:17:55 +00003182 * xmlLoadCatalog:
3183 * @filename: a file path
3184 *
Daniel Veillard81418e32001-05-22 15:08:55 +00003185 * Load the catalog and makes its definitions effective for the default
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003186 * external entity loader. It will recurse in SGML CATALOG entries.
Daniel Veillard81463942001-10-16 12:34:39 +00003187 * this function is not thread safe, catalog initialization should
3188 * preferably be done once at startup
Daniel Veillarda7374592001-05-10 14:17:55 +00003189 *
3190 * Returns 0 in case of success -1 in case of error
3191 */
3192int
Daniel Veillard16756b62001-10-01 07:36:25 +00003193xmlLoadCatalog(const char *filename)
3194{
Daniel Veillard75b96822001-10-11 18:59:45 +00003195 int ret;
3196 xmlCatalogPtr catal;
Daniel Veillard16756b62001-10-01 07:36:25 +00003197
Daniel Veillard81463942001-10-16 12:34:39 +00003198 if (!xmlCatalogInitialized)
3199 xmlInitializeCatalogData();
3200
3201 xmlRMutexLock(xmlCatalogMutex);
3202
Daniel Veillard75b96822001-10-11 18:59:45 +00003203 if (xmlDefaultCatalog == NULL) {
3204 catal = xmlLoadACatalog(filename);
William M. Brack59002e72003-07-04 17:01:59 +00003205 if (catal == NULL) {
3206 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003207 return(-1);
William M. Brack59002e72003-07-04 17:01:59 +00003208 }
Daniel Veillarda7374592001-05-10 14:17:55 +00003209
Daniel Veillard75b96822001-10-11 18:59:45 +00003210 xmlDefaultCatalog = catal;
Daniel Veillard81463942001-10-16 12:34:39 +00003211 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003212 return(0);
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00003213 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00003214
Daniel Veillard75b96822001-10-11 18:59:45 +00003215 ret = xmlExpandCatalog(xmlDefaultCatalog, filename);
Daniel Veillard81463942001-10-16 12:34:39 +00003216 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003217 return(ret);
Daniel Veillarda7374592001-05-10 14:17:55 +00003218}
3219
Daniel Veillard5e2dace2001-07-18 19:30:27 +00003220/**
Daniel Veillard81418e32001-05-22 15:08:55 +00003221 * xmlLoadCatalogs:
Daniel Veillard5aad8322002-12-11 15:59:44 +00003222 * @pathss: a list of directories separated by a colon or a space.
Daniel Veillard81418e32001-05-22 15:08:55 +00003223 *
3224 * Load the catalogs and makes their definitions effective for the default
3225 * external entity loader.
Daniel Veillard81463942001-10-16 12:34:39 +00003226 * this function is not thread safe, catalog initialization should
3227 * preferably be done once at startup
Daniel Veillard81418e32001-05-22 15:08:55 +00003228 */
3229void
3230xmlLoadCatalogs(const char *pathss) {
3231 const char *cur;
3232 const char *paths;
3233 xmlChar *path;
Daniel Veillarded121382007-04-17 12:33:19 +00003234#ifdef _WIN32
3235 int i, iLen;
3236#endif
Daniel Veillard81418e32001-05-22 15:08:55 +00003237
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003238 if (pathss == NULL)
3239 return;
3240
Daniel Veillard81418e32001-05-22 15:08:55 +00003241 cur = pathss;
Daniel Veillard2728f842006-03-09 16:49:24 +00003242 while (*cur != 0) {
William M. Brack68aca052003-10-11 15:22:13 +00003243 while (xmlIsBlank_ch(*cur)) cur++;
Daniel Veillard81418e32001-05-22 15:08:55 +00003244 if (*cur != 0) {
3245 paths = cur;
Daniel Veillarded121382007-04-17 12:33:19 +00003246 while ((*cur != 0) && (*cur != PATH_SEAPARATOR) && (!xmlIsBlank_ch(*cur)))
Daniel Veillard81418e32001-05-22 15:08:55 +00003247 cur++;
3248 path = xmlStrndup((const xmlChar *)paths, cur - paths);
Daniel Veillarded121382007-04-17 12:33:19 +00003249#ifdef _WIN32
3250 iLen = strlen(path);
3251 for(i = 0; i < iLen; i++) {
3252 if(path[i] == '\\') {
3253 path[i] = '/';
3254 }
3255 }
3256#endif
Daniel Veillard81418e32001-05-22 15:08:55 +00003257 if (path != NULL) {
3258 xmlLoadCatalog((const char *) path);
3259 xmlFree(path);
3260 }
3261 }
Daniel Veillarded121382007-04-17 12:33:19 +00003262 while (*cur == PATH_SEAPARATOR)
Igor Zlatkovic130e5792002-11-06 22:51:58 +00003263 cur++;
Daniel Veillard81418e32001-05-22 15:08:55 +00003264 }
3265}
3266
Daniel Veillarda7374592001-05-10 14:17:55 +00003267/**
3268 * xmlCatalogCleanup:
3269 *
3270 * Free up all the memory associated with catalogs
3271 */
3272void
3273xmlCatalogCleanup(void) {
Daniel Veillard364789a2001-10-16 12:45:00 +00003274 if (xmlCatalogInitialized == 0)
3275 return;
3276
Daniel Veillard81463942001-10-16 12:34:39 +00003277 xmlRMutexLock(xmlCatalogMutex);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003278 if (xmlDebugCatalogs)
3279 xmlGenericError(xmlGenericErrorContext,
3280 "Catalogs cleanup\n");
Daniel Veillard6990bf32001-08-23 21:17:48 +00003281 if (xmlCatalogXMLFiles != NULL)
Daniel Veillard85c11fa2001-10-16 21:03:08 +00003282 xmlHashFree(xmlCatalogXMLFiles,
3283 (xmlHashDeallocator)xmlFreeCatalogHashEntryList);
Daniel Veillard6990bf32001-08-23 21:17:48 +00003284 xmlCatalogXMLFiles = NULL;
Daniel Veillarda7374592001-05-10 14:17:55 +00003285 if (xmlDefaultCatalog != NULL)
Daniel Veillard75b96822001-10-11 18:59:45 +00003286 xmlFreeCatalog(xmlDefaultCatalog);
Daniel Veillard6990bf32001-08-23 21:17:48 +00003287 xmlDefaultCatalog = NULL;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003288 xmlDebugCatalogs = 0;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003289 xmlCatalogInitialized = 0;
Daniel Veillard81463942001-10-16 12:34:39 +00003290 xmlRMutexUnlock(xmlCatalogMutex);
3291 xmlFreeRMutex(xmlCatalogMutex);
Daniel Veillarda7374592001-05-10 14:17:55 +00003292}
3293
3294/**
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003295 * xmlCatalogResolveSystem:
Daniel Veillard06d25242004-02-25 13:01:42 +00003296 * @sysID: the system ID string
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003297 *
3298 * Try to lookup the catalog resource for a system ID
3299 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003300 * Returns the resource if found or NULL otherwise, the value returned
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003301 * must be freed by the caller.
3302 */
3303xmlChar *
3304xmlCatalogResolveSystem(const xmlChar *sysID) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003305 xmlChar *ret;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003306
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003307 if (!xmlCatalogInitialized)
3308 xmlInitializeCatalog();
3309
Daniel Veillard75b96822001-10-11 18:59:45 +00003310 ret = xmlACatalogResolveSystem(xmlDefaultCatalog, sysID);
3311 return(ret);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003312}
3313
3314/**
3315 * xmlCatalogResolvePublic:
Daniel Veillard5aad8322002-12-11 15:59:44 +00003316 * @pubID: the public ID string
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003317 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003318 * Try to lookup the catalog reference associated to a public ID
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003319 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003320 * Returns the resource if found or NULL otherwise, the value returned
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003321 * must be freed by the caller.
3322 */
3323xmlChar *
3324xmlCatalogResolvePublic(const xmlChar *pubID) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003325 xmlChar *ret;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003326
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003327 if (!xmlCatalogInitialized)
3328 xmlInitializeCatalog();
3329
Daniel Veillard75b96822001-10-11 18:59:45 +00003330 ret = xmlACatalogResolvePublic(xmlDefaultCatalog, pubID);
3331 return(ret);
Daniel Veillard7d6fd212001-05-10 15:34:11 +00003332}
Daniel Veillard344cee72001-08-20 00:08:40 +00003333
Daniel Veillard7d6fd212001-05-10 15:34:11 +00003334/**
Daniel Veillardcda96922001-08-21 10:56:31 +00003335 * xmlCatalogResolve:
Daniel Veillard5aad8322002-12-11 15:59:44 +00003336 * @pubID: the public ID string
3337 * @sysID: the system ID string
Daniel Veillardcda96922001-08-21 10:56:31 +00003338 *
3339 * Do a complete resolution lookup of an External Identifier
3340 *
3341 * Returns the URI of the resource or NULL if not found, it must be freed
3342 * by the caller.
3343 */
3344xmlChar *
3345xmlCatalogResolve(const xmlChar *pubID, const xmlChar *sysID) {
Daniel Veillard75b96822001-10-11 18:59:45 +00003346 xmlChar *ret;
Daniel Veillard6990bf32001-08-23 21:17:48 +00003347
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003348 if (!xmlCatalogInitialized)
3349 xmlInitializeCatalog();
3350
Daniel Veillard75b96822001-10-11 18:59:45 +00003351 ret = xmlACatalogResolve(xmlDefaultCatalog, pubID, sysID);
3352 return(ret);
Daniel Veillardcda96922001-08-21 10:56:31 +00003353}
3354
3355/**
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003356 * xmlCatalogResolveURI:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00003357 * @URI: the URI
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003358 *
3359 * Do a complete resolution lookup of an URI
3360 *
3361 * Returns the URI of the resource or NULL if not found, it must be freed
3362 * by the caller.
3363 */
3364xmlChar *
3365xmlCatalogResolveURI(const xmlChar *URI) {
Daniel Veillard75b96822001-10-11 18:59:45 +00003366 xmlChar *ret;
3367
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003368 if (!xmlCatalogInitialized)
3369 xmlInitializeCatalog();
3370
Daniel Veillard75b96822001-10-11 18:59:45 +00003371 ret = xmlACatalogResolveURI(xmlDefaultCatalog, URI);
3372 return(ret);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003373}
3374
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003375#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003376/**
Daniel Veillarda7374592001-05-10 14:17:55 +00003377 * xmlCatalogDump:
3378 * @out: the file.
3379 *
Daniel Veillarda8dc2882004-03-29 12:21:26 +00003380 * Dump all the global catalog content to the given file.
Daniel Veillarda7374592001-05-10 14:17:55 +00003381 */
3382void
3383xmlCatalogDump(FILE *out) {
3384 if (out == NULL)
3385 return;
Daniel Veillard344cee72001-08-20 00:08:40 +00003386
Daniel Veillard75b96822001-10-11 18:59:45 +00003387 if (!xmlCatalogInitialized)
3388 xmlInitializeCatalog();
3389
3390 xmlACatalogDump(xmlDefaultCatalog, out);
Daniel Veillard344cee72001-08-20 00:08:40 +00003391}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003392#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard344cee72001-08-20 00:08:40 +00003393
3394/**
3395 * xmlCatalogAdd:
3396 * @type: the type of record to add to the catalog
3397 * @orig: the system, public or prefix to match
3398 * @replace: the replacement value for the match
3399 *
3400 * Add an entry in the catalog, it may overwrite existing but
3401 * different entries.
Daniel Veillardcbaf3992001-12-31 16:16:02 +00003402 * If called before any other catalog routine, allows to override the
Daniel Veillard75b96822001-10-11 18:59:45 +00003403 * default shared catalog put in place by xmlInitializeCatalog();
Daniel Veillard344cee72001-08-20 00:08:40 +00003404 *
3405 * Returns 0 if successful, -1 otherwise
3406 */
3407int
3408xmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace) {
3409 int res = -1;
3410
Daniel Veillard81463942001-10-16 12:34:39 +00003411 if (!xmlCatalogInitialized)
3412 xmlInitializeCatalogData();
3413
3414 xmlRMutexLock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003415 /*
3416 * Specific case where one want to override the default catalog
3417 * put in place by xmlInitializeCatalog();
3418 */
3419 if ((xmlDefaultCatalog == NULL) &&
Daniel Veillarde7ead2d2001-08-22 23:44:09 +00003420 (xmlStrEqual(type, BAD_CAST "catalog"))) {
Daniel Veillardcd21dc72001-11-04 20:03:38 +00003421 xmlDefaultCatalog = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
Daniel Veillard75b96822001-10-11 18:59:45 +00003422 xmlCatalogDefaultPrefer);
3423 xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00003424 orig, NULL, xmlCatalogDefaultPrefer, NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00003425
Daniel Veillard81463942001-10-16 12:34:39 +00003426 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillarde7ead2d2001-08-22 23:44:09 +00003427 return(0);
3428 }
3429
Daniel Veillard75b96822001-10-11 18:59:45 +00003430 res = xmlACatalogAdd(xmlDefaultCatalog, type, orig, replace);
Daniel Veillard81463942001-10-16 12:34:39 +00003431 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillard344cee72001-08-20 00:08:40 +00003432 return(res);
3433}
3434
3435/**
3436 * xmlCatalogRemove:
3437 * @value: the value to remove
3438 *
3439 * Remove an entry from the catalog
3440 *
Daniel Veillard82d75332001-10-08 15:01:59 +00003441 * Returns the number of entries removed if successful, -1 otherwise
Daniel Veillard344cee72001-08-20 00:08:40 +00003442 */
3443int
3444xmlCatalogRemove(const xmlChar *value) {
Daniel Veillard75b96822001-10-11 18:59:45 +00003445 int res;
Daniel Veillardcda96922001-08-21 10:56:31 +00003446
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003447 if (!xmlCatalogInitialized)
3448 xmlInitializeCatalog();
3449
Daniel Veillard81463942001-10-16 12:34:39 +00003450 xmlRMutexLock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003451 res = xmlACatalogRemove(xmlDefaultCatalog, value);
Daniel Veillard81463942001-10-16 12:34:39 +00003452 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillardcda96922001-08-21 10:56:31 +00003453 return(res);
Daniel Veillard344cee72001-08-20 00:08:40 +00003454}
3455
3456/**
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003457 * xmlCatalogConvert:
3458 *
3459 * Convert all the SGML catalog entries as XML ones
3460 *
3461 * Returns the number of entries converted if successful, -1 otherwise
3462 */
3463int
3464xmlCatalogConvert(void) {
3465 int res = -1;
3466
3467 if (!xmlCatalogInitialized)
3468 xmlInitializeCatalog();
3469
Daniel Veillard81463942001-10-16 12:34:39 +00003470 xmlRMutexLock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003471 res = xmlConvertSGMLCatalog(xmlDefaultCatalog);
Daniel Veillard81463942001-10-16 12:34:39 +00003472 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003473 return(res);
3474}
3475
Daniel Veillard75b96822001-10-11 18:59:45 +00003476/************************************************************************
3477 * *
3478 * Public interface manipulating the common preferences *
3479 * *
3480 ************************************************************************/
Daniel Veillard81463942001-10-16 12:34:39 +00003481
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003482/**
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003483 * xmlCatalogGetDefaults:
3484 *
3485 * Used to get the user preference w.r.t. to what catalogs should
3486 * be accepted
3487 *
3488 * Returns the current xmlCatalogAllow value
3489 */
3490xmlCatalogAllow
3491xmlCatalogGetDefaults(void) {
3492 return(xmlCatalogDefaultAllow);
3493}
3494
3495/**
3496 * xmlCatalogSetDefaults:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00003497 * @allow: what catalogs should be accepted
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003498 *
3499 * Used to set the user preference w.r.t. to what catalogs should
3500 * be accepted
3501 */
3502void
3503xmlCatalogSetDefaults(xmlCatalogAllow allow) {
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003504 if (xmlDebugCatalogs) {
3505 switch (allow) {
3506 case XML_CATA_ALLOW_NONE:
3507 xmlGenericError(xmlGenericErrorContext,
3508 "Disabling catalog usage\n");
3509 break;
3510 case XML_CATA_ALLOW_GLOBAL:
3511 xmlGenericError(xmlGenericErrorContext,
3512 "Allowing only global catalogs\n");
3513 break;
3514 case XML_CATA_ALLOW_DOCUMENT:
3515 xmlGenericError(xmlGenericErrorContext,
3516 "Allowing only catalogs from the document\n");
3517 break;
3518 case XML_CATA_ALLOW_ALL:
3519 xmlGenericError(xmlGenericErrorContext,
3520 "Allowing all catalogs\n");
3521 break;
3522 }
3523 }
3524 xmlCatalogDefaultAllow = allow;
3525}
3526
3527/**
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003528 * xmlCatalogSetDefaultPrefer:
3529 * @prefer: the default preference for delegation
3530 *
3531 * Allows to set the preference between public and system for deletion
3532 * in XML Catalog resolution. C.f. section 4.1.1 of the spec
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003533 * Values accepted are XML_CATA_PREFER_PUBLIC or XML_CATA_PREFER_SYSTEM
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003534 *
3535 * Returns the previous value of the default preference for delegation
3536 */
3537xmlCatalogPrefer
3538xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer) {
3539 xmlCatalogPrefer ret = xmlCatalogDefaultPrefer;
3540
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003541 if (prefer == XML_CATA_PREFER_NONE)
3542 return(ret);
3543
3544 if (xmlDebugCatalogs) {
3545 switch (prefer) {
3546 case XML_CATA_PREFER_PUBLIC:
3547 xmlGenericError(xmlGenericErrorContext,
3548 "Setting catalog preference to PUBLIC\n");
3549 break;
3550 case XML_CATA_PREFER_SYSTEM:
3551 xmlGenericError(xmlGenericErrorContext,
3552 "Setting catalog preference to SYSTEM\n");
3553 break;
3554 case XML_CATA_PREFER_NONE:
3555 break;
3556 }
3557 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003558 xmlCatalogDefaultPrefer = prefer;
3559 return(ret);
3560}
3561
3562/**
Daniel Veillard344cee72001-08-20 00:08:40 +00003563 * xmlCatalogSetDebug:
3564 * @level: the debug level of catalogs required
3565 *
3566 * Used to set the debug level for catalog operation, 0 disable
3567 * debugging, 1 enable it
3568 *
3569 * Returns the previous value of the catalog debugging level
3570 */
3571int
3572xmlCatalogSetDebug(int level) {
3573 int ret = xmlDebugCatalogs;
3574
3575 if (level <= 0)
3576 xmlDebugCatalogs = 0;
3577 else
3578 xmlDebugCatalogs = level;
3579 return(ret);
Daniel Veillarda7374592001-05-10 14:17:55 +00003580}
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003581
Daniel Veillard75b96822001-10-11 18:59:45 +00003582/************************************************************************
3583 * *
3584 * Minimal interfaces used for per-document catalogs by the parser *
3585 * *
3586 ************************************************************************/
3587
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003588/**
3589 * xmlCatalogFreeLocal:
3590 * @catalogs: a document's list of catalogs
3591 *
3592 * Free up the memory associated to the catalog list
3593 */
3594void
3595xmlCatalogFreeLocal(void *catalogs) {
3596 xmlCatalogEntryPtr catal;
3597
Daniel Veillard81463942001-10-16 12:34:39 +00003598 if (!xmlCatalogInitialized)
3599 xmlInitializeCatalog();
3600
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003601 catal = (xmlCatalogEntryPtr) catalogs;
3602 if (catal != NULL)
3603 xmlFreeCatalogEntryList(catal);
3604}
3605
3606
3607/**
3608 * xmlCatalogAddLocal:
3609 * @catalogs: a document's list of catalogs
3610 * @URL: the URL to a new local catalog
3611 *
3612 * Add the new entry to the catalog list
3613 *
3614 * Returns the updated list
3615 */
3616void *
3617xmlCatalogAddLocal(void *catalogs, const xmlChar *URL) {
3618 xmlCatalogEntryPtr catal, add;
3619
3620 if (!xmlCatalogInitialized)
3621 xmlInitializeCatalog();
Daniel Veillard81463942001-10-16 12:34:39 +00003622
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003623 if (URL == NULL)
3624 return(catalogs);
3625
3626 if (xmlDebugCatalogs)
3627 xmlGenericError(xmlGenericErrorContext,
3628 "Adding document catalog %s\n", URL);
3629
Daniel Veillardc853b322001-11-06 15:24:37 +00003630 add = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, URL, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00003631 xmlCatalogDefaultPrefer, NULL);
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003632 if (add == NULL)
3633 return(catalogs);
3634
3635 catal = (xmlCatalogEntryPtr) catalogs;
3636 if (catal == NULL)
3637 return((void *) add);
3638
3639 while (catal->next != NULL)
3640 catal = catal->next;
3641 catal->next = add;
3642 return(catalogs);
3643}
3644
3645/**
3646 * xmlCatalogLocalResolve:
3647 * @catalogs: a document's list of catalogs
Daniel Veillard5aad8322002-12-11 15:59:44 +00003648 * @pubID: the public ID string
3649 * @sysID: the system ID string
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003650 *
3651 * Do a complete resolution lookup of an External Identifier using a
3652 * document's private catalog list
3653 *
3654 * Returns the URI of the resource or NULL if not found, it must be freed
3655 * by the caller.
3656 */
3657xmlChar *
3658xmlCatalogLocalResolve(void *catalogs, const xmlChar *pubID,
3659 const xmlChar *sysID) {
3660 xmlCatalogEntryPtr catal;
Daniel Veillard6990bf32001-08-23 21:17:48 +00003661 xmlChar *ret;
3662
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003663 if (!xmlCatalogInitialized)
3664 xmlInitializeCatalog();
Daniel Veillard6990bf32001-08-23 21:17:48 +00003665
Daniel Veillard81463942001-10-16 12:34:39 +00003666 if ((pubID == NULL) && (sysID == NULL))
3667 return(NULL);
3668
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003669 if (xmlDebugCatalogs) {
Daniel Veillard770075b2004-02-25 10:44:30 +00003670 if ((pubID != NULL) && (sysID != NULL)) {
3671 xmlGenericError(xmlGenericErrorContext,
3672 "Local Resolve: pubID %s sysID %s\n", pubID, sysID);
3673 } else if (pubID != NULL) {
3674 xmlGenericError(xmlGenericErrorContext,
3675 "Local Resolve: pubID %s\n", pubID);
3676 } else {
3677 xmlGenericError(xmlGenericErrorContext,
3678 "Local Resolve: sysID %s\n", sysID);
3679 }
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003680 }
Daniel Veillard6990bf32001-08-23 21:17:48 +00003681
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003682 catal = (xmlCatalogEntryPtr) catalogs;
3683 if (catal == NULL)
3684 return(NULL);
Daniel Veillard6990bf32001-08-23 21:17:48 +00003685 ret = xmlCatalogListXMLResolve(catal, pubID, sysID);
3686 if ((ret != NULL) && (ret != XML_CATAL_BREAK))
3687 return(ret);
3688 return(NULL);
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003689}
3690
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003691/**
3692 * xmlCatalogLocalResolveURI:
3693 * @catalogs: a document's list of catalogs
Daniel Veillardcbaf3992001-12-31 16:16:02 +00003694 * @URI: the URI
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003695 *
3696 * Do a complete resolution lookup of an URI using a
3697 * document's private catalog list
3698 *
3699 * Returns the URI of the resource or NULL if not found, it must be freed
3700 * by the caller.
3701 */
3702xmlChar *
3703xmlCatalogLocalResolveURI(void *catalogs, const xmlChar *URI) {
3704 xmlCatalogEntryPtr catal;
Daniel Veillard6990bf32001-08-23 21:17:48 +00003705 xmlChar *ret;
3706
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003707 if (!xmlCatalogInitialized)
3708 xmlInitializeCatalog();
Daniel Veillard6990bf32001-08-23 21:17:48 +00003709
Daniel Veillard81463942001-10-16 12:34:39 +00003710 if (URI == NULL)
3711 return(NULL);
3712
Daniel Veillard6990bf32001-08-23 21:17:48 +00003713 if (xmlDebugCatalogs)
3714 xmlGenericError(xmlGenericErrorContext,
3715 "Resolve URI %s\n", URI);
3716
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003717 catal = (xmlCatalogEntryPtr) catalogs;
3718 if (catal == NULL)
3719 return(NULL);
Daniel Veillard6990bf32001-08-23 21:17:48 +00003720 ret = xmlCatalogListXMLResolveURI(catal, URI);
3721 if ((ret != NULL) && (ret != XML_CATAL_BREAK))
3722 return(ret);
3723 return(NULL);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003724}
3725
Daniel Veillard75b96822001-10-11 18:59:45 +00003726/************************************************************************
3727 * *
3728 * Deprecated interfaces *
3729 * *
3730 ************************************************************************/
3731/**
3732 * xmlCatalogGetSystem:
Daniel Veillard5aad8322002-12-11 15:59:44 +00003733 * @sysID: the system ID string
Daniel Veillard75b96822001-10-11 18:59:45 +00003734 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003735 * Try to lookup the catalog reference associated to a system ID
Daniel Veillard75b96822001-10-11 18:59:45 +00003736 * DEPRECATED, use xmlCatalogResolveSystem()
3737 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003738 * Returns the resource if found or NULL otherwise.
Daniel Veillard75b96822001-10-11 18:59:45 +00003739 */
3740const xmlChar *
3741xmlCatalogGetSystem(const xmlChar *sysID) {
Daniel Veillardab690c52004-06-14 12:19:09 +00003742 xmlChar *ret;
3743 static xmlChar result[1000];
3744 static int msg = 0;
3745
3746 if (!xmlCatalogInitialized)
3747 xmlInitializeCatalog();
3748
3749 if (msg == 0) {
3750 xmlGenericError(xmlGenericErrorContext,
3751 "Use of deprecated xmlCatalogGetSystem() call\n");
3752 msg++;
3753 }
3754
3755 if (sysID == NULL)
3756 return(NULL);
3757
3758 /*
3759 * Check first the XML catalogs
3760 */
3761 if (xmlDefaultCatalog != NULL) {
3762 ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, NULL, sysID);
3763 if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
3764 snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
3765 result[sizeof(result) - 1] = 0;
3766 return(result);
3767 }
3768 }
3769
3770 if (xmlDefaultCatalog != NULL)
3771 return(xmlCatalogGetSGMLSystem(xmlDefaultCatalog->sgml, sysID));
3772 return(NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00003773}
3774
3775/**
3776 * xmlCatalogGetPublic:
Daniel Veillard5aad8322002-12-11 15:59:44 +00003777 * @pubID: the public ID string
Daniel Veillard75b96822001-10-11 18:59:45 +00003778 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003779 * Try to lookup the catalog reference associated to a public ID
Daniel Veillard75b96822001-10-11 18:59:45 +00003780 * DEPRECATED, use xmlCatalogResolvePublic()
3781 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003782 * Returns the resource if found or NULL otherwise.
Daniel Veillard75b96822001-10-11 18:59:45 +00003783 */
3784const xmlChar *
3785xmlCatalogGetPublic(const xmlChar *pubID) {
Daniel Veillardab690c52004-06-14 12:19:09 +00003786 xmlChar *ret;
3787 static xmlChar result[1000];
3788 static int msg = 0;
3789
3790 if (!xmlCatalogInitialized)
3791 xmlInitializeCatalog();
3792
3793 if (msg == 0) {
3794 xmlGenericError(xmlGenericErrorContext,
3795 "Use of deprecated xmlCatalogGetPublic() call\n");
3796 msg++;
3797 }
3798
3799 if (pubID == NULL)
3800 return(NULL);
3801
3802 /*
3803 * Check first the XML catalogs
3804 */
3805 if (xmlDefaultCatalog != NULL) {
3806 ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, pubID, NULL);
3807 if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
3808 snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
3809 result[sizeof(result) - 1] = 0;
3810 return(result);
3811 }
3812 }
3813
3814 if (xmlDefaultCatalog != NULL)
3815 return(xmlCatalogGetSGMLPublic(xmlDefaultCatalog->sgml, pubID));
3816 return(NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00003817}
3818
Daniel Veillard5d4644e2005-04-01 13:11:58 +00003819#define bottom_catalog
3820#include "elfgcchack.h"
Daniel Veillarda7374592001-05-10 14:17:55 +00003821#endif /* LIBXML_CATALOG_ENABLED */