blob: 1fac0254d05e648933081b38e8314bd732fae068 [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 Veillard2a1d2422012-07-16 14:38:14 +080044#include "buf.h"
45
Daniel Veillard6990bf32001-08-23 21:17:48 +000046#define MAX_DELEGATE 50
Daniel Veillard5ee43b02003-08-04 00:58:46 +000047#define MAX_CATAL_DEPTH 50
Daniel Veillard6990bf32001-08-23 21:17:48 +000048
Daniel Veillarded121382007-04-17 12:33:19 +000049#ifdef _WIN32
50# define PATH_SEAPARATOR ';'
51#else
52# define PATH_SEAPARATOR ':'
53#endif
54
Daniel Veillard344cee72001-08-20 00:08:40 +000055/**
56 * TODO:
57 *
58 * macro to flag unimplemented blocks
Daniel Veillard3e59fc52003-04-18 12:34:58 +000059 * XML_CATALOG_PREFER user env to select between system/public prefered
60 * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk>
61 *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
62 *> values "system" and "public". I have made the default be "system" to
63 *> match yours.
Daniel Veillard344cee72001-08-20 00:08:40 +000064 */
65#define TODO \
66 xmlGenericError(xmlGenericErrorContext, \
67 "Unimplemented block at %s:%d\n", \
68 __FILE__, __LINE__);
69
Daniel Veillardcda96922001-08-21 10:56:31 +000070#define XML_URN_PUBID "urn:publicid:"
Daniel Veillarde2940dd2001-08-22 00:06:49 +000071#define XML_CATAL_BREAK ((xmlChar *) -1)
Daniel Veillard75b96822001-10-11 18:59:45 +000072#ifndef XML_XML_DEFAULT_CATALOG
Daniel Veillardf7b094f2001-11-15 13:54:39 +000073#define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog"
Daniel Veillard6c5f9d12001-08-25 13:33:14 +000074#endif
Daniel Veillard75b96822001-10-11 18:59:45 +000075#ifndef XML_SGML_DEFAULT_CATALOG
Daniel Veillardf7b094f2001-11-15 13:54:39 +000076#define XML_SGML_DEFAULT_CATALOG "file:///etc/sgml/catalog"
Daniel Veillard75b96822001-10-11 18:59:45 +000077#endif
78
Daniel Veillardfb382b82004-06-14 12:13:12 +000079#if defined(_WIN32) && defined(_MSC_VER)
80#undef XML_XML_DEFAULT_CATALOG
81static char XML_XML_DEFAULT_CATALOG[256] = "file:///etc/xml/catalog";
Daniel Veillard59d3ed82007-04-17 12:44:58 +000082#if defined(_WIN32_WCE)
83/* Windows CE don't have a A variant */
84#define GetModuleHandleA GetModuleHandle
85#define GetModuleFileNameA GetModuleFileName
86#else
Daniel Veillardfb382b82004-06-14 12:13:12 +000087void* __stdcall GetModuleHandleA(const char*);
88unsigned long __stdcall GetModuleFileNameA(void*, char*, unsigned long);
89#endif
Daniel Veillard59d3ed82007-04-17 12:44:58 +000090#endif
Daniel Veillardfb382b82004-06-14 12:13:12 +000091
Daniel Veillardc8155052004-07-16 09:03:08 +000092static xmlChar *xmlCatalogNormalizePublic(const xmlChar *pubID);
Daniel Veillard85c11fa2001-10-16 21:03:08 +000093static int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename);
Daniel Veillard344cee72001-08-20 00:08:40 +000094
Daniel Veillarda7374592001-05-10 14:17:55 +000095/************************************************************************
96 * *
97 * Types, all private *
98 * *
99 ************************************************************************/
100
101typedef enum {
Daniel Veillardc853b322001-11-06 15:24:37 +0000102 XML_CATA_REMOVED = -1,
Daniel Veillarda7374592001-05-10 14:17:55 +0000103 XML_CATA_NONE = 0,
Daniel Veillarda7374592001-05-10 14:17:55 +0000104 XML_CATA_CATALOG,
Daniel Veillard9f7b84b2001-08-23 15:31:19 +0000105 XML_CATA_BROKEN_CATALOG,
Daniel Veillard344cee72001-08-20 00:08:40 +0000106 XML_CATA_NEXT_CATALOG,
William M. Brackb7b54de2004-10-06 16:38:01 +0000107 XML_CATA_GROUP,
Daniel Veillard344cee72001-08-20 00:08:40 +0000108 XML_CATA_PUBLIC,
109 XML_CATA_SYSTEM,
110 XML_CATA_REWRITE_SYSTEM,
111 XML_CATA_DELEGATE_PUBLIC,
112 XML_CATA_DELEGATE_SYSTEM,
113 XML_CATA_URI,
114 XML_CATA_REWRITE_URI,
115 XML_CATA_DELEGATE_URI,
116 SGML_CATA_SYSTEM,
117 SGML_CATA_PUBLIC,
118 SGML_CATA_ENTITY,
119 SGML_CATA_PENTITY,
120 SGML_CATA_DOCTYPE,
121 SGML_CATA_LINKTYPE,
122 SGML_CATA_NOTATION,
123 SGML_CATA_DELEGATE,
124 SGML_CATA_BASE,
125 SGML_CATA_CATALOG,
126 SGML_CATA_DOCUMENT,
127 SGML_CATA_SGMLDECL
Daniel Veillarda7374592001-05-10 14:17:55 +0000128} xmlCatalogEntryType;
129
130typedef struct _xmlCatalogEntry xmlCatalogEntry;
131typedef xmlCatalogEntry *xmlCatalogEntryPtr;
132struct _xmlCatalogEntry {
Daniel Veillard344cee72001-08-20 00:08:40 +0000133 struct _xmlCatalogEntry *next;
134 struct _xmlCatalogEntry *parent;
135 struct _xmlCatalogEntry *children;
Daniel Veillarda7374592001-05-10 14:17:55 +0000136 xmlCatalogEntryType type;
137 xmlChar *name;
138 xmlChar *value;
Daniel Veillardc853b322001-11-06 15:24:37 +0000139 xmlChar *URL; /* The expanded URL using the base */
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000140 xmlCatalogPrefer prefer;
Daniel Veillard6990bf32001-08-23 21:17:48 +0000141 int dealloc;
Daniel Veillard5ee43b02003-08-04 00:58:46 +0000142 int depth;
William M. Brackb7b54de2004-10-06 16:38:01 +0000143 struct _xmlCatalogEntry *group;
Daniel Veillarda7374592001-05-10 14:17:55 +0000144};
145
Daniel Veillard75b96822001-10-11 18:59:45 +0000146typedef enum {
147 XML_XML_CATALOG_TYPE = 1,
148 XML_SGML_CATALOG_TYPE
149} xmlCatalogType;
150
151#define XML_MAX_SGML_CATA_DEPTH 10
152struct _xmlCatalog {
153 xmlCatalogType type; /* either XML or SGML */
154
155 /*
156 * SGML Catalogs are stored as a simple hash table of catalog entries
157 * Catalog stack to check against overflows when building the
158 * SGML catalog
159 */
160 char *catalTab[XML_MAX_SGML_CATA_DEPTH]; /* stack of catals */
161 int catalNr; /* Number of current catal streams */
162 int catalMax; /* Max number of catal streams */
163 xmlHashTablePtr sgml;
164
165 /*
166 * XML Catalogs are stored as a tree of Catalog entries
167 */
168 xmlCatalogPrefer prefer;
169 xmlCatalogEntryPtr xml;
170};
171
172/************************************************************************
173 * *
174 * Global variables *
175 * *
176 ************************************************************************/
177
Daniel Veillard81463942001-10-16 12:34:39 +0000178/*
179 * Those are preferences
180 */
181static int xmlDebugCatalogs = 0; /* used for debugging */
Daniel Veillard5d90b6c2001-08-22 14:29:45 +0000182static xmlCatalogAllow xmlCatalogDefaultAllow = XML_CATA_ALLOW_ALL;
Daniel Veillard6990bf32001-08-23 21:17:48 +0000183static xmlCatalogPrefer xmlCatalogDefaultPrefer = XML_CATA_PREFER_PUBLIC;
Daniel Veillard75b96822001-10-11 18:59:45 +0000184
185/*
186 * Hash table containing all the trees of XML catalogs parsed by
187 * the application.
188 */
Daniel Veillard6990bf32001-08-23 21:17:48 +0000189static xmlHashTablePtr xmlCatalogXMLFiles = NULL;
Daniel Veillard75b96822001-10-11 18:59:45 +0000190
191/*
192 * The default catalog in use by the application
193 */
194static xmlCatalogPtr xmlDefaultCatalog = NULL;
195
196/*
Daniel Veillard81463942001-10-16 12:34:39 +0000197 * A mutex for modifying the shared global catalog(s)
198 * xmlDefaultCatalog tree.
199 * It also protects xmlCatalogXMLFiles
200 * The core of this readers/writer scheme is in xmlFetchXMLCatalogFile()
201 */
202static xmlRMutexPtr xmlCatalogMutex = NULL;
203
204/*
Daniel Veillard75b96822001-10-11 18:59:45 +0000205 * Whether the catalog support was initialized.
206 */
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000207static int xmlCatalogInitialized = 0;
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000208
Daniel Veillard69d2c172003-10-09 11:46:07 +0000209/************************************************************************
210 * *
211 * Catalog error handlers *
212 * *
213 ************************************************************************/
214
215/**
216 * xmlCatalogErrMemory:
217 * @extra: extra informations
218 *
219 * Handle an out of memory condition
220 */
221static void
222xmlCatalogErrMemory(const char *extra)
223{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000224 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_CATALOG,
Daniel Veillard69d2c172003-10-09 11:46:07 +0000225 XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0,
226 extra, NULL, NULL, 0, 0,
227 "Memory allocation failed : %s\n", extra);
228}
229
230/**
231 * xmlCatalogErr:
232 * @catal: the Catalog entry
233 * @node: the context node
234 * @msg: the error message
235 * @extra: extra informations
236 *
237 * Handle a catalog error
238 */
239static void
240xmlCatalogErr(xmlCatalogEntryPtr catal, xmlNodePtr node, int error,
241 const char *msg, const xmlChar *str1, const xmlChar *str2,
242 const xmlChar *str3)
243{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000244 __xmlRaiseError(NULL, NULL, NULL, catal, node, XML_FROM_CATALOG,
Daniel Veillard69d2c172003-10-09 11:46:07 +0000245 error, XML_ERR_ERROR, NULL, 0,
246 (const char *) str1, (const char *) str2,
247 (const char *) str3, 0, 0,
248 msg, str1, str2, str3);
249}
250
Daniel Veillarda7374592001-05-10 14:17:55 +0000251
252/************************************************************************
253 * *
Daniel Veillard75b96822001-10-11 18:59:45 +0000254 * Allocation and Freeing *
Daniel Veillarda7374592001-05-10 14:17:55 +0000255 * *
256 ************************************************************************/
257
Daniel Veillard75b96822001-10-11 18:59:45 +0000258/**
259 * xmlNewCatalogEntry:
260 * @type: type of entry
261 * @name: name of the entry
262 * @value: value of the entry
263 * @prefer: the PUBLIC vs. SYSTEM current preference value
William M. Brackb7b54de2004-10-06 16:38:01 +0000264 * @group: for members of a group, the group entry
Daniel Veillard75b96822001-10-11 18:59:45 +0000265 *
266 * create a new Catalog entry, this type is shared both by XML and
267 * SGML catalogs, but the acceptable types values differs.
268 *
269 * Returns the xmlCatalogEntryPtr or NULL in case of error
270 */
Daniel Veillarda7374592001-05-10 14:17:55 +0000271static xmlCatalogEntryPtr
Daniel Veillard344cee72001-08-20 00:08:40 +0000272xmlNewCatalogEntry(xmlCatalogEntryType type, const xmlChar *name,
William M. Brackb7b54de2004-10-06 16:38:01 +0000273 const xmlChar *value, const xmlChar *URL, xmlCatalogPrefer prefer,
274 xmlCatalogEntryPtr group) {
Daniel Veillarda7374592001-05-10 14:17:55 +0000275 xmlCatalogEntryPtr ret;
Daniel Veillardc8155052004-07-16 09:03:08 +0000276 xmlChar *normid = NULL;
Daniel Veillarda7374592001-05-10 14:17:55 +0000277
278 ret = (xmlCatalogEntryPtr) xmlMalloc(sizeof(xmlCatalogEntry));
279 if (ret == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +0000280 xmlCatalogErrMemory("allocating catalog entry");
Daniel Veillarda7374592001-05-10 14:17:55 +0000281 return(NULL);
282 }
Daniel Veillard344cee72001-08-20 00:08:40 +0000283 ret->next = NULL;
284 ret->parent = NULL;
285 ret->children = NULL;
Daniel Veillarda7374592001-05-10 14:17:55 +0000286 ret->type = type;
Daniel Veillardc8155052004-07-16 09:03:08 +0000287 if (type == XML_CATA_PUBLIC || type == XML_CATA_DELEGATE_PUBLIC) {
288 normid = xmlCatalogNormalizePublic(name);
289 if (normid != NULL)
290 name = (*normid != 0 ? normid : NULL);
291 }
Daniel Veillard344cee72001-08-20 00:08:40 +0000292 if (name != NULL)
293 ret->name = xmlStrdup(name);
294 else
295 ret->name = NULL;
Daniel Veillardc8155052004-07-16 09:03:08 +0000296 if (normid != NULL)
297 xmlFree(normid);
Daniel Veillard344cee72001-08-20 00:08:40 +0000298 if (value != NULL)
299 ret->value = xmlStrdup(value);
300 else
301 ret->value = NULL;
Daniel Veillardc853b322001-11-06 15:24:37 +0000302 if (URL == NULL)
303 URL = value;
304 if (URL != NULL)
305 ret->URL = xmlStrdup(URL);
306 else
307 ret->URL = NULL;
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000308 ret->prefer = prefer;
Daniel Veillard85c11fa2001-10-16 21:03:08 +0000309 ret->dealloc = 0;
Daniel Veillard5ee43b02003-08-04 00:58:46 +0000310 ret->depth = 0;
William M. Brackb7b54de2004-10-06 16:38:01 +0000311 ret->group = group;
Daniel Veillarda7374592001-05-10 14:17:55 +0000312 return(ret);
313}
314
315static void
Daniel Veillard344cee72001-08-20 00:08:40 +0000316xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret);
317
Daniel Veillard75b96822001-10-11 18:59:45 +0000318/**
319 * xmlFreeCatalogEntry:
320 * @ret: a Catalog entry
321 *
322 * Free the memory allocated to a Catalog entry
323 */
Daniel Veillard344cee72001-08-20 00:08:40 +0000324static void
Daniel Veillarda7374592001-05-10 14:17:55 +0000325xmlFreeCatalogEntry(xmlCatalogEntryPtr ret) {
326 if (ret == NULL)
327 return;
Daniel Veillard85c11fa2001-10-16 21:03:08 +0000328 /*
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000329 * Entries stored in the file hash must be deallocated
Daniel Veillard85c11fa2001-10-16 21:03:08 +0000330 * only by the file hash cleaner !
331 */
332 if (ret->dealloc == 1)
333 return;
334
335 if (xmlDebugCatalogs) {
336 if (ret->name != NULL)
337 xmlGenericError(xmlGenericErrorContext,
338 "Free catalog entry %s\n", ret->name);
339 else if (ret->value != NULL)
340 xmlGenericError(xmlGenericErrorContext,
341 "Free catalog entry %s\n", ret->value);
342 else
343 xmlGenericError(xmlGenericErrorContext,
344 "Free catalog entry\n");
345 }
346
Daniel Veillarda7374592001-05-10 14:17:55 +0000347 if (ret->name != NULL)
348 xmlFree(ret->name);
349 if (ret->value != NULL)
350 xmlFree(ret->value);
Daniel Veillardc853b322001-11-06 15:24:37 +0000351 if (ret->URL != NULL)
352 xmlFree(ret->URL);
Daniel Veillarda7374592001-05-10 14:17:55 +0000353 xmlFree(ret);
354}
355
Daniel Veillard75b96822001-10-11 18:59:45 +0000356/**
357 * xmlFreeCatalogEntryList:
358 * @ret: a Catalog entry list
359 *
360 * Free the memory allocated to a full chained list of Catalog entries
361 */
Daniel Veillard344cee72001-08-20 00:08:40 +0000362static void
363xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret) {
364 xmlCatalogEntryPtr next;
365
366 while (ret != NULL) {
367 next = ret->next;
368 xmlFreeCatalogEntry(ret);
369 ret = next;
370 }
371}
372
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000373/**
Daniel Veillard85c11fa2001-10-16 21:03:08 +0000374 * xmlFreeCatalogHashEntryList:
375 * @ret: a Catalog entry list
376 *
377 * Free the memory allocated to list of Catalog entries from the
378 * catalog file hash.
379 */
380static void
381xmlFreeCatalogHashEntryList(xmlCatalogEntryPtr catal) {
382 xmlCatalogEntryPtr children, next;
383
384 if (catal == NULL)
385 return;
386
387 children = catal->children;
388 while (children != NULL) {
389 next = children->next;
390 children->dealloc = 0;
391 children->children = NULL;
392 xmlFreeCatalogEntry(children);
393 children = next;
394 }
395 catal->dealloc = 0;
396 xmlFreeCatalogEntry(catal);
397}
398
399/**
Daniel Veillardcd21dc72001-11-04 20:03:38 +0000400 * xmlCreateNewCatalog:
Daniel Veillard75b96822001-10-11 18:59:45 +0000401 * @type: type of catalog
402 * @prefer: the PUBLIC vs. SYSTEM current preference value
403 *
404 * create a new Catalog, this type is shared both by XML and
405 * SGML catalogs, but the acceptable types values differs.
406 *
407 * Returns the xmlCatalogPtr or NULL in case of error
408 */
409static xmlCatalogPtr
Daniel Veillardcd21dc72001-11-04 20:03:38 +0000410xmlCreateNewCatalog(xmlCatalogType type, xmlCatalogPrefer prefer) {
Daniel Veillard75b96822001-10-11 18:59:45 +0000411 xmlCatalogPtr ret;
412
413 ret = (xmlCatalogPtr) xmlMalloc(sizeof(xmlCatalog));
414 if (ret == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +0000415 xmlCatalogErrMemory("allocating catalog");
Daniel Veillard75b96822001-10-11 18:59:45 +0000416 return(NULL);
417 }
418 memset(ret, 0, sizeof(xmlCatalog));
419 ret->type = type;
420 ret->catalNr = 0;
421 ret->catalMax = XML_MAX_SGML_CATA_DEPTH;
422 ret->prefer = prefer;
Daniel Veillardcd21dc72001-11-04 20:03:38 +0000423 if (ret->type == XML_SGML_CATALOG_TYPE)
424 ret->sgml = xmlHashCreate(10);
Daniel Veillard75b96822001-10-11 18:59:45 +0000425 return(ret);
426}
427
428/**
429 * xmlFreeCatalog:
Daniel Veillard06d25242004-02-25 13:01:42 +0000430 * @catal: a Catalog
Daniel Veillard75b96822001-10-11 18:59:45 +0000431 *
432 * Free the memory allocated to a Catalog
433 */
434void
435xmlFreeCatalog(xmlCatalogPtr catal) {
436 if (catal == NULL)
437 return;
438 if (catal->xml != NULL)
439 xmlFreeCatalogEntryList(catal->xml);
440 if (catal->sgml != NULL)
441 xmlHashFree(catal->sgml,
442 (xmlHashDeallocator) xmlFreeCatalogEntry);
443 xmlFree(catal);
444}
445
446/************************************************************************
447 * *
448 * Serializing Catalogs *
449 * *
450 ************************************************************************/
451
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000452#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard75b96822001-10-11 18:59:45 +0000453/**
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000454 * xmlCatalogDumpEntry:
Daniel Veillard06d25242004-02-25 13:01:42 +0000455 * @entry: the catalog entry
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000456 * @out: the file.
457 *
Daniel Veillard75b96822001-10-11 18:59:45 +0000458 * Serialize an SGML Catalog entry
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000459 */
460static void
461xmlCatalogDumpEntry(xmlCatalogEntryPtr entry, FILE *out) {
462 if ((entry == NULL) || (out == NULL))
463 return;
464 switch (entry->type) {
Daniel Veillard344cee72001-08-20 00:08:40 +0000465 case SGML_CATA_ENTITY:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000466 fprintf(out, "ENTITY "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000467 case SGML_CATA_PENTITY:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000468 fprintf(out, "ENTITY %%"); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000469 case SGML_CATA_DOCTYPE:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000470 fprintf(out, "DOCTYPE "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000471 case SGML_CATA_LINKTYPE:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000472 fprintf(out, "LINKTYPE "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000473 case SGML_CATA_NOTATION:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000474 fprintf(out, "NOTATION "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000475 case SGML_CATA_PUBLIC:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000476 fprintf(out, "PUBLIC "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000477 case SGML_CATA_SYSTEM:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000478 fprintf(out, "SYSTEM "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000479 case SGML_CATA_DELEGATE:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000480 fprintf(out, "DELEGATE "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000481 case SGML_CATA_BASE:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000482 fprintf(out, "BASE "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000483 case SGML_CATA_CATALOG:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000484 fprintf(out, "CATALOG "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000485 case SGML_CATA_DOCUMENT:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000486 fprintf(out, "DOCUMENT "); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000487 case SGML_CATA_SGMLDECL:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000488 fprintf(out, "SGMLDECL "); break;
489 default:
490 return;
491 }
492 switch (entry->type) {
Daniel Veillard344cee72001-08-20 00:08:40 +0000493 case SGML_CATA_ENTITY:
494 case SGML_CATA_PENTITY:
495 case SGML_CATA_DOCTYPE:
496 case SGML_CATA_LINKTYPE:
497 case SGML_CATA_NOTATION:
Daniel Veillard580ced82003-03-21 21:22:48 +0000498 fprintf(out, "%s", (const char *) entry->name); break;
Daniel Veillard344cee72001-08-20 00:08:40 +0000499 case SGML_CATA_PUBLIC:
500 case SGML_CATA_SYSTEM:
501 case SGML_CATA_SGMLDECL:
502 case SGML_CATA_DOCUMENT:
503 case SGML_CATA_CATALOG:
504 case SGML_CATA_BASE:
505 case SGML_CATA_DELEGATE:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000506 fprintf(out, "\"%s\"", entry->name); break;
507 default:
508 break;
509 }
510 switch (entry->type) {
Daniel Veillard344cee72001-08-20 00:08:40 +0000511 case SGML_CATA_ENTITY:
512 case SGML_CATA_PENTITY:
513 case SGML_CATA_DOCTYPE:
514 case SGML_CATA_LINKTYPE:
515 case SGML_CATA_NOTATION:
516 case SGML_CATA_PUBLIC:
517 case SGML_CATA_SYSTEM:
518 case SGML_CATA_DELEGATE:
Daniel Veillard7d6fd212001-05-10 15:34:11 +0000519 fprintf(out, " \"%s\"", entry->value); break;
520 default:
521 break;
522 }
523 fprintf(out, "\n");
524}
525
William M. Brackb7b54de2004-10-06 16:38:01 +0000526/**
527 * xmlDumpXMLCatalogNode:
528 * @catal: top catalog entry
529 * @catalog: pointer to the xml tree
530 * @doc: the containing document
531 * @ns: the current namespace
532 * @cgroup: group node for group members
533 *
534 * Serializes a Catalog entry, called by xmlDumpXMLCatalog and recursively
535 * for group entries
536 */
537static void xmlDumpXMLCatalogNode(xmlCatalogEntryPtr catal, xmlNodePtr catalog,
538 xmlDocPtr doc, xmlNsPtr ns, xmlCatalogEntryPtr cgroup) {
539 xmlNodePtr node;
540 xmlCatalogEntryPtr cur;
541 /*
542 * add all the catalog entries
543 */
544 cur = catal;
545 while (cur != NULL) {
546 if (cur->group == cgroup) {
547 switch (cur->type) {
548 case XML_CATA_REMOVED:
549 break;
550 case XML_CATA_BROKEN_CATALOG:
551 case XML_CATA_CATALOG:
552 if (cur == catal) {
553 cur = cur->children;
554 continue;
555 }
556 break;
557 case XML_CATA_NEXT_CATALOG:
558 node = xmlNewDocNode(doc, ns, BAD_CAST "nextCatalog", NULL);
559 xmlSetProp(node, BAD_CAST "catalog", cur->value);
560 xmlAddChild(catalog, node);
561 break;
562 case XML_CATA_NONE:
563 break;
564 case XML_CATA_GROUP:
565 node = xmlNewDocNode(doc, ns, BAD_CAST "group", NULL);
566 xmlSetProp(node, BAD_CAST "id", cur->name);
William M. Brack6218b312004-10-06 17:52:32 +0000567 if (cur->value != NULL) {
568 xmlNsPtr xns;
569 xns = xmlSearchNsByHref(doc, node, XML_XML_NAMESPACE);
570 if (xns != NULL)
571 xmlSetNsProp(node, xns, BAD_CAST "base",
572 cur->value);
573 }
William M. Brackb7b54de2004-10-06 16:38:01 +0000574 switch (cur->prefer) {
575 case XML_CATA_PREFER_NONE:
576 break;
577 case XML_CATA_PREFER_PUBLIC:
578 xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "public");
579 break;
580 case XML_CATA_PREFER_SYSTEM:
581 xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "system");
582 break;
583 }
584 xmlDumpXMLCatalogNode(cur->next, node, doc, ns, cur);
585 xmlAddChild(catalog, node);
586 break;
587 case XML_CATA_PUBLIC:
588 node = xmlNewDocNode(doc, ns, BAD_CAST "public", NULL);
589 xmlSetProp(node, BAD_CAST "publicId", cur->name);
590 xmlSetProp(node, BAD_CAST "uri", cur->value);
591 xmlAddChild(catalog, node);
592 break;
593 case XML_CATA_SYSTEM:
594 node = xmlNewDocNode(doc, ns, BAD_CAST "system", NULL);
595 xmlSetProp(node, BAD_CAST "systemId", cur->name);
596 xmlSetProp(node, BAD_CAST "uri", cur->value);
597 xmlAddChild(catalog, node);
598 break;
599 case XML_CATA_REWRITE_SYSTEM:
600 node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteSystem", NULL);
601 xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
602 xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
603 xmlAddChild(catalog, node);
604 break;
605 case XML_CATA_DELEGATE_PUBLIC:
606 node = xmlNewDocNode(doc, ns, BAD_CAST "delegatePublic", NULL);
607 xmlSetProp(node, BAD_CAST "publicIdStartString", cur->name);
608 xmlSetProp(node, BAD_CAST "catalog", cur->value);
609 xmlAddChild(catalog, node);
610 break;
611 case XML_CATA_DELEGATE_SYSTEM:
612 node = xmlNewDocNode(doc, ns, BAD_CAST "delegateSystem", NULL);
613 xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
614 xmlSetProp(node, BAD_CAST "catalog", cur->value);
615 xmlAddChild(catalog, node);
616 break;
617 case XML_CATA_URI:
618 node = xmlNewDocNode(doc, ns, BAD_CAST "uri", NULL);
619 xmlSetProp(node, BAD_CAST "name", cur->name);
620 xmlSetProp(node, BAD_CAST "uri", cur->value);
621 xmlAddChild(catalog, node);
622 break;
623 case XML_CATA_REWRITE_URI:
624 node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteURI", NULL);
625 xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
626 xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
627 xmlAddChild(catalog, node);
628 break;
629 case XML_CATA_DELEGATE_URI:
630 node = xmlNewDocNode(doc, ns, BAD_CAST "delegateURI", NULL);
631 xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
632 xmlSetProp(node, BAD_CAST "catalog", cur->value);
633 xmlAddChild(catalog, node);
634 break;
635 case SGML_CATA_SYSTEM:
636 case SGML_CATA_PUBLIC:
637 case SGML_CATA_ENTITY:
638 case SGML_CATA_PENTITY:
639 case SGML_CATA_DOCTYPE:
640 case SGML_CATA_LINKTYPE:
641 case SGML_CATA_NOTATION:
642 case SGML_CATA_DELEGATE:
643 case SGML_CATA_BASE:
644 case SGML_CATA_CATALOG:
645 case SGML_CATA_DOCUMENT:
646 case SGML_CATA_SGMLDECL:
647 break;
648 }
649 }
650 cur = cur->next;
651 }
652}
653
Daniel Veillard75b96822001-10-11 18:59:45 +0000654static int
655xmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) {
656 int ret;
657 xmlDocPtr doc;
658 xmlNsPtr ns;
659 xmlDtdPtr dtd;
William M. Brackb7b54de2004-10-06 16:38:01 +0000660 xmlNodePtr catalog;
Daniel Veillard75b96822001-10-11 18:59:45 +0000661 xmlOutputBufferPtr buf;
Daniel Veillard75b96822001-10-11 18:59:45 +0000662
663 /*
664 * Rebuild a catalog
665 */
666 doc = xmlNewDoc(NULL);
667 if (doc == NULL)
668 return(-1);
669 dtd = xmlNewDtd(doc, BAD_CAST "catalog",
670 BAD_CAST "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN",
671BAD_CAST "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd");
672
673 xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd);
674
675 ns = xmlNewNs(NULL, XML_CATALOGS_NAMESPACE, NULL);
676 if (ns == NULL) {
677 xmlFreeDoc(doc);
678 return(-1);
679 }
680 catalog = xmlNewDocNode(doc, ns, BAD_CAST "catalog", NULL);
681 if (catalog == NULL) {
682 xmlFreeNs(ns);
683 xmlFreeDoc(doc);
684 return(-1);
685 }
686 catalog->nsDef = ns;
687 xmlAddChild((xmlNodePtr) doc, catalog);
688
William M. Brackb7b54de2004-10-06 16:38:01 +0000689 xmlDumpXMLCatalogNode(catal, catalog, doc, ns, NULL);
690
Daniel Veillard75b96822001-10-11 18:59:45 +0000691 /*
692 * reserialize it
693 */
694 buf = xmlOutputBufferCreateFile(out, NULL);
695 if (buf == NULL) {
696 xmlFreeDoc(doc);
697 return(-1);
698 }
699 ret = xmlSaveFormatFileTo(buf, doc, NULL, 1);
700
701 /*
702 * Free it
703 */
704 xmlFreeDoc(doc);
705
706 return(ret);
707}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000708#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard75b96822001-10-11 18:59:45 +0000709
710/************************************************************************
711 * *
712 * Converting SGML Catalogs to XML *
713 * *
714 ************************************************************************/
715
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000716/**
717 * xmlCatalogConvertEntry:
718 * @entry: the entry
Daniel Veillard75b96822001-10-11 18:59:45 +0000719 * @catal: pointer to the catalog being converted
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000720 *
Daniel Veillard75b96822001-10-11 18:59:45 +0000721 * Convert one entry from the catalog
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000722 */
723static void
Daniel Veillard75b96822001-10-11 18:59:45 +0000724xmlCatalogConvertEntry(xmlCatalogEntryPtr entry, xmlCatalogPtr catal) {
725 if ((entry == NULL) || (catal == NULL) || (catal->sgml == NULL) ||
726 (catal->xml == NULL))
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000727 return;
728 switch (entry->type) {
729 case SGML_CATA_ENTITY:
730 entry->type = XML_CATA_PUBLIC;
731 break;
732 case SGML_CATA_PENTITY:
733 entry->type = XML_CATA_PUBLIC;
734 break;
735 case SGML_CATA_DOCTYPE:
736 entry->type = XML_CATA_PUBLIC;
737 break;
738 case SGML_CATA_LINKTYPE:
739 entry->type = XML_CATA_PUBLIC;
740 break;
741 case SGML_CATA_NOTATION:
742 entry->type = XML_CATA_PUBLIC;
743 break;
744 case SGML_CATA_PUBLIC:
745 entry->type = XML_CATA_PUBLIC;
746 break;
747 case SGML_CATA_SYSTEM:
748 entry->type = XML_CATA_SYSTEM;
749 break;
750 case SGML_CATA_DELEGATE:
751 entry->type = XML_CATA_DELEGATE_PUBLIC;
752 break;
753 case SGML_CATA_CATALOG:
754 entry->type = XML_CATA_CATALOG;
755 break;
756 default:
Daniel Veillard75b96822001-10-11 18:59:45 +0000757 xmlHashRemoveEntry(catal->sgml, entry->name,
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000758 (xmlHashDeallocator) xmlFreeCatalogEntry);
759 return;
760 }
761 /*
762 * Conversion successful, remove from the SGML catalog
763 * and add it to the default XML one
764 */
Daniel Veillard75b96822001-10-11 18:59:45 +0000765 xmlHashRemoveEntry(catal->sgml, entry->name, NULL);
766 entry->parent = catal->xml;
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000767 entry->next = NULL;
Daniel Veillard75b96822001-10-11 18:59:45 +0000768 if (catal->xml->children == NULL)
769 catal->xml->children = entry;
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000770 else {
771 xmlCatalogEntryPtr prev;
772
Daniel Veillard75b96822001-10-11 18:59:45 +0000773 prev = catal->xml->children;
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000774 while (prev->next != NULL)
775 prev = prev->next;
776 prev->next = entry;
777 }
Daniel Veillard75b96822001-10-11 18:59:45 +0000778}
779
780/**
781 * xmlConvertSGMLCatalog:
782 * @catal: the catalog
783 *
784 * Convert all the SGML catalog entries as XML ones
785 *
786 * Returns the number of entries converted if successful, -1 otherwise
787 */
788int
789xmlConvertSGMLCatalog(xmlCatalogPtr catal) {
790
791 if ((catal == NULL) || (catal->type != XML_SGML_CATALOG_TYPE))
792 return(-1);
793
794 if (xmlDebugCatalogs) {
795 xmlGenericError(xmlGenericErrorContext,
796 "Converting SGML catalog to XML\n");
797 }
798 xmlHashScan(catal->sgml,
799 (xmlHashScanner) xmlCatalogConvertEntry,
800 &catal);
801 return(0);
Daniel Veillard6c5f9d12001-08-25 13:33:14 +0000802}
803
Daniel Veillarda7374592001-05-10 14:17:55 +0000804/************************************************************************
805 * *
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000806 * Helper function *
807 * *
808 ************************************************************************/
809
810/**
811 * xmlCatalogUnWrapURN:
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000812 * @urn: an "urn:publicid:" to unwrap
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000813 *
814 * Expand the URN into the equivalent Public Identifier
815 *
816 * Returns the new identifier or NULL, the string must be deallocated
817 * by the caller.
818 */
819static xmlChar *
820xmlCatalogUnWrapURN(const xmlChar *urn) {
821 xmlChar result[2000];
822 unsigned int i = 0;
823
824 if (xmlStrncmp(urn, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1))
825 return(NULL);
826 urn += sizeof(XML_URN_PUBID) - 1;
827
828 while (*urn != 0) {
Daniel Veillard770075b2004-02-25 10:44:30 +0000829 if (i > sizeof(result) - 4)
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000830 break;
831 if (*urn == '+') {
832 result[i++] = ' ';
833 urn++;
834 } else if (*urn == ':') {
835 result[i++] = '/';
836 result[i++] = '/';
837 urn++;
838 } else if (*urn == ';') {
839 result[i++] = ':';
840 result[i++] = ':';
841 urn++;
842 } else if (*urn == '%') {
Daniel Veillard770075b2004-02-25 10:44:30 +0000843 if ((urn[1] == '2') && (urn[2] == 'B'))
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000844 result[i++] = '+';
Daniel Veillard770075b2004-02-25 10:44:30 +0000845 else if ((urn[1] == '3') && (urn[2] == 'A'))
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000846 result[i++] = ':';
Daniel Veillard770075b2004-02-25 10:44:30 +0000847 else if ((urn[1] == '2') && (urn[2] == 'F'))
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000848 result[i++] = '/';
Daniel Veillard770075b2004-02-25 10:44:30 +0000849 else if ((urn[1] == '3') && (urn[2] == 'B'))
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000850 result[i++] = ';';
Daniel Veillard770075b2004-02-25 10:44:30 +0000851 else if ((urn[1] == '2') && (urn[2] == '7'))
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000852 result[i++] = '\'';
Daniel Veillard770075b2004-02-25 10:44:30 +0000853 else if ((urn[1] == '3') && (urn[2] == 'F'))
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] == '3'))
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000856 result[i++] = '#';
Daniel Veillard770075b2004-02-25 10:44:30 +0000857 else if ((urn[1] == '2') && (urn[2] == '5'))
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000858 result[i++] = '%';
859 else {
860 result[i++] = *urn;
861 urn++;
862 continue;
863 }
864 urn += 3;
865 } else {
866 result[i++] = *urn;
867 urn++;
868 }
869 }
870 result[i] = 0;
871
872 return(xmlStrdup(result));
873}
874
Daniel Veillard9f7b84b2001-08-23 15:31:19 +0000875/**
876 * xmlParseCatalogFile:
877 * @filename: the filename
878 *
879 * parse an XML file and build a tree. It's like xmlParseFile()
880 * except it bypass all catalog lookups.
881 *
882 * Returns the resulting document tree or NULL in case of error
883 */
884
885xmlDocPtr
886xmlParseCatalogFile(const char *filename) {
887 xmlDocPtr ret;
888 xmlParserCtxtPtr ctxt;
889 char *directory = NULL;
890 xmlParserInputPtr inputStream;
891 xmlParserInputBufferPtr buf;
892
893 ctxt = xmlNewParserCtxt();
894 if (ctxt == NULL) {
Daniel Veillardd0cf7f62004-11-09 16:17:02 +0000895#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard9f7b84b2001-08-23 15:31:19 +0000896 if (xmlDefaultSAXHandler.error != NULL) {
897 xmlDefaultSAXHandler.error(NULL, "out of memory\n");
898 }
Daniel Veillardd0cf7f62004-11-09 16:17:02 +0000899#endif
Daniel Veillard9f7b84b2001-08-23 15:31:19 +0000900 return(NULL);
901 }
902
903 buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
904 if (buf == NULL) {
905 xmlFreeParserCtxt(ctxt);
906 return(NULL);
907 }
908
909 inputStream = xmlNewInputStream(ctxt);
910 if (inputStream == NULL) {
911 xmlFreeParserCtxt(ctxt);
912 return(NULL);
913 }
914
Daniel Veillardc3ca5ba2003-05-09 22:26:28 +0000915 inputStream->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
Daniel Veillard9f7b84b2001-08-23 15:31:19 +0000916 inputStream->buf = buf;
Daniel Veillard61551a12012-07-16 16:28:47 +0800917 xmlBufResetInput(buf->buffer, inputStream);
Daniel Veillard9f7b84b2001-08-23 15:31:19 +0000918
919 inputPush(ctxt, inputStream);
920 if ((ctxt->directory == NULL) && (directory == NULL))
921 directory = xmlParserGetDirectory(filename);
922 if ((ctxt->directory == NULL) && (directory != NULL))
923 ctxt->directory = directory;
Daniel Veillard6990bf32001-08-23 21:17:48 +0000924 ctxt->valid = 0;
925 ctxt->validate = 0;
926 ctxt->loadsubset = 0;
927 ctxt->pedantic = 0;
Daniel Veillard03a53c32004-10-26 16:06:51 +0000928 ctxt->dictNames = 1;
Daniel Veillard9f7b84b2001-08-23 15:31:19 +0000929
930 xmlParseDocument(ctxt);
931
932 if (ctxt->wellFormed)
933 ret = ctxt->myDoc;
934 else {
935 ret = NULL;
936 xmlFreeDoc(ctxt->myDoc);
937 ctxt->myDoc = NULL;
938 }
939 xmlFreeParserCtxt(ctxt);
940
941 return(ret);
942}
943
Daniel Veillard75b96822001-10-11 18:59:45 +0000944/**
945 * xmlLoadFileContent:
946 * @filename: a file path
947 *
948 * Load a file content into memory.
949 *
950 * Returns a pointer to the 0 terminated string or NULL in case of error
951 */
952static xmlChar *
953xmlLoadFileContent(const char *filename)
954{
955#ifdef HAVE_STAT
956 int fd;
957#else
958 FILE *fd;
959#endif
960 int len;
961 long size;
962
963#ifdef HAVE_STAT
964 struct stat info;
965#endif
966 xmlChar *content;
967
968 if (filename == NULL)
969 return (NULL);
970
971#ifdef HAVE_STAT
972 if (stat(filename, &info) < 0)
973 return (NULL);
974#endif
975
976#ifdef HAVE_STAT
Daniel Veillard5aad8322002-12-11 15:59:44 +0000977 if ((fd = open(filename, O_RDONLY)) < 0)
Daniel Veillard75b96822001-10-11 18:59:45 +0000978#else
Daniel Veillard5aad8322002-12-11 15:59:44 +0000979 if ((fd = fopen(filename, "rb")) == NULL)
Daniel Veillard75b96822001-10-11 18:59:45 +0000980#endif
Daniel Veillard5aad8322002-12-11 15:59:44 +0000981 {
Daniel Veillard75b96822001-10-11 18:59:45 +0000982 return (NULL);
983 }
984#ifdef HAVE_STAT
985 size = info.st_size;
986#else
987 if (fseek(fd, 0, SEEK_END) || (size = ftell(fd)) == EOF || fseek(fd, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */
988 fclose(fd);
989 return (NULL);
990 }
991#endif
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000992 content = xmlMallocAtomic(size + 10);
Daniel Veillard75b96822001-10-11 18:59:45 +0000993 if (content == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +0000994 xmlCatalogErrMemory("allocating catalog data");
Daniel Veillard75b96822001-10-11 18:59:45 +0000995 return (NULL);
996 }
997#ifdef HAVE_STAT
998 len = read(fd, content, size);
Carlo Braminic43ac662010-10-14 14:27:54 +0200999 close(fd);
Daniel Veillard75b96822001-10-11 18:59:45 +00001000#else
1001 len = fread(content, 1, size, fd);
Carlo Braminic43ac662010-10-14 14:27:54 +02001002 fclose(fd);
Daniel Veillard75b96822001-10-11 18:59:45 +00001003#endif
1004 if (len < 0) {
1005 xmlFree(content);
1006 return (NULL);
1007 }
Daniel Veillard75b96822001-10-11 18:59:45 +00001008 content[len] = 0;
1009
1010 return(content);
1011}
1012
Daniel Veillardc8155052004-07-16 09:03:08 +00001013/**
1014 * xmlCatalogNormalizePublic:
1015 * @pubID: the public ID string
1016 *
1017 * Normalizes the Public Identifier
1018 *
1019 * Implements 6.2. Public Identifier Normalization
1020 * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1021 *
1022 * Returns the new string or NULL, the string must be deallocated
1023 * by the caller.
1024 */
1025static xmlChar *
1026xmlCatalogNormalizePublic(const xmlChar *pubID)
1027{
1028 int ok = 1;
1029 int white;
1030 const xmlChar *p;
1031 xmlChar *ret;
1032 xmlChar *q;
1033
1034 if (pubID == NULL)
1035 return(NULL);
1036
1037 white = 1;
1038 for (p = pubID;*p != 0 && ok;p++) {
1039 if (!xmlIsBlank_ch(*p))
1040 white = 0;
1041 else if (*p == 0x20 && !white)
1042 white = 1;
1043 else
1044 ok = 0;
1045 }
1046 if (ok && !white) /* is normalized */
1047 return(NULL);
1048
1049 ret = xmlStrdup(pubID);
1050 q = ret;
1051 white = 0;
1052 for (p = pubID;*p != 0;p++) {
1053 if (xmlIsBlank_ch(*p)) {
1054 if (q != ret)
1055 white = 1;
1056 } else {
1057 if (white) {
1058 *(q++) = 0x20;
1059 white = 0;
1060 }
1061 *(q++) = *p;
1062 }
1063 }
1064 *q = 0;
1065 return(ret);
1066}
1067
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001068/************************************************************************
1069 * *
Daniel Veillard344cee72001-08-20 00:08:40 +00001070 * The XML Catalog parser *
1071 * *
1072 ************************************************************************/
1073
1074static xmlCatalogEntryPtr
1075xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename);
Daniel Veillard344cee72001-08-20 00:08:40 +00001076static void
1077xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
William M. Brackb7b54de2004-10-06 16:38:01 +00001078 xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup);
Daniel Veillardcda96922001-08-21 10:56:31 +00001079static xmlChar *
1080xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1081 const xmlChar *sysID);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001082static xmlChar *
1083xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI);
1084
Daniel Veillard344cee72001-08-20 00:08:40 +00001085
Daniel Veillard75b96822001-10-11 18:59:45 +00001086/**
1087 * xmlGetXMLCatalogEntryType:
1088 * @name: the name
1089 *
1090 * lookup the internal type associated to an XML catalog entry name
1091 *
Daniel Veillard06d25242004-02-25 13:01:42 +00001092 * Returns the type associated with that name
Daniel Veillard75b96822001-10-11 18:59:45 +00001093 */
Daniel Veillard344cee72001-08-20 00:08:40 +00001094static xmlCatalogEntryType
1095xmlGetXMLCatalogEntryType(const xmlChar *name) {
1096 xmlCatalogEntryType type = XML_CATA_NONE;
1097 if (xmlStrEqual(name, (const xmlChar *) "system"))
1098 type = XML_CATA_SYSTEM;
1099 else if (xmlStrEqual(name, (const xmlChar *) "public"))
1100 type = XML_CATA_PUBLIC;
1101 else if (xmlStrEqual(name, (const xmlChar *) "rewriteSystem"))
1102 type = XML_CATA_REWRITE_SYSTEM;
1103 else if (xmlStrEqual(name, (const xmlChar *) "delegatePublic"))
1104 type = XML_CATA_DELEGATE_PUBLIC;
1105 else if (xmlStrEqual(name, (const xmlChar *) "delegateSystem"))
1106 type = XML_CATA_DELEGATE_SYSTEM;
1107 else if (xmlStrEqual(name, (const xmlChar *) "uri"))
1108 type = XML_CATA_URI;
1109 else if (xmlStrEqual(name, (const xmlChar *) "rewriteURI"))
1110 type = XML_CATA_REWRITE_URI;
1111 else if (xmlStrEqual(name, (const xmlChar *) "delegateURI"))
1112 type = XML_CATA_DELEGATE_URI;
1113 else if (xmlStrEqual(name, (const xmlChar *) "nextCatalog"))
1114 type = XML_CATA_NEXT_CATALOG;
1115 else if (xmlStrEqual(name, (const xmlChar *) "catalog"))
1116 type = XML_CATA_CATALOG;
1117 return(type);
1118}
1119
Daniel Veillard75b96822001-10-11 18:59:45 +00001120/**
1121 * xmlParseXMLCatalogOneNode:
1122 * @cur: the XML node
1123 * @type: the type of Catalog entry
1124 * @name: the name of the node
1125 * @attrName: the attribute holding the value
1126 * @uriAttrName: the attribute holding the URI-Reference
1127 * @prefer: the PUBLIC vs. SYSTEM current preference value
William M. Brackb7b54de2004-10-06 16:38:01 +00001128 * @cgroup: the group which includes this node
Daniel Veillard75b96822001-10-11 18:59:45 +00001129 *
1130 * Finishes the examination of an XML tree node of a catalog and build
1131 * a Catalog entry from it.
1132 *
1133 * Returns the new Catalog entry node or NULL in case of error.
1134 */
Daniel Veillard344cee72001-08-20 00:08:40 +00001135static xmlCatalogEntryPtr
1136xmlParseXMLCatalogOneNode(xmlNodePtr cur, xmlCatalogEntryType type,
1137 const xmlChar *name, const xmlChar *attrName,
William M. Brackb7b54de2004-10-06 16:38:01 +00001138 const xmlChar *uriAttrName, xmlCatalogPrefer prefer,
1139 xmlCatalogEntryPtr cgroup) {
Daniel Veillard344cee72001-08-20 00:08:40 +00001140 int ok = 1;
1141 xmlChar *uriValue;
1142 xmlChar *nameValue = NULL;
1143 xmlChar *base = NULL;
1144 xmlChar *URL = NULL;
1145 xmlCatalogEntryPtr ret = NULL;
1146
1147 if (attrName != NULL) {
1148 nameValue = xmlGetProp(cur, attrName);
1149 if (nameValue == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001150 xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
1151 "%s entry lacks '%s'\n", name, attrName, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001152 ok = 0;
1153 }
1154 }
1155 uriValue = xmlGetProp(cur, uriAttrName);
1156 if (uriValue == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001157 xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
1158 "%s entry lacks '%s'\n", name, uriAttrName, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001159 ok = 0;
1160 }
1161 if (!ok) {
1162 if (nameValue != NULL)
1163 xmlFree(nameValue);
1164 if (uriValue != NULL)
1165 xmlFree(uriValue);
1166 return(NULL);
1167 }
1168
1169 base = xmlNodeGetBase(cur->doc, cur);
1170 URL = xmlBuildURI(uriValue, base);
1171 if (URL != NULL) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001172 if (xmlDebugCatalogs > 1) {
Daniel Veillard344cee72001-08-20 00:08:40 +00001173 if (nameValue != NULL)
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001174 xmlGenericError(xmlGenericErrorContext,
1175 "Found %s: '%s' '%s'\n", name, nameValue, URL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001176 else
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001177 xmlGenericError(xmlGenericErrorContext,
1178 "Found %s: '%s'\n", name, URL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001179 }
William M. Brackb7b54de2004-10-06 16:38:01 +00001180 ret = xmlNewCatalogEntry(type, nameValue, uriValue, URL, prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001181 } else {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001182 xmlCatalogErr(ret, cur, XML_CATALOG_ENTRY_BROKEN,
Daniel Veillard344cee72001-08-20 00:08:40 +00001183 "%s entry '%s' broken ?: %s\n", name, uriAttrName, uriValue);
1184 }
1185 if (nameValue != NULL)
1186 xmlFree(nameValue);
1187 if (uriValue != NULL)
1188 xmlFree(uriValue);
1189 if (base != NULL)
1190 xmlFree(base);
1191 if (URL != NULL)
1192 xmlFree(URL);
1193 return(ret);
1194}
1195
Daniel Veillard75b96822001-10-11 18:59:45 +00001196/**
1197 * xmlParseXMLCatalogNode:
1198 * @cur: the XML node
1199 * @prefer: the PUBLIC vs. SYSTEM current preference value
1200 * @parent: the parent Catalog entry
William M. Brackb7b54de2004-10-06 16:38:01 +00001201 * @cgroup: the group which includes this node
Daniel Veillard75b96822001-10-11 18:59:45 +00001202 *
1203 * Examines an XML tree node of a catalog and build
1204 * a Catalog entry from it adding it to its parent. The examination can
1205 * be recursive.
1206 */
Daniel Veillard344cee72001-08-20 00:08:40 +00001207static void
1208xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer,
William M. Brackb7b54de2004-10-06 16:38:01 +00001209 xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup)
Daniel Veillard344cee72001-08-20 00:08:40 +00001210{
Daniel Veillard344cee72001-08-20 00:08:40 +00001211 xmlChar *base = NULL;
1212 xmlCatalogEntryPtr entry = NULL;
1213
1214 if (cur == NULL)
1215 return;
1216 if (xmlStrEqual(cur->name, BAD_CAST "group")) {
1217 xmlChar *prop;
William M. Brackb7b54de2004-10-06 16:38:01 +00001218 xmlCatalogPrefer pref = XML_CATA_PREFER_NONE;
Daniel Veillard344cee72001-08-20 00:08:40 +00001219
1220 prop = xmlGetProp(cur, BAD_CAST "prefer");
1221 if (prop != NULL) {
1222 if (xmlStrEqual(prop, BAD_CAST "system")) {
1223 prefer = XML_CATA_PREFER_SYSTEM;
1224 } else if (xmlStrEqual(prop, BAD_CAST "public")) {
1225 prefer = XML_CATA_PREFER_PUBLIC;
1226 } else {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001227 xmlCatalogErr(parent, cur, XML_CATALOG_PREFER_VALUE,
1228 "Invalid value for prefer: '%s'\n",
1229 prop, NULL, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001230 }
1231 xmlFree(prop);
William M. Brackb7b54de2004-10-06 16:38:01 +00001232 pref = prefer;
Daniel Veillard344cee72001-08-20 00:08:40 +00001233 }
William M. Brackb7b54de2004-10-06 16:38:01 +00001234 prop = xmlGetProp(cur, BAD_CAST "id");
1235 base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE);
1236 entry = xmlNewCatalogEntry(XML_CATA_GROUP, prop, base, NULL, pref, cgroup);
William M. Brack181a1ca2004-10-06 18:00:29 +00001237 xmlFree(prop);
Daniel Veillard344cee72001-08-20 00:08:40 +00001238 } else if (xmlStrEqual(cur->name, BAD_CAST "public")) {
1239 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_PUBLIC,
William M. Brackb7b54de2004-10-06 16:38:01 +00001240 BAD_CAST "public", BAD_CAST "publicId", BAD_CAST "uri", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001241 } else if (xmlStrEqual(cur->name, BAD_CAST "system")) {
1242 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_SYSTEM,
William M. Brackb7b54de2004-10-06 16:38:01 +00001243 BAD_CAST "system", BAD_CAST "systemId", BAD_CAST "uri", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001244 } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteSystem")) {
1245 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_SYSTEM,
1246 BAD_CAST "rewriteSystem", BAD_CAST "systemIdStartString",
William M. Brackb7b54de2004-10-06 16:38:01 +00001247 BAD_CAST "rewritePrefix", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001248 } else if (xmlStrEqual(cur->name, BAD_CAST "delegatePublic")) {
1249 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_PUBLIC,
1250 BAD_CAST "delegatePublic", BAD_CAST "publicIdStartString",
William M. Brackb7b54de2004-10-06 16:38:01 +00001251 BAD_CAST "catalog", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001252 } else if (xmlStrEqual(cur->name, BAD_CAST "delegateSystem")) {
1253 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_SYSTEM,
1254 BAD_CAST "delegateSystem", BAD_CAST "systemIdStartString",
William M. Brackb7b54de2004-10-06 16:38:01 +00001255 BAD_CAST "catalog", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001256 } else if (xmlStrEqual(cur->name, BAD_CAST "uri")) {
1257 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_URI,
1258 BAD_CAST "uri", BAD_CAST "name",
William M. Brackb7b54de2004-10-06 16:38:01 +00001259 BAD_CAST "uri", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001260 } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteURI")) {
1261 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_URI,
1262 BAD_CAST "rewriteURI", BAD_CAST "uriStartString",
William M. Brackb7b54de2004-10-06 16:38:01 +00001263 BAD_CAST "rewritePrefix", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001264 } else if (xmlStrEqual(cur->name, BAD_CAST "delegateURI")) {
1265 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_URI,
1266 BAD_CAST "delegateURI", BAD_CAST "uriStartString",
William M. Brackb7b54de2004-10-06 16:38:01 +00001267 BAD_CAST "catalog", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001268 } else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) {
1269 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG,
1270 BAD_CAST "nextCatalog", NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00001271 BAD_CAST "catalog", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001272 }
William M. Brackb031cef2004-11-05 16:34:22 +00001273 if (entry != NULL) {
1274 if (parent != NULL) {
1275 entry->parent = parent;
1276 if (parent->children == NULL)
1277 parent->children = entry;
1278 else {
1279 xmlCatalogEntryPtr prev;
Daniel Veillard344cee72001-08-20 00:08:40 +00001280
William M. Brackb031cef2004-11-05 16:34:22 +00001281 prev = parent->children;
1282 while (prev->next != NULL)
1283 prev = prev->next;
1284 prev->next = entry;
1285 }
Daniel Veillard344cee72001-08-20 00:08:40 +00001286 }
William M. Brackb031cef2004-11-05 16:34:22 +00001287 if (entry->type == XML_CATA_GROUP) {
1288 /*
1289 * Recurse to propagate prefer to the subtree
1290 * (xml:base handling is automated)
1291 */
1292 xmlParseXMLCatalogNodeList(cur->children, prefer, parent, entry);
1293 }
William M. Brackb7b54de2004-10-06 16:38:01 +00001294 }
Daniel Veillard344cee72001-08-20 00:08:40 +00001295 if (base != NULL)
1296 xmlFree(base);
Daniel Veillard344cee72001-08-20 00:08:40 +00001297}
1298
Daniel Veillard75b96822001-10-11 18:59:45 +00001299/**
1300 * xmlParseXMLCatalogNodeList:
1301 * @cur: the XML node list of siblings
1302 * @prefer: the PUBLIC vs. SYSTEM current preference value
1303 * @parent: the parent Catalog entry
William M. Brackb7b54de2004-10-06 16:38:01 +00001304 * @cgroup: the group which includes this list
Daniel Veillard75b96822001-10-11 18:59:45 +00001305 *
1306 * Examines a list of XML sibling nodes of a catalog and build
1307 * a list of Catalog entry from it adding it to the parent.
1308 * The examination will recurse to examine node subtrees.
1309 */
Daniel Veillard344cee72001-08-20 00:08:40 +00001310static void
1311xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
William M. Brackb7b54de2004-10-06 16:38:01 +00001312 xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup) {
Daniel Veillard344cee72001-08-20 00:08:40 +00001313 while (cur != NULL) {
1314 if ((cur->ns != NULL) && (cur->ns->href != NULL) &&
1315 (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) {
William M. Brackb7b54de2004-10-06 16:38:01 +00001316 xmlParseXMLCatalogNode(cur, prefer, parent, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001317 }
1318 cur = cur->next;
1319 }
1320 /* TODO: sort the list according to REWRITE lengths and prefer value */
1321}
1322
Daniel Veillard75b96822001-10-11 18:59:45 +00001323/**
Daniel Veillard75b96822001-10-11 18:59:45 +00001324 * xmlParseXMLCatalogFile:
1325 * @prefer: the PUBLIC vs. SYSTEM current preference value
1326 * @filename: the filename for the catalog
1327 *
1328 * Parses the catalog file to extract the XML tree and then analyze the
1329 * tree to build a list of Catalog entries corresponding to this catalog
1330 *
1331 * Returns the resulting Catalog entries list
1332 */
Daniel Veillard344cee72001-08-20 00:08:40 +00001333static xmlCatalogEntryPtr
1334xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename) {
1335 xmlDocPtr doc;
1336 xmlNodePtr cur;
1337 xmlChar *prop;
1338 xmlCatalogEntryPtr parent = NULL;
1339
1340 if (filename == NULL)
1341 return(NULL);
1342
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00001343 doc = xmlParseCatalogFile((const char *) filename);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001344 if (doc == NULL) {
1345 if (xmlDebugCatalogs)
1346 xmlGenericError(xmlGenericErrorContext,
1347 "Failed to parse catalog %s\n", filename);
Daniel Veillard344cee72001-08-20 00:08:40 +00001348 return(NULL);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001349 }
1350
1351 if (xmlDebugCatalogs)
1352 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard3c01b1d2001-10-17 15:58:35 +00001353 "%d Parsing catalog %s\n", xmlGetThreadId(), filename);
Daniel Veillard344cee72001-08-20 00:08:40 +00001354
1355 cur = xmlDocGetRootElement(doc);
1356 if ((cur != NULL) && (xmlStrEqual(cur->name, BAD_CAST "catalog")) &&
1357 (cur->ns != NULL) && (cur->ns->href != NULL) &&
1358 (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) {
1359
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001360 parent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00001361 (const xmlChar *)filename, NULL, prefer, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001362 if (parent == NULL) {
1363 xmlFreeDoc(doc);
1364 return(NULL);
1365 }
1366
1367 prop = xmlGetProp(cur, BAD_CAST "prefer");
1368 if (prop != NULL) {
1369 if (xmlStrEqual(prop, BAD_CAST "system")) {
1370 prefer = XML_CATA_PREFER_SYSTEM;
1371 } else if (xmlStrEqual(prop, BAD_CAST "public")) {
1372 prefer = XML_CATA_PREFER_PUBLIC;
1373 } else {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001374 xmlCatalogErr(NULL, cur, XML_CATALOG_PREFER_VALUE,
1375 "Invalid value for prefer: '%s'\n",
1376 prop, NULL, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001377 }
1378 xmlFree(prop);
1379 }
1380 cur = cur->children;
William M. Brackb7b54de2004-10-06 16:38:01 +00001381 xmlParseXMLCatalogNodeList(cur, prefer, parent, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001382 } else {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001383 xmlCatalogErr(NULL, (xmlNodePtr) doc, XML_CATALOG_NOT_CATALOG,
1384 "File %s is not an XML Catalog\n",
1385 filename, NULL, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001386 xmlFreeDoc(doc);
1387 return(NULL);
1388 }
1389 xmlFreeDoc(doc);
1390 return(parent);
1391}
1392
Daniel Veillardcda96922001-08-21 10:56:31 +00001393/**
1394 * xmlFetchXMLCatalogFile:
1395 * @catal: an existing but incomplete catalog entry
1396 *
1397 * Fetch and parse the subcatalog referenced by an entry
Daniel Veillardcda96922001-08-21 10:56:31 +00001398 *
1399 * Returns 0 in case of success, -1 otherwise
1400 */
1401static int
1402xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) {
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001403 xmlCatalogEntryPtr doc;
Daniel Veillardcda96922001-08-21 10:56:31 +00001404
1405 if (catal == NULL)
1406 return(-1);
Daniel Veillardc853b322001-11-06 15:24:37 +00001407 if (catal->URL == NULL)
Daniel Veillardcda96922001-08-21 10:56:31 +00001408 return(-1);
Daniel Veillardcda96922001-08-21 10:56:31 +00001409
Daniel Veillard81463942001-10-16 12:34:39 +00001410 /*
1411 * lock the whole catalog for modification
1412 */
1413 xmlRMutexLock(xmlCatalogMutex);
1414 if (catal->children != NULL) {
1415 /* Okay someone else did it in the meantime */
1416 xmlRMutexUnlock(xmlCatalogMutex);
1417 return(0);
Daniel Veillard81463942001-10-16 12:34:39 +00001418 }
1419
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001420 if (xmlCatalogXMLFiles != NULL) {
1421 doc = (xmlCatalogEntryPtr)
Daniel Veillardc853b322001-11-06 15:24:37 +00001422 xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001423 if (doc != NULL) {
1424 if (xmlDebugCatalogs)
1425 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001426 "Found %s in file hash\n", catal->URL);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001427
1428 if (catal->type == XML_CATA_CATALOG)
1429 catal->children = doc->children;
1430 else
1431 catal->children = doc;
1432 catal->dealloc = 0;
1433 xmlRMutexUnlock(xmlCatalogMutex);
1434 return(0);
1435 }
1436 if (xmlDebugCatalogs)
1437 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001438 "%s not found in file hash\n", catal->URL);
Daniel Veillard6990bf32001-08-23 21:17:48 +00001439 }
1440
Daniel Veillardcda96922001-08-21 10:56:31 +00001441 /*
Daniel Veillard75b96822001-10-11 18:59:45 +00001442 * Fetch and parse. Note that xmlParseXMLCatalogFile does not
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001443 * use the existing catalog, there is no recursion allowed at
Daniel Veillard75b96822001-10-11 18:59:45 +00001444 * that level.
Daniel Veillardcda96922001-08-21 10:56:31 +00001445 */
Daniel Veillardc853b322001-11-06 15:24:37 +00001446 doc = xmlParseXMLCatalogFile(catal->prefer, catal->URL);
Daniel Veillard6990bf32001-08-23 21:17:48 +00001447 if (doc == NULL) {
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00001448 catal->type = XML_CATA_BROKEN_CATALOG;
Daniel Veillard81463942001-10-16 12:34:39 +00001449 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillardcda96922001-08-21 10:56:31 +00001450 return(-1);
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00001451 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001452
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001453 if (catal->type == XML_CATA_CATALOG)
1454 catal->children = doc->children;
1455 else
1456 catal->children = doc;
1457
1458 doc->dealloc = 1;
1459
Daniel Veillard81463942001-10-16 12:34:39 +00001460 if (xmlCatalogXMLFiles == NULL)
1461 xmlCatalogXMLFiles = xmlHashCreate(10);
1462 if (xmlCatalogXMLFiles != NULL) {
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001463 if (xmlDebugCatalogs)
1464 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001465 "%s added to file hash\n", catal->URL);
1466 xmlHashAddEntry(xmlCatalogXMLFiles, catal->URL, doc);
Daniel Veillardcda96922001-08-21 10:56:31 +00001467 }
Daniel Veillard81463942001-10-16 12:34:39 +00001468 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillardcda96922001-08-21 10:56:31 +00001469 return(0);
1470}
1471
Daniel Veillard75b96822001-10-11 18:59:45 +00001472/************************************************************************
1473 * *
1474 * XML Catalog handling *
1475 * *
1476 ************************************************************************/
Daniel Veillard344cee72001-08-20 00:08:40 +00001477
1478/**
1479 * xmlAddXMLCatalog:
1480 * @catal: top of an XML catalog
1481 * @type: the type of record to add to the catalog
Daniel Veillardcda96922001-08-21 10:56:31 +00001482 * @orig: the system, public or prefix to match (or NULL)
Daniel Veillard344cee72001-08-20 00:08:40 +00001483 * @replace: the replacement value for the match
1484 *
1485 * Add an entry in the XML catalog, it may overwrite existing but
1486 * different entries.
1487 *
1488 * Returns 0 if successful, -1 otherwise
1489 */
1490static int
1491xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type,
1492 const xmlChar *orig, const xmlChar *replace) {
1493 xmlCatalogEntryPtr cur;
1494 xmlCatalogEntryType typ;
Daniel Veillardc853b322001-11-06 15:24:37 +00001495 int doregister = 0;
Daniel Veillard344cee72001-08-20 00:08:40 +00001496
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00001497 if ((catal == NULL) ||
1498 ((catal->type != XML_CATA_CATALOG) &&
1499 (catal->type != XML_CATA_BROKEN_CATALOG)))
Daniel Veillard344cee72001-08-20 00:08:40 +00001500 return(-1);
Daniel Veillardffe09c92001-11-05 14:21:47 +00001501 if (catal->children == NULL) {
1502 xmlFetchXMLCatalogFile(catal);
1503 }
Daniel Veillardc853b322001-11-06 15:24:37 +00001504 if (catal->children == NULL)
1505 doregister = 1;
1506
Daniel Veillard344cee72001-08-20 00:08:40 +00001507 typ = xmlGetXMLCatalogEntryType(type);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001508 if (typ == XML_CATA_NONE) {
1509 if (xmlDebugCatalogs)
1510 xmlGenericError(xmlGenericErrorContext,
1511 "Failed to add unknown element %s to catalog\n", type);
Daniel Veillard344cee72001-08-20 00:08:40 +00001512 return(-1);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001513 }
Daniel Veillard344cee72001-08-20 00:08:40 +00001514
1515 cur = catal->children;
1516 /*
1517 * Might be a simple "update in place"
1518 */
1519 if (cur != NULL) {
1520 while (cur != NULL) {
Daniel Veillardcda96922001-08-21 10:56:31 +00001521 if ((orig != NULL) && (cur->type == typ) &&
1522 (xmlStrEqual(orig, cur->name))) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001523 if (xmlDebugCatalogs)
1524 xmlGenericError(xmlGenericErrorContext,
1525 "Updating element %s to catalog\n", type);
Daniel Veillard344cee72001-08-20 00:08:40 +00001526 if (cur->value != NULL)
1527 xmlFree(cur->value);
Daniel Veillardc853b322001-11-06 15:24:37 +00001528 if (cur->URL != NULL)
1529 xmlFree(cur->URL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001530 cur->value = xmlStrdup(replace);
Daniel Veillardc853b322001-11-06 15:24:37 +00001531 cur->URL = xmlStrdup(replace);
Daniel Veillardcda96922001-08-21 10:56:31 +00001532 return(0);
Daniel Veillard344cee72001-08-20 00:08:40 +00001533 }
1534 if (cur->next == NULL)
1535 break;
1536 cur = cur->next;
1537 }
1538 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001539 if (xmlDebugCatalogs)
1540 xmlGenericError(xmlGenericErrorContext,
1541 "Adding element %s to catalog\n", type);
Daniel Veillard344cee72001-08-20 00:08:40 +00001542 if (cur == NULL)
Daniel Veillardc853b322001-11-06 15:24:37 +00001543 catal->children = xmlNewCatalogEntry(typ, orig, replace,
William M. Brackb7b54de2004-10-06 16:38:01 +00001544 NULL, catal->prefer, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001545 else
Daniel Veillardc853b322001-11-06 15:24:37 +00001546 cur->next = xmlNewCatalogEntry(typ, orig, replace,
William M. Brackb7b54de2004-10-06 16:38:01 +00001547 NULL, catal->prefer, NULL);
Daniel Veillardc853b322001-11-06 15:24:37 +00001548 if (doregister) {
Daniel Veillard27bec142006-02-24 20:22:27 +00001549 catal->type = XML_CATA_CATALOG;
Daniel Veillardc853b322001-11-06 15:24:37 +00001550 cur = xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
1551 if (cur != NULL)
1552 cur->children = catal->children;
1553 }
1554
Daniel Veillardcda96922001-08-21 10:56:31 +00001555 return(0);
1556}
1557
1558/**
1559 * xmlDelXMLCatalog:
1560 * @catal: top of an XML catalog
Daniel Veillard60087f32001-10-10 09:45:09 +00001561 * @value: the value to remove from the catalog
Daniel Veillardcda96922001-08-21 10:56:31 +00001562 *
1563 * Remove entries in the XML catalog where the value or the URI
1564 * is equal to @value
1565 *
1566 * Returns the number of entries removed if successful, -1 otherwise
1567 */
1568static int
1569xmlDelXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *value) {
Daniel Veillardc853b322001-11-06 15:24:37 +00001570 xmlCatalogEntryPtr cur;
Daniel Veillardcda96922001-08-21 10:56:31 +00001571 int ret = 0;
1572
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00001573 if ((catal == NULL) ||
1574 ((catal->type != XML_CATA_CATALOG) &&
1575 (catal->type != XML_CATA_BROKEN_CATALOG)))
Daniel Veillardcda96922001-08-21 10:56:31 +00001576 return(-1);
1577 if (value == NULL)
1578 return(-1);
Daniel Veillardffe09c92001-11-05 14:21:47 +00001579 if (catal->children == NULL) {
1580 xmlFetchXMLCatalogFile(catal);
1581 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001582
1583 /*
1584 * Scan the children
1585 */
1586 cur = catal->children;
Daniel Veillardcda96922001-08-21 10:56:31 +00001587 while (cur != NULL) {
1588 if (((cur->name != NULL) && (xmlStrEqual(value, cur->name))) ||
1589 (xmlStrEqual(value, cur->value))) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001590 if (xmlDebugCatalogs) {
1591 if (cur->name != NULL)
1592 xmlGenericError(xmlGenericErrorContext,
1593 "Removing element %s from catalog\n", cur->name);
1594 else
1595 xmlGenericError(xmlGenericErrorContext,
1596 "Removing element %s from catalog\n", cur->value);
1597 }
Daniel Veillardc853b322001-11-06 15:24:37 +00001598 cur->type = XML_CATA_REMOVED;
Daniel Veillardcda96922001-08-21 10:56:31 +00001599 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001600 cur = cur->next;
1601 }
1602 return(ret);
1603}
1604
1605/**
Daniel Veillardcda96922001-08-21 10:56:31 +00001606 * xmlCatalogXMLResolve:
1607 * @catal: a catalog list
Daniel Veillard06d25242004-02-25 13:01:42 +00001608 * @pubID: the public ID string
1609 * @sysID: the system ID string
Daniel Veillardcda96922001-08-21 10:56:31 +00001610 *
1611 * Do a complete resolution lookup of an External Identifier for a
1612 * list of catalog entries.
1613 *
1614 * Implements (or tries to) 7.1. External Identifier Resolution
1615 * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1616 *
1617 * Returns the URI of the resource or NULL if not found
1618 */
1619static xmlChar *
1620xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1621 const xmlChar *sysID) {
1622 xmlChar *ret = NULL;
1623 xmlCatalogEntryPtr cur;
1624 int haveDelegate = 0;
1625 int haveNext = 0;
1626
1627 /*
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001628 * protection against loops
1629 */
1630 if (catal->depth > MAX_CATAL_DEPTH) {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001631 xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
1632 "Detected recursion in catalog %s\n",
1633 catal->name, NULL, NULL);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001634 return(NULL);
1635 }
1636 catal->depth++;
1637
1638 /*
Daniel Veillardcda96922001-08-21 10:56:31 +00001639 * First tries steps 2/ 3/ 4/ if a system ID is provided.
1640 */
1641 if (sysID != NULL) {
1642 xmlCatalogEntryPtr rewrite = NULL;
1643 int lenrewrite = 0, len;
1644 cur = catal;
1645 haveDelegate = 0;
1646 while (cur != NULL) {
1647 switch (cur->type) {
1648 case XML_CATA_SYSTEM:
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001649 if (xmlStrEqual(sysID, cur->name)) {
1650 if (xmlDebugCatalogs)
1651 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard890b5492006-02-23 08:14:00 +00001652 "Found system match %s, using %s\n",
1653 cur->name, cur->URL);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001654 catal->depth--;
Daniel Veillardc853b322001-11-06 15:24:37 +00001655 return(xmlStrdup(cur->URL));
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001656 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001657 break;
1658 case XML_CATA_REWRITE_SYSTEM:
1659 len = xmlStrlen(cur->name);
1660 if ((len > lenrewrite) &&
1661 (!xmlStrncmp(sysID, cur->name, len))) {
1662 lenrewrite = len;
1663 rewrite = cur;
1664 }
1665 break;
1666 case XML_CATA_DELEGATE_SYSTEM:
1667 if (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))
1668 haveDelegate++;
1669 break;
1670 case XML_CATA_NEXT_CATALOG:
1671 haveNext++;
1672 break;
1673 default:
1674 break;
1675 }
1676 cur = cur->next;
1677 }
1678 if (rewrite != NULL) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001679 if (xmlDebugCatalogs)
1680 xmlGenericError(xmlGenericErrorContext,
1681 "Using rewriting rule %s\n", rewrite->name);
Daniel Veillardc853b322001-11-06 15:24:37 +00001682 ret = xmlStrdup(rewrite->URL);
Daniel Veillardcda96922001-08-21 10:56:31 +00001683 if (ret != NULL)
1684 ret = xmlStrcat(ret, &sysID[lenrewrite]);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001685 catal->depth--;
Daniel Veillardcda96922001-08-21 10:56:31 +00001686 return(ret);
1687 }
1688 if (haveDelegate) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001689 const xmlChar *delegates[MAX_DELEGATE];
1690 int nbList = 0, i;
1691
Daniel Veillardcda96922001-08-21 10:56:31 +00001692 /*
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001693 * Assume the entries have been sorted by decreasing substring
Daniel Veillardcda96922001-08-21 10:56:31 +00001694 * matches when the list was produced.
1695 */
1696 cur = catal;
1697 while (cur != NULL) {
1698 if ((cur->type == XML_CATA_DELEGATE_SYSTEM) &&
1699 (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001700 for (i = 0;i < nbList;i++)
Daniel Veillardc853b322001-11-06 15:24:37 +00001701 if (xmlStrEqual(cur->URL, delegates[i]))
Daniel Veillard6990bf32001-08-23 21:17:48 +00001702 break;
1703 if (i < nbList) {
1704 cur = cur->next;
1705 continue;
1706 }
1707 if (nbList < MAX_DELEGATE)
Daniel Veillardc853b322001-11-06 15:24:37 +00001708 delegates[nbList++] = cur->URL;
Daniel Veillard6990bf32001-08-23 21:17:48 +00001709
Daniel Veillardcda96922001-08-21 10:56:31 +00001710 if (cur->children == NULL) {
1711 xmlFetchXMLCatalogFile(cur);
1712 }
1713 if (cur->children != NULL) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001714 if (xmlDebugCatalogs)
1715 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001716 "Trying system delegate %s\n", cur->URL);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001717 ret = xmlCatalogListXMLResolve(
1718 cur->children, NULL, sysID);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001719 if (ret != NULL) {
1720 catal->depth--;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001721 return(ret);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001722 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001723 }
1724 }
1725 cur = cur->next;
1726 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001727 /*
1728 * Apply the cut algorithm explained in 4/
1729 */
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001730 catal->depth--;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001731 return(XML_CATAL_BREAK);
Daniel Veillardcda96922001-08-21 10:56:31 +00001732 }
1733 }
1734 /*
1735 * Then tries 5/ 6/ if a public ID is provided
1736 */
1737 if (pubID != NULL) {
1738 cur = catal;
1739 haveDelegate = 0;
1740 while (cur != NULL) {
1741 switch (cur->type) {
1742 case XML_CATA_PUBLIC:
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001743 if (xmlStrEqual(pubID, cur->name)) {
1744 if (xmlDebugCatalogs)
1745 xmlGenericError(xmlGenericErrorContext,
1746 "Found public match %s\n", cur->name);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001747 catal->depth--;
Daniel Veillardc853b322001-11-06 15:24:37 +00001748 return(xmlStrdup(cur->URL));
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001749 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001750 break;
1751 case XML_CATA_DELEGATE_PUBLIC:
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001752 if (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)) &&
1753 (cur->prefer == XML_CATA_PREFER_PUBLIC))
Daniel Veillardcda96922001-08-21 10:56:31 +00001754 haveDelegate++;
1755 break;
1756 case XML_CATA_NEXT_CATALOG:
1757 if (sysID == NULL)
1758 haveNext++;
1759 break;
1760 default:
1761 break;
1762 }
1763 cur = cur->next;
1764 }
1765 if (haveDelegate) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001766 const xmlChar *delegates[MAX_DELEGATE];
1767 int nbList = 0, i;
1768
Daniel Veillardcda96922001-08-21 10:56:31 +00001769 /*
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001770 * Assume the entries have been sorted by decreasing substring
Daniel Veillardcda96922001-08-21 10:56:31 +00001771 * matches when the list was produced.
1772 */
1773 cur = catal;
1774 while (cur != NULL) {
1775 if ((cur->type == XML_CATA_DELEGATE_PUBLIC) &&
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001776 (cur->prefer == XML_CATA_PREFER_PUBLIC) &&
1777 (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)))) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001778
1779 for (i = 0;i < nbList;i++)
Daniel Veillardc853b322001-11-06 15:24:37 +00001780 if (xmlStrEqual(cur->URL, delegates[i]))
Daniel Veillard6990bf32001-08-23 21:17:48 +00001781 break;
1782 if (i < nbList) {
1783 cur = cur->next;
1784 continue;
1785 }
1786 if (nbList < MAX_DELEGATE)
Daniel Veillardc853b322001-11-06 15:24:37 +00001787 delegates[nbList++] = cur->URL;
Daniel Veillard6990bf32001-08-23 21:17:48 +00001788
Daniel Veillardcda96922001-08-21 10:56:31 +00001789 if (cur->children == NULL) {
1790 xmlFetchXMLCatalogFile(cur);
1791 }
1792 if (cur->children != NULL) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001793 if (xmlDebugCatalogs)
1794 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001795 "Trying public delegate %s\n", cur->URL);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001796 ret = xmlCatalogListXMLResolve(
1797 cur->children, pubID, NULL);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001798 if (ret != NULL) {
1799 catal->depth--;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001800 return(ret);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001801 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001802 }
1803 }
1804 cur = cur->next;
1805 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001806 /*
1807 * Apply the cut algorithm explained in 4/
1808 */
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001809 catal->depth--;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001810 return(XML_CATAL_BREAK);
Daniel Veillardcda96922001-08-21 10:56:31 +00001811 }
1812 }
1813 if (haveNext) {
1814 cur = catal;
1815 while (cur != NULL) {
1816 if (cur->type == XML_CATA_NEXT_CATALOG) {
1817 if (cur->children == NULL) {
1818 xmlFetchXMLCatalogFile(cur);
1819 }
1820 if (cur->children != NULL) {
Daniel Veillard64339542001-08-21 12:57:59 +00001821 ret = xmlCatalogListXMLResolve(cur->children, pubID, sysID);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001822 if (ret != NULL) {
1823 catal->depth--;
Daniel Veillard64339542001-08-21 12:57:59 +00001824 return(ret);
Daniel Veillardbe8d9d32007-06-12 09:14:11 +00001825 } else if (catal->depth > MAX_CATAL_DEPTH) {
1826 return(NULL);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001827 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001828 }
1829 }
1830 cur = cur->next;
1831 }
1832 }
1833
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001834 catal->depth--;
Daniel Veillardcda96922001-08-21 10:56:31 +00001835 return(NULL);
1836}
1837
1838/**
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001839 * xmlCatalogXMLResolveURI:
1840 * @catal: a catalog list
1841 * @URI: the URI
Daniel Veillard06d25242004-02-25 13:01:42 +00001842 * @sysID: the system ID string
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001843 *
1844 * Do a complete resolution lookup of an External Identifier for a
1845 * list of catalog entries.
1846 *
1847 * Implements (or tries to) 7.2.2. URI Resolution
1848 * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1849 *
1850 * Returns the URI of the resource or NULL if not found
1851 */
1852static xmlChar *
1853xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
1854 xmlChar *ret = NULL;
1855 xmlCatalogEntryPtr cur;
1856 int haveDelegate = 0;
1857 int haveNext = 0;
1858 xmlCatalogEntryPtr rewrite = NULL;
1859 int lenrewrite = 0, len;
1860
1861 if (catal == NULL)
1862 return(NULL);
1863
1864 if (URI == NULL)
1865 return(NULL);
1866
Daniel Veillardbe8d9d32007-06-12 09:14:11 +00001867 if (catal->depth > MAX_CATAL_DEPTH) {
1868 xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
1869 "Detected recursion in catalog %s\n",
1870 catal->name, NULL, NULL);
1871 return(NULL);
1872 }
1873
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001874 /*
1875 * First tries steps 2/ 3/ 4/ if a system ID is provided.
1876 */
1877 cur = catal;
1878 haveDelegate = 0;
1879 while (cur != NULL) {
1880 switch (cur->type) {
1881 case XML_CATA_URI:
1882 if (xmlStrEqual(URI, cur->name)) {
1883 if (xmlDebugCatalogs)
1884 xmlGenericError(xmlGenericErrorContext,
1885 "Found URI match %s\n", cur->name);
Daniel Veillardc853b322001-11-06 15:24:37 +00001886 return(xmlStrdup(cur->URL));
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001887 }
1888 break;
1889 case XML_CATA_REWRITE_URI:
1890 len = xmlStrlen(cur->name);
1891 if ((len > lenrewrite) &&
1892 (!xmlStrncmp(URI, cur->name, len))) {
1893 lenrewrite = len;
1894 rewrite = cur;
1895 }
1896 break;
1897 case XML_CATA_DELEGATE_URI:
1898 if (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))
1899 haveDelegate++;
1900 break;
1901 case XML_CATA_NEXT_CATALOG:
1902 haveNext++;
1903 break;
1904 default:
1905 break;
1906 }
1907 cur = cur->next;
1908 }
1909 if (rewrite != NULL) {
1910 if (xmlDebugCatalogs)
1911 xmlGenericError(xmlGenericErrorContext,
1912 "Using rewriting rule %s\n", rewrite->name);
Daniel Veillardc853b322001-11-06 15:24:37 +00001913 ret = xmlStrdup(rewrite->URL);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001914 if (ret != NULL)
1915 ret = xmlStrcat(ret, &URI[lenrewrite]);
1916 return(ret);
1917 }
1918 if (haveDelegate) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001919 const xmlChar *delegates[MAX_DELEGATE];
1920 int nbList = 0, i;
1921
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001922 /*
1923 * Assume the entries have been sorted by decreasing substring
1924 * matches when the list was produced.
1925 */
1926 cur = catal;
1927 while (cur != NULL) {
Daniel Veillard652d8a92003-02-04 19:28:49 +00001928 if (((cur->type == XML_CATA_DELEGATE_SYSTEM) ||
1929 (cur->type == XML_CATA_DELEGATE_URI)) &&
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001930 (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001931 for (i = 0;i < nbList;i++)
Daniel Veillardc853b322001-11-06 15:24:37 +00001932 if (xmlStrEqual(cur->URL, delegates[i]))
Daniel Veillard6990bf32001-08-23 21:17:48 +00001933 break;
1934 if (i < nbList) {
1935 cur = cur->next;
1936 continue;
1937 }
1938 if (nbList < MAX_DELEGATE)
Daniel Veillardc853b322001-11-06 15:24:37 +00001939 delegates[nbList++] = cur->URL;
Daniel Veillard6990bf32001-08-23 21:17:48 +00001940
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001941 if (cur->children == NULL) {
1942 xmlFetchXMLCatalogFile(cur);
1943 }
1944 if (cur->children != NULL) {
1945 if (xmlDebugCatalogs)
1946 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001947 "Trying URI delegate %s\n", cur->URL);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001948 ret = xmlCatalogListXMLResolveURI(
1949 cur->children, URI);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001950 if (ret != NULL)
1951 return(ret);
1952 }
1953 }
1954 cur = cur->next;
1955 }
1956 /*
1957 * Apply the cut algorithm explained in 4/
1958 */
1959 return(XML_CATAL_BREAK);
1960 }
1961 if (haveNext) {
1962 cur = catal;
1963 while (cur != NULL) {
1964 if (cur->type == XML_CATA_NEXT_CATALOG) {
1965 if (cur->children == NULL) {
1966 xmlFetchXMLCatalogFile(cur);
1967 }
1968 if (cur->children != NULL) {
1969 ret = xmlCatalogListXMLResolveURI(cur->children, URI);
1970 if (ret != NULL)
1971 return(ret);
1972 }
1973 }
1974 cur = cur->next;
1975 }
1976 }
1977
1978 return(NULL);
1979}
1980
1981/**
Daniel Veillardcda96922001-08-21 10:56:31 +00001982 * xmlCatalogListXMLResolve:
1983 * @catal: a catalog list
Daniel Veillard06d25242004-02-25 13:01:42 +00001984 * @pubID: the public ID string
1985 * @sysID: the system ID string
Daniel Veillardcda96922001-08-21 10:56:31 +00001986 *
1987 * Do a complete resolution lookup of an External Identifier for a
1988 * list of catalogs
1989 *
1990 * Implements (or tries to) 7.1. External Identifier Resolution
1991 * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1992 *
1993 * Returns the URI of the resource or NULL if not found
1994 */
1995static xmlChar *
1996xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1997 const xmlChar *sysID) {
1998 xmlChar *ret = NULL;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001999 xmlChar *urnID = NULL;
Daniel Veillardc8155052004-07-16 09:03:08 +00002000 xmlChar *normid;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002001
2002 if (catal == NULL)
2003 return(NULL);
2004 if ((pubID == NULL) && (sysID == NULL))
2005 return(NULL);
2006
Daniel Veillardc8155052004-07-16 09:03:08 +00002007 normid = xmlCatalogNormalizePublic(pubID);
2008 if (normid != NULL)
2009 pubID = (*normid != 0 ? normid : NULL);
2010
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002011 if (!xmlStrncmp(pubID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2012 urnID = xmlCatalogUnWrapURN(pubID);
2013 if (xmlDebugCatalogs) {
2014 if (urnID == NULL)
2015 xmlGenericError(xmlGenericErrorContext,
2016 "Public URN ID %s expanded to NULL\n", pubID);
2017 else
2018 xmlGenericError(xmlGenericErrorContext,
2019 "Public URN ID expanded to %s\n", urnID);
2020 }
2021 ret = xmlCatalogListXMLResolve(catal, urnID, sysID);
2022 if (urnID != NULL)
2023 xmlFree(urnID);
Daniel Veillardc8155052004-07-16 09:03:08 +00002024 if (normid != NULL)
2025 xmlFree(normid);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002026 return(ret);
Daniel Veillardcda96922001-08-21 10:56:31 +00002027 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002028 if (!xmlStrncmp(sysID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2029 urnID = xmlCatalogUnWrapURN(sysID);
2030 if (xmlDebugCatalogs) {
2031 if (urnID == NULL)
2032 xmlGenericError(xmlGenericErrorContext,
2033 "System URN ID %s expanded to NULL\n", sysID);
2034 else
2035 xmlGenericError(xmlGenericErrorContext,
2036 "System URN ID expanded to %s\n", urnID);
2037 }
2038 if (pubID == NULL)
2039 ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
2040 else if (xmlStrEqual(pubID, urnID))
2041 ret = xmlCatalogListXMLResolve(catal, pubID, NULL);
2042 else {
Daniel Veillard770075b2004-02-25 10:44:30 +00002043 ret = xmlCatalogListXMLResolve(catal, pubID, urnID);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002044 }
2045 if (urnID != NULL)
2046 xmlFree(urnID);
Daniel Veillardc8155052004-07-16 09:03:08 +00002047 if (normid != NULL)
2048 xmlFree(normid);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002049 return(ret);
Daniel Veillardcda96922001-08-21 10:56:31 +00002050 }
2051 while (catal != NULL) {
2052 if (catal->type == XML_CATA_CATALOG) {
2053 if (catal->children == NULL) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002054 xmlFetchXMLCatalogFile(catal);
Daniel Veillardcda96922001-08-21 10:56:31 +00002055 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002056 if (catal->children != NULL) {
2057 ret = xmlCatalogXMLResolve(catal->children, pubID, sysID);
Daniel Veillardc8155052004-07-16 09:03:08 +00002058 if (ret != NULL) {
Daniel Veillardbe8d9d32007-06-12 09:14:11 +00002059 break;
2060 } else if ((catal->children != NULL) &&
2061 (catal->children->depth > MAX_CATAL_DEPTH)) {
2062 ret = NULL;
2063 break;
2064 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002065 }
Daniel Veillardcda96922001-08-21 10:56:31 +00002066 }
2067 catal = catal->next;
2068 }
Daniel Veillardbe8d9d32007-06-12 09:14:11 +00002069 if (normid != NULL)
2070 xmlFree(normid);
Daniel Veillardcda96922001-08-21 10:56:31 +00002071 return(ret);
Daniel Veillard344cee72001-08-20 00:08:40 +00002072}
2073
Daniel Veillarddc2cee22001-08-22 16:30:37 +00002074/**
2075 * xmlCatalogListXMLResolveURI:
2076 * @catal: a catalog list
2077 * @URI: the URI
2078 *
2079 * Do a complete resolution lookup of an URI for a list of catalogs
2080 *
2081 * Implements (or tries to) 7.2. URI Resolution
2082 * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
2083 *
2084 * Returns the URI of the resource or NULL if not found
2085 */
2086static xmlChar *
2087xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
2088 xmlChar *ret = NULL;
2089 xmlChar *urnID = NULL;
2090
2091 if (catal == NULL)
2092 return(NULL);
2093 if (URI == NULL)
2094 return(NULL);
2095
2096 if (!xmlStrncmp(URI, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2097 urnID = xmlCatalogUnWrapURN(URI);
2098 if (xmlDebugCatalogs) {
2099 if (urnID == NULL)
2100 xmlGenericError(xmlGenericErrorContext,
2101 "URN ID %s expanded to NULL\n", URI);
2102 else
2103 xmlGenericError(xmlGenericErrorContext,
2104 "URN ID expanded to %s\n", urnID);
2105 }
2106 ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
2107 if (urnID != NULL)
2108 xmlFree(urnID);
2109 return(ret);
2110 }
2111 while (catal != NULL) {
2112 if (catal->type == XML_CATA_CATALOG) {
2113 if (catal->children == NULL) {
2114 xmlFetchXMLCatalogFile(catal);
2115 }
2116 if (catal->children != NULL) {
2117 ret = xmlCatalogXMLResolveURI(catal->children, URI);
2118 if (ret != NULL)
2119 return(ret);
2120 }
2121 }
2122 catal = catal->next;
2123 }
2124 return(ret);
2125}
2126
Daniel Veillard344cee72001-08-20 00:08:40 +00002127/************************************************************************
2128 * *
2129 * The SGML Catalog parser *
Daniel Veillarda7374592001-05-10 14:17:55 +00002130 * *
2131 ************************************************************************/
2132
2133
2134#define RAW *cur
2135#define NEXT cur++;
2136#define SKIP(x) cur += x;
2137
William M. Brack272693c2003-11-14 16:20:34 +00002138#define SKIP_BLANKS while (IS_BLANK_CH(*cur)) NEXT;
Daniel Veillarda7374592001-05-10 14:17:55 +00002139
Daniel Veillard75b96822001-10-11 18:59:45 +00002140/**
2141 * xmlParseSGMLCatalogComment:
2142 * @cur: the current character
2143 *
2144 * Skip a comment in an SGML catalog
2145 *
2146 * Returns new current character
2147 */
Daniel Veillarda7374592001-05-10 14:17:55 +00002148static const xmlChar *
Daniel Veillardcda96922001-08-21 10:56:31 +00002149xmlParseSGMLCatalogComment(const xmlChar *cur) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002150 if ((cur[0] != '-') || (cur[1] != '-'))
2151 return(cur);
2152 SKIP(2);
2153 while ((cur[0] != 0) && ((cur[0] != '-') || ((cur[1] != '-'))))
2154 NEXT;
2155 if (cur[0] == 0) {
2156 return(NULL);
2157 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002158 return(cur + 2);
Daniel Veillarda7374592001-05-10 14:17:55 +00002159}
2160
Daniel Veillard75b96822001-10-11 18:59:45 +00002161/**
2162 * xmlParseSGMLCatalogPubid:
2163 * @cur: the current character
2164 * @id: the return location
2165 *
2166 * Parse an SGML catalog ID
2167 *
2168 * Returns new current character and store the value in @id
2169 */
Daniel Veillarda7374592001-05-10 14:17:55 +00002170static const xmlChar *
Daniel Veillardcda96922001-08-21 10:56:31 +00002171xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) {
Daniel Veillard69d2c172003-10-09 11:46:07 +00002172 xmlChar *buf = NULL, *tmp;
Daniel Veillarda7374592001-05-10 14:17:55 +00002173 int len = 0;
2174 int size = 50;
2175 xmlChar stop;
2176 int count = 0;
2177
2178 *id = NULL;
2179
2180 if (RAW == '"') {
2181 NEXT;
2182 stop = '"';
2183 } else if (RAW == '\'') {
2184 NEXT;
2185 stop = '\'';
2186 } else {
2187 stop = ' ';
2188 }
Daniel Veillard3c908dc2003-04-19 00:07:51 +00002189 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
Daniel Veillarda7374592001-05-10 14:17:55 +00002190 if (buf == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +00002191 xmlCatalogErrMemory("allocating public ID");
Daniel Veillarda7374592001-05-10 14:17:55 +00002192 return(NULL);
2193 }
William M. Brack76e95df2003-10-18 16:20:14 +00002194 while (IS_PUBIDCHAR_CH(*cur) || (*cur == '?')) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002195 if ((*cur == stop) && (stop != ' '))
2196 break;
William M. Brack76e95df2003-10-18 16:20:14 +00002197 if ((stop == ' ') && (IS_BLANK_CH(*cur)))
Daniel Veillarda7374592001-05-10 14:17:55 +00002198 break;
2199 if (len + 1 >= size) {
2200 size *= 2;
Daniel Veillard69d2c172003-10-09 11:46:07 +00002201 tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
2202 if (tmp == NULL) {
2203 xmlCatalogErrMemory("allocating public ID");
2204 xmlFree(buf);
Daniel Veillarda7374592001-05-10 14:17:55 +00002205 return(NULL);
2206 }
Daniel Veillard69d2c172003-10-09 11:46:07 +00002207 buf = tmp;
Daniel Veillarda7374592001-05-10 14:17:55 +00002208 }
2209 buf[len++] = *cur;
2210 count++;
2211 NEXT;
2212 }
2213 buf[len] = 0;
2214 if (stop == ' ') {
William M. Brack76e95df2003-10-18 16:20:14 +00002215 if (!IS_BLANK_CH(*cur)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002216 xmlFree(buf);
2217 return(NULL);
2218 }
2219 } else {
2220 if (*cur != stop) {
2221 xmlFree(buf);
2222 return(NULL);
2223 }
2224 NEXT;
2225 }
2226 *id = buf;
2227 return(cur);
2228}
2229
Daniel Veillard75b96822001-10-11 18:59:45 +00002230/**
2231 * xmlParseSGMLCatalogName:
2232 * @cur: the current character
2233 * @name: the return location
2234 *
2235 * Parse an SGML catalog name
2236 *
2237 * Returns new current character and store the value in @name
2238 */
Daniel Veillarda7374592001-05-10 14:17:55 +00002239static const xmlChar *
Daniel Veillardcda96922001-08-21 10:56:31 +00002240xmlParseSGMLCatalogName(const xmlChar *cur, xmlChar **name) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002241 xmlChar buf[XML_MAX_NAMELEN + 5];
2242 int len = 0;
2243 int c;
2244
2245 *name = NULL;
2246
2247 /*
2248 * Handler for more complex cases
2249 */
2250 c = *cur;
2251 if ((!IS_LETTER(c) && (c != '_') && (c != ':'))) {
2252 return(NULL);
2253 }
2254
2255 while (((IS_LETTER(c)) || (IS_DIGIT(c)) ||
2256 (c == '.') || (c == '-') ||
2257 (c == '_') || (c == ':'))) {
2258 buf[len++] = c;
2259 cur++;
2260 c = *cur;
2261 if (len >= XML_MAX_NAMELEN)
2262 return(NULL);
2263 }
2264 *name = xmlStrndup(buf, len);
2265 return(cur);
2266}
2267
Daniel Veillard75b96822001-10-11 18:59:45 +00002268/**
2269 * xmlGetSGMLCatalogEntryType:
2270 * @name: the entry name
2271 *
2272 * Get the Catalog entry type for a given SGML Catalog name
2273 *
2274 * Returns Catalog entry type
2275 */
Daniel Veillard344cee72001-08-20 00:08:40 +00002276static xmlCatalogEntryType
Daniel Veillardcda96922001-08-21 10:56:31 +00002277xmlGetSGMLCatalogEntryType(const xmlChar *name) {
Daniel Veillard344cee72001-08-20 00:08:40 +00002278 xmlCatalogEntryType type = XML_CATA_NONE;
2279 if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
2280 type = SGML_CATA_SYSTEM;
2281 else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
2282 type = SGML_CATA_PUBLIC;
2283 else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
2284 type = SGML_CATA_DELEGATE;
2285 else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
2286 type = SGML_CATA_ENTITY;
2287 else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
2288 type = SGML_CATA_DOCTYPE;
2289 else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
2290 type = SGML_CATA_LINKTYPE;
2291 else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
2292 type = SGML_CATA_NOTATION;
2293 else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
2294 type = SGML_CATA_SGMLDECL;
2295 else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
2296 type = SGML_CATA_DOCUMENT;
2297 else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
2298 type = SGML_CATA_CATALOG;
2299 else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
2300 type = SGML_CATA_BASE;
Daniel Veillard344cee72001-08-20 00:08:40 +00002301 return(type);
2302}
2303
Daniel Veillard75b96822001-10-11 18:59:45 +00002304/**
2305 * xmlParseSGMLCatalog:
2306 * @catal: the SGML Catalog
2307 * @value: the content of the SGML Catalog serialization
2308 * @file: the filepath for the catalog
2309 * @super: should this be handled as a Super Catalog in which case
2310 * parsing is not recursive
2311 *
2312 * Parse an SGML catalog content and fill up the @catal hash table with
2313 * the new entries found.
2314 *
2315 * Returns 0 in case of success, -1 in case of error.
2316 */
Daniel Veillarda7374592001-05-10 14:17:55 +00002317static int
Daniel Veillard75b96822001-10-11 18:59:45 +00002318xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value,
2319 const char *file, int super) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002320 const xmlChar *cur = value;
2321 xmlChar *base = NULL;
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002322 int res;
Daniel Veillarda7374592001-05-10 14:17:55 +00002323
2324 if ((cur == NULL) || (file == NULL))
2325 return(-1);
2326 base = xmlStrdup((const xmlChar *) file);
2327
Daniel Veillardbc2ddbe2001-08-23 10:24:27 +00002328 while ((cur != NULL) && (cur[0] != 0)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002329 SKIP_BLANKS;
Daniel Veillardbc2ddbe2001-08-23 10:24:27 +00002330 if (cur[0] == 0)
2331 break;
Daniel Veillarda7374592001-05-10 14:17:55 +00002332 if ((cur[0] == '-') && (cur[1] == '-')) {
Daniel Veillardcda96922001-08-21 10:56:31 +00002333 cur = xmlParseSGMLCatalogComment(cur);
Daniel Veillarda7374592001-05-10 14:17:55 +00002334 if (cur == NULL) {
2335 /* error */
2336 break;
2337 }
2338 } else {
2339 xmlChar *sysid = NULL;
2340 xmlChar *name = NULL;
2341 xmlCatalogEntryType type = XML_CATA_NONE;
2342
Daniel Veillardcda96922001-08-21 10:56:31 +00002343 cur = xmlParseSGMLCatalogName(cur, &name);
Daniel Veillarda7374592001-05-10 14:17:55 +00002344 if (name == NULL) {
2345 /* error */
2346 break;
2347 }
William M. Brack76e95df2003-10-18 16:20:14 +00002348 if (!IS_BLANK_CH(*cur)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002349 /* error */
2350 break;
2351 }
2352 SKIP_BLANKS;
2353 if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002354 type = SGML_CATA_SYSTEM;
Daniel Veillarda7374592001-05-10 14:17:55 +00002355 else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002356 type = SGML_CATA_PUBLIC;
Daniel Veillarda7374592001-05-10 14:17:55 +00002357 else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002358 type = SGML_CATA_DELEGATE;
Daniel Veillarda7374592001-05-10 14:17:55 +00002359 else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002360 type = SGML_CATA_ENTITY;
Daniel Veillarda7374592001-05-10 14:17:55 +00002361 else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002362 type = SGML_CATA_DOCTYPE;
Daniel Veillarda7374592001-05-10 14:17:55 +00002363 else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002364 type = SGML_CATA_LINKTYPE;
Daniel Veillarda7374592001-05-10 14:17:55 +00002365 else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002366 type = SGML_CATA_NOTATION;
Daniel Veillarda7374592001-05-10 14:17:55 +00002367 else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002368 type = SGML_CATA_SGMLDECL;
Daniel Veillarda7374592001-05-10 14:17:55 +00002369 else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002370 type = SGML_CATA_DOCUMENT;
Daniel Veillarda7374592001-05-10 14:17:55 +00002371 else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002372 type = SGML_CATA_CATALOG;
Daniel Veillarda7374592001-05-10 14:17:55 +00002373 else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002374 type = SGML_CATA_BASE;
Daniel Veillarda7374592001-05-10 14:17:55 +00002375 else if (xmlStrEqual(name, (const xmlChar *) "OVERRIDE")) {
2376 xmlFree(name);
Daniel Veillardcda96922001-08-21 10:56:31 +00002377 cur = xmlParseSGMLCatalogName(cur, &name);
Daniel Veillarda7374592001-05-10 14:17:55 +00002378 if (name == NULL) {
2379 /* error */
2380 break;
2381 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002382 xmlFree(name);
Daniel Veillarda7374592001-05-10 14:17:55 +00002383 continue;
2384 }
2385 xmlFree(name);
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002386 name = NULL;
Daniel Veillarda7374592001-05-10 14:17:55 +00002387
2388 switch(type) {
Daniel Veillard344cee72001-08-20 00:08:40 +00002389 case SGML_CATA_ENTITY:
Daniel Veillarda7374592001-05-10 14:17:55 +00002390 if (*cur == '%')
Daniel Veillard344cee72001-08-20 00:08:40 +00002391 type = SGML_CATA_PENTITY;
2392 case SGML_CATA_PENTITY:
2393 case SGML_CATA_DOCTYPE:
2394 case SGML_CATA_LINKTYPE:
2395 case SGML_CATA_NOTATION:
Daniel Veillardcda96922001-08-21 10:56:31 +00002396 cur = xmlParseSGMLCatalogName(cur, &name);
Daniel Veillarda7374592001-05-10 14:17:55 +00002397 if (cur == NULL) {
2398 /* error */
2399 break;
2400 }
William M. Brack76e95df2003-10-18 16:20:14 +00002401 if (!IS_BLANK_CH(*cur)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002402 /* error */
2403 break;
2404 }
2405 SKIP_BLANKS;
Daniel Veillardcda96922001-08-21 10:56:31 +00002406 cur = xmlParseSGMLCatalogPubid(cur, &sysid);
Daniel Veillarda7374592001-05-10 14:17:55 +00002407 if (cur == NULL) {
2408 /* error */
2409 break;
2410 }
2411 break;
Daniel Veillard344cee72001-08-20 00:08:40 +00002412 case SGML_CATA_PUBLIC:
2413 case SGML_CATA_SYSTEM:
2414 case SGML_CATA_DELEGATE:
Daniel Veillardcda96922001-08-21 10:56:31 +00002415 cur = xmlParseSGMLCatalogPubid(cur, &name);
Daniel Veillarda7374592001-05-10 14:17:55 +00002416 if (cur == NULL) {
2417 /* error */
2418 break;
2419 }
Daniel Veillardc8155052004-07-16 09:03:08 +00002420 if (type != SGML_CATA_SYSTEM) {
2421 xmlChar *normid;
2422
2423 normid = xmlCatalogNormalizePublic(name);
2424 if (normid != NULL) {
2425 if (name != NULL)
2426 xmlFree(name);
2427 if (*normid != 0)
2428 name = normid;
2429 else {
2430 xmlFree(normid);
2431 name = NULL;
2432 }
2433 }
2434 }
William M. Brack76e95df2003-10-18 16:20:14 +00002435 if (!IS_BLANK_CH(*cur)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002436 /* error */
2437 break;
2438 }
2439 SKIP_BLANKS;
Daniel Veillardcda96922001-08-21 10:56:31 +00002440 cur = xmlParseSGMLCatalogPubid(cur, &sysid);
Daniel Veillarda7374592001-05-10 14:17:55 +00002441 if (cur == NULL) {
2442 /* error */
2443 break;
2444 }
2445 break;
Daniel Veillard344cee72001-08-20 00:08:40 +00002446 case SGML_CATA_BASE:
2447 case SGML_CATA_CATALOG:
2448 case SGML_CATA_DOCUMENT:
2449 case SGML_CATA_SGMLDECL:
Daniel Veillardcda96922001-08-21 10:56:31 +00002450 cur = xmlParseSGMLCatalogPubid(cur, &sysid);
Daniel Veillarda7374592001-05-10 14:17:55 +00002451 if (cur == NULL) {
2452 /* error */
2453 break;
2454 }
2455 break;
2456 default:
2457 break;
2458 }
2459 if (cur == NULL) {
2460 if (name != NULL)
2461 xmlFree(name);
2462 if (sysid != NULL)
2463 xmlFree(sysid);
2464 break;
Daniel Veillard344cee72001-08-20 00:08:40 +00002465 } else if (type == SGML_CATA_BASE) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002466 if (base != NULL)
2467 xmlFree(base);
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002468 base = xmlStrdup(sysid);
Daniel Veillard344cee72001-08-20 00:08:40 +00002469 } else if ((type == SGML_CATA_PUBLIC) ||
2470 (type == SGML_CATA_SYSTEM)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002471 xmlChar *filename;
2472
2473 filename = xmlBuildURI(sysid, base);
2474 if (filename != NULL) {
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002475 xmlCatalogEntryPtr entry;
Daniel Veillarda7374592001-05-10 14:17:55 +00002476
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002477 entry = xmlNewCatalogEntry(type, name, filename,
William M. Brackb7b54de2004-10-06 16:38:01 +00002478 NULL, XML_CATA_PREFER_NONE, NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00002479 res = xmlHashAddEntry(catal->sgml, name, entry);
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002480 if (res < 0) {
2481 xmlFreeCatalogEntry(entry);
2482 }
2483 xmlFree(filename);
Daniel Veillarda7374592001-05-10 14:17:55 +00002484 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002485
Daniel Veillard344cee72001-08-20 00:08:40 +00002486 } else if (type == SGML_CATA_CATALOG) {
Daniel Veillard82d75332001-10-08 15:01:59 +00002487 if (super) {
2488 xmlCatalogEntryPtr entry;
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002489
Daniel Veillardc853b322001-11-06 15:24:37 +00002490 entry = xmlNewCatalogEntry(type, sysid, NULL, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00002491 XML_CATA_PREFER_NONE, NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00002492 res = xmlHashAddEntry(catal->sgml, sysid, entry);
Daniel Veillard82d75332001-10-08 15:01:59 +00002493 if (res < 0) {
2494 xmlFreeCatalogEntry(entry);
2495 }
2496 } else {
2497 xmlChar *filename;
2498
2499 filename = xmlBuildURI(sysid, base);
2500 if (filename != NULL) {
Daniel Veillard75b96822001-10-11 18:59:45 +00002501 xmlExpandCatalog(catal, (const char *)filename);
Daniel Veillard82d75332001-10-08 15:01:59 +00002502 xmlFree(filename);
2503 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002504 }
Daniel Veillarda7374592001-05-10 14:17:55 +00002505 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002506 /*
2507 * drop anything else we won't handle it
2508 */
2509 if (name != NULL)
2510 xmlFree(name);
2511 if (sysid != NULL)
2512 xmlFree(sysid);
Daniel Veillarda7374592001-05-10 14:17:55 +00002513 }
2514 }
2515 if (base != NULL)
2516 xmlFree(base);
2517 if (cur == NULL)
2518 return(-1);
2519 return(0);
2520}
2521
Daniel Veillard75b96822001-10-11 18:59:45 +00002522/************************************************************************
2523 * *
2524 * SGML Catalog handling *
2525 * *
2526 ************************************************************************/
2527
Daniel Veillardcda96922001-08-21 10:56:31 +00002528/**
2529 * xmlCatalogGetSGMLPublic:
2530 * @catal: an SGML catalog hash
Daniel Veillard06d25242004-02-25 13:01:42 +00002531 * @pubID: the public ID string
Daniel Veillardcda96922001-08-21 10:56:31 +00002532 *
Daniel Veillard06d25242004-02-25 13:01:42 +00002533 * Try to lookup the catalog local reference associated to a public ID
Daniel Veillardcda96922001-08-21 10:56:31 +00002534 *
Daniel Veillard06d25242004-02-25 13:01:42 +00002535 * Returns the local resource if found or NULL otherwise.
Daniel Veillardcda96922001-08-21 10:56:31 +00002536 */
2537static const xmlChar *
2538xmlCatalogGetSGMLPublic(xmlHashTablePtr catal, const xmlChar *pubID) {
2539 xmlCatalogEntryPtr entry;
Daniel Veillardc8155052004-07-16 09:03:08 +00002540 xmlChar *normid;
Daniel Veillardcda96922001-08-21 10:56:31 +00002541
2542 if (catal == NULL)
2543 return(NULL);
2544
Daniel Veillardc8155052004-07-16 09:03:08 +00002545 normid = xmlCatalogNormalizePublic(pubID);
2546 if (normid != NULL)
2547 pubID = (*normid != 0 ? normid : NULL);
2548
Daniel Veillardcda96922001-08-21 10:56:31 +00002549 entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, pubID);
Daniel Veillardc8155052004-07-16 09:03:08 +00002550 if (entry == NULL) {
2551 if (normid != NULL)
2552 xmlFree(normid);
Daniel Veillardcda96922001-08-21 10:56:31 +00002553 return(NULL);
Daniel Veillardc8155052004-07-16 09:03:08 +00002554 }
2555 if (entry->type == SGML_CATA_PUBLIC) {
2556 if (normid != NULL)
2557 xmlFree(normid);
Daniel Veillardc853b322001-11-06 15:24:37 +00002558 return(entry->URL);
Daniel Veillardc8155052004-07-16 09:03:08 +00002559 }
2560 if (normid != NULL)
2561 xmlFree(normid);
Daniel Veillardcda96922001-08-21 10:56:31 +00002562 return(NULL);
2563}
2564
2565/**
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002566 * xmlCatalogGetSGMLSystem:
2567 * @catal: an SGML catalog hash
Daniel Veillard06d25242004-02-25 13:01:42 +00002568 * @sysID: the system ID string
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002569 *
2570 * Try to lookup the catalog local reference for a system ID
2571 *
Daniel Veillard770075b2004-02-25 10:44:30 +00002572 * Returns the local resource if found or NULL otherwise.
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002573 */
2574static const xmlChar *
2575xmlCatalogGetSGMLSystem(xmlHashTablePtr catal, const xmlChar *sysID) {
2576 xmlCatalogEntryPtr entry;
2577
2578 if (catal == NULL)
2579 return(NULL);
2580
2581 entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, sysID);
2582 if (entry == NULL)
2583 return(NULL);
2584 if (entry->type == SGML_CATA_SYSTEM)
Daniel Veillardc853b322001-11-06 15:24:37 +00002585 return(entry->URL);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002586 return(NULL);
2587}
2588
2589/**
Daniel Veillardcda96922001-08-21 10:56:31 +00002590 * xmlCatalogSGMLResolve:
Daniel Veillard75b96822001-10-11 18:59:45 +00002591 * @catal: the SGML catalog
Daniel Veillard06d25242004-02-25 13:01:42 +00002592 * @pubID: the public ID string
2593 * @sysID: the system ID string
Daniel Veillardcda96922001-08-21 10:56:31 +00002594 *
2595 * Do a complete resolution lookup of an External Identifier
2596 *
2597 * Returns the URI of the resource or NULL if not found
2598 */
2599static const xmlChar *
Daniel Veillard75b96822001-10-11 18:59:45 +00002600xmlCatalogSGMLResolve(xmlCatalogPtr catal, const xmlChar *pubID,
2601 const xmlChar *sysID) {
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00002602 const xmlChar *ret = NULL;
2603
Daniel Veillard75b96822001-10-11 18:59:45 +00002604 if (catal->sgml == NULL)
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00002605 return(NULL);
2606
2607 if (pubID != NULL)
Daniel Veillard75b96822001-10-11 18:59:45 +00002608 ret = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00002609 if (ret != NULL)
2610 return(ret);
2611 if (sysID != NULL)
Daniel Veillard75b96822001-10-11 18:59:45 +00002612 ret = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
Daniel Veillard63806b52008-06-10 14:56:11 +00002613 if (ret != NULL)
2614 return(ret);
Daniel Veillardcda96922001-08-21 10:56:31 +00002615 return(NULL);
2616}
2617
Daniel Veillarda7374592001-05-10 14:17:55 +00002618/************************************************************************
2619 * *
Daniel Veillard75b96822001-10-11 18:59:45 +00002620 * Specific Public interfaces *
2621 * *
2622 ************************************************************************/
2623
2624/**
2625 * xmlLoadSGMLSuperCatalog:
2626 * @filename: a file path
2627 *
2628 * Load an SGML super catalog. It won't expand CATALOG or DELEGATE
2629 * references. This is only needed for manipulating SGML Super Catalogs
2630 * like adding and removing CATALOG or DELEGATE entries.
2631 *
2632 * Returns the catalog parsed or NULL in case of error
2633 */
2634xmlCatalogPtr
2635xmlLoadSGMLSuperCatalog(const char *filename)
2636{
2637 xmlChar *content;
2638 xmlCatalogPtr catal;
2639 int ret;
2640
2641 content = xmlLoadFileContent(filename);
2642 if (content == NULL)
2643 return(NULL);
2644
Daniel Veillardcd21dc72001-11-04 20:03:38 +00002645 catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
Daniel Veillard75b96822001-10-11 18:59:45 +00002646 if (catal == NULL) {
2647 xmlFree(content);
2648 return(NULL);
2649 }
2650
2651 ret = xmlParseSGMLCatalog(catal, content, filename, 1);
2652 xmlFree(content);
2653 if (ret < 0) {
2654 xmlFreeCatalog(catal);
2655 return(NULL);
2656 }
2657 return (catal);
2658}
2659
2660/**
2661 * xmlLoadACatalog:
2662 * @filename: a file path
2663 *
2664 * Load the catalog and build the associated data structures.
2665 * This can be either an XML Catalog or an SGML Catalog
2666 * It will recurse in SGML CATALOG entries. On the other hand XML
2667 * Catalogs are not handled recursively.
2668 *
2669 * Returns the catalog parsed or NULL in case of error
2670 */
2671xmlCatalogPtr
2672xmlLoadACatalog(const char *filename)
2673{
2674 xmlChar *content;
2675 xmlChar *first;
2676 xmlCatalogPtr catal;
2677 int ret;
2678
2679 content = xmlLoadFileContent(filename);
2680 if (content == NULL)
2681 return(NULL);
2682
2683
2684 first = content;
2685
2686 while ((*first != 0) && (*first != '-') && (*first != '<') &&
2687 (!(((*first >= 'A') && (*first <= 'Z')) ||
2688 ((*first >= 'a') && (*first <= 'z')))))
2689 first++;
2690
2691 if (*first != '<') {
Daniel Veillardcd21dc72001-11-04 20:03:38 +00002692 catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
Daniel Veillard75b96822001-10-11 18:59:45 +00002693 if (catal == NULL) {
2694 xmlFree(content);
2695 return(NULL);
2696 }
2697 ret = xmlParseSGMLCatalog(catal, content, filename, 0);
2698 if (ret < 0) {
2699 xmlFreeCatalog(catal);
2700 xmlFree(content);
2701 return(NULL);
2702 }
2703 } else {
Daniel Veillardcd21dc72001-11-04 20:03:38 +00002704 catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
Daniel Veillard75b96822001-10-11 18:59:45 +00002705 if (catal == NULL) {
2706 xmlFree(content);
2707 return(NULL);
2708 }
Daniel Veillardc853b322001-11-06 15:24:37 +00002709 catal->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00002710 NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00002711 }
2712 xmlFree(content);
2713 return (catal);
2714}
2715
2716/**
2717 * xmlExpandCatalog:
2718 * @catal: a catalog
2719 * @filename: a file path
2720 *
2721 * Load the catalog and expand the existing catal structure.
2722 * This can be either an XML Catalog or an SGML Catalog
2723 *
2724 * Returns 0 in case of success, -1 in case of error
2725 */
Daniel Veillard85c11fa2001-10-16 21:03:08 +00002726static int
Daniel Veillard75b96822001-10-11 18:59:45 +00002727xmlExpandCatalog(xmlCatalogPtr catal, const char *filename)
2728{
Daniel Veillard75b96822001-10-11 18:59:45 +00002729 int ret;
2730
2731 if ((catal == NULL) || (filename == NULL))
2732 return(-1);
2733
Daniel Veillard75b96822001-10-11 18:59:45 +00002734
2735 if (catal->type == XML_SGML_CATALOG_TYPE) {
Daniel Veillard85c11fa2001-10-16 21:03:08 +00002736 xmlChar *content;
2737
2738 content = xmlLoadFileContent(filename);
2739 if (content == NULL)
2740 return(-1);
2741
Daniel Veillard75b96822001-10-11 18:59:45 +00002742 ret = xmlParseSGMLCatalog(catal, content, filename, 0);
2743 if (ret < 0) {
2744 xmlFree(content);
2745 return(-1);
2746 }
Daniel Veillard85c11fa2001-10-16 21:03:08 +00002747 xmlFree(content);
Daniel Veillard75b96822001-10-11 18:59:45 +00002748 } else {
2749 xmlCatalogEntryPtr tmp, cur;
Daniel Veillardc853b322001-11-06 15:24:37 +00002750 tmp = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00002751 NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00002752
Daniel Veillard75b96822001-10-11 18:59:45 +00002753 cur = catal->xml;
2754 if (cur == NULL) {
2755 catal->xml = tmp;
2756 } else {
2757 while (cur->next != NULL) cur = cur->next;
2758 cur->next = tmp;
2759 }
Daniel Veillard75b96822001-10-11 18:59:45 +00002760 }
Daniel Veillard75b96822001-10-11 18:59:45 +00002761 return (0);
2762}
2763
2764/**
2765 * xmlACatalogResolveSystem:
2766 * @catal: a Catalog
Daniel Veillard06d25242004-02-25 13:01:42 +00002767 * @sysID: the system ID string
Daniel Veillard75b96822001-10-11 18:59:45 +00002768 *
2769 * Try to lookup the catalog resource for a system ID
2770 *
Daniel Veillard06d25242004-02-25 13:01:42 +00002771 * Returns the resource if found or NULL otherwise, the value returned
Daniel Veillard75b96822001-10-11 18:59:45 +00002772 * must be freed by the caller.
2773 */
2774xmlChar *
2775xmlACatalogResolveSystem(xmlCatalogPtr catal, const xmlChar *sysID) {
2776 xmlChar *ret = NULL;
2777
2778 if ((sysID == NULL) || (catal == NULL))
2779 return(NULL);
2780
2781 if (xmlDebugCatalogs)
2782 xmlGenericError(xmlGenericErrorContext,
2783 "Resolve sysID %s\n", sysID);
2784
2785 if (catal->type == XML_XML_CATALOG_TYPE) {
2786 ret = xmlCatalogListXMLResolve(catal->xml, NULL, sysID);
2787 if (ret == XML_CATAL_BREAK)
2788 ret = NULL;
2789 } else {
2790 const xmlChar *sgml;
2791
2792 sgml = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
2793 if (sgml != NULL)
2794 ret = xmlStrdup(sgml);
2795 }
2796 return(ret);
2797}
2798
2799/**
2800 * xmlACatalogResolvePublic:
2801 * @catal: a Catalog
Daniel Veillard5aad8322002-12-11 15:59:44 +00002802 * @pubID: the public ID string
Daniel Veillard75b96822001-10-11 18:59:45 +00002803 *
Daniel Veillard06d25242004-02-25 13:01:42 +00002804 * Try to lookup the catalog local reference associated to a public ID in that catalog
Daniel Veillard75b96822001-10-11 18:59:45 +00002805 *
Daniel Veillard06d25242004-02-25 13:01:42 +00002806 * Returns the local resource if found or NULL otherwise, the value returned
Daniel Veillard75b96822001-10-11 18:59:45 +00002807 * must be freed by the caller.
2808 */
2809xmlChar *
2810xmlACatalogResolvePublic(xmlCatalogPtr catal, const xmlChar *pubID) {
2811 xmlChar *ret = NULL;
2812
2813 if ((pubID == NULL) || (catal == NULL))
2814 return(NULL);
2815
2816 if (xmlDebugCatalogs)
2817 xmlGenericError(xmlGenericErrorContext,
2818 "Resolve pubID %s\n", pubID);
2819
2820 if (catal->type == XML_XML_CATALOG_TYPE) {
2821 ret = xmlCatalogListXMLResolve(catal->xml, pubID, NULL);
2822 if (ret == XML_CATAL_BREAK)
2823 ret = NULL;
2824 } else {
2825 const xmlChar *sgml;
2826
2827 sgml = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
2828 if (sgml != NULL)
2829 ret = xmlStrdup(sgml);
2830 }
2831 return(ret);
2832}
2833
2834/**
2835 * xmlACatalogResolve:
2836 * @catal: a Catalog
Daniel Veillard5aad8322002-12-11 15:59:44 +00002837 * @pubID: the public ID string
2838 * @sysID: the system ID string
Daniel Veillard75b96822001-10-11 18:59:45 +00002839 *
2840 * Do a complete resolution lookup of an External Identifier
2841 *
2842 * Returns the URI of the resource or NULL if not found, it must be freed
2843 * by the caller.
2844 */
2845xmlChar *
2846xmlACatalogResolve(xmlCatalogPtr catal, const xmlChar * pubID,
2847 const xmlChar * sysID)
2848{
2849 xmlChar *ret = NULL;
2850
2851 if (((pubID == NULL) && (sysID == NULL)) || (catal == NULL))
2852 return (NULL);
2853
2854 if (xmlDebugCatalogs) {
Daniel Veillard770075b2004-02-25 10:44:30 +00002855 if ((pubID != NULL) && (sysID != NULL)) {
2856 xmlGenericError(xmlGenericErrorContext,
2857 "Resolve: pubID %s sysID %s\n", pubID, sysID);
2858 } else if (pubID != NULL) {
2859 xmlGenericError(xmlGenericErrorContext,
2860 "Resolve: pubID %s\n", pubID);
2861 } else {
2862 xmlGenericError(xmlGenericErrorContext,
2863 "Resolve: sysID %s\n", sysID);
2864 }
Daniel Veillard75b96822001-10-11 18:59:45 +00002865 }
2866
2867 if (catal->type == XML_XML_CATALOG_TYPE) {
2868 ret = xmlCatalogListXMLResolve(catal->xml, pubID, sysID);
2869 if (ret == XML_CATAL_BREAK)
2870 ret = NULL;
2871 } else {
2872 const xmlChar *sgml;
2873
2874 sgml = xmlCatalogSGMLResolve(catal, pubID, sysID);
2875 if (sgml != NULL)
2876 ret = xmlStrdup(sgml);
2877 }
2878 return (ret);
2879}
2880
2881/**
2882 * xmlACatalogResolveURI:
2883 * @catal: a Catalog
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002884 * @URI: the URI
Daniel Veillard75b96822001-10-11 18:59:45 +00002885 *
2886 * Do a complete resolution lookup of an URI
2887 *
2888 * Returns the URI of the resource or NULL if not found, it must be freed
2889 * by the caller.
2890 */
2891xmlChar *
2892xmlACatalogResolveURI(xmlCatalogPtr catal, const xmlChar *URI) {
2893 xmlChar *ret = NULL;
2894
2895 if ((URI == NULL) || (catal == NULL))
2896 return(NULL);
2897
Daniel Veillardb44025c2001-10-11 22:55:55 +00002898 if (xmlDebugCatalogs)
Daniel Veillard75b96822001-10-11 18:59:45 +00002899 xmlGenericError(xmlGenericErrorContext,
2900 "Resolve URI %s\n", URI);
2901
2902 if (catal->type == XML_XML_CATALOG_TYPE) {
2903 ret = xmlCatalogListXMLResolveURI(catal->xml, URI);
2904 if (ret == XML_CATAL_BREAK)
2905 ret = NULL;
2906 } else {
2907 const xmlChar *sgml;
2908
2909 sgml = xmlCatalogSGMLResolve(catal, NULL, URI);
2910 if (sgml != NULL)
Daniel Veillard63806b52008-06-10 14:56:11 +00002911 ret = xmlStrdup(sgml);
Daniel Veillard75b96822001-10-11 18:59:45 +00002912 }
2913 return(ret);
2914}
2915
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002916#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard75b96822001-10-11 18:59:45 +00002917/**
2918 * xmlACatalogDump:
2919 * @catal: a Catalog
2920 * @out: the file.
2921 *
Daniel Veillarda8dc2882004-03-29 12:21:26 +00002922 * Dump the given catalog to the given file.
Daniel Veillard75b96822001-10-11 18:59:45 +00002923 */
2924void
2925xmlACatalogDump(xmlCatalogPtr catal, FILE *out) {
Daniel Veillardcd21dc72001-11-04 20:03:38 +00002926 if ((out == NULL) || (catal == NULL))
Daniel Veillard75b96822001-10-11 18:59:45 +00002927 return;
2928
2929 if (catal->type == XML_XML_CATALOG_TYPE) {
2930 xmlDumpXMLCatalog(out, catal->xml);
2931 } else {
2932 xmlHashScan(catal->sgml,
2933 (xmlHashScanner) xmlCatalogDumpEntry, out);
2934 }
2935}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002936#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard75b96822001-10-11 18:59:45 +00002937
2938/**
2939 * xmlACatalogAdd:
2940 * @catal: a Catalog
2941 * @type: the type of record to add to the catalog
2942 * @orig: the system, public or prefix to match
2943 * @replace: the replacement value for the match
2944 *
2945 * Add an entry in the catalog, it may overwrite existing but
2946 * different entries.
2947 *
2948 * Returns 0 if successful, -1 otherwise
2949 */
2950int
2951xmlACatalogAdd(xmlCatalogPtr catal, const xmlChar * type,
2952 const xmlChar * orig, const xmlChar * replace)
2953{
2954 int res = -1;
2955
2956 if (catal == NULL)
2957 return(-1);
2958
2959 if (catal->type == XML_XML_CATALOG_TYPE) {
2960 res = xmlAddXMLCatalog(catal->xml, type, orig, replace);
2961 } else {
2962 xmlCatalogEntryType cattype;
2963
2964 cattype = xmlGetSGMLCatalogEntryType(type);
2965 if (cattype != XML_CATA_NONE) {
2966 xmlCatalogEntryPtr entry;
2967
Daniel Veillardc853b322001-11-06 15:24:37 +00002968 entry = xmlNewCatalogEntry(cattype, orig, replace, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00002969 XML_CATA_PREFER_NONE, NULL);
Daniel Veillardcd21dc72001-11-04 20:03:38 +00002970 if (catal->sgml == NULL)
2971 catal->sgml = xmlHashCreate(10);
Daniel Veillard75b96822001-10-11 18:59:45 +00002972 res = xmlHashAddEntry(catal->sgml, orig, entry);
2973 }
2974 }
2975 return (res);
2976}
2977
2978/**
2979 * xmlACatalogRemove:
2980 * @catal: a Catalog
2981 * @value: the value to remove
2982 *
2983 * Remove an entry from the catalog
2984 *
2985 * Returns the number of entries removed if successful, -1 otherwise
2986 */
2987int
2988xmlACatalogRemove(xmlCatalogPtr catal, const xmlChar *value) {
2989 int res = -1;
2990
2991 if ((catal == NULL) || (value == NULL))
2992 return(-1);
2993
2994 if (catal->type == XML_XML_CATALOG_TYPE) {
2995 res = xmlDelXMLCatalog(catal->xml, value);
2996 } else {
2997 res = xmlHashRemoveEntry(catal->sgml, value,
2998 (xmlHashDeallocator) xmlFreeCatalogEntry);
2999 if (res == 0)
3000 res = 1;
3001 }
3002 return(res);
3003}
3004
Daniel Veillardcd21dc72001-11-04 20:03:38 +00003005/**
3006 * xmlNewCatalog:
3007 * @sgml: should this create an SGML catalog
3008 *
3009 * create a new Catalog.
3010 *
3011 * Returns the xmlCatalogPtr or NULL in case of error
3012 */
3013xmlCatalogPtr
3014xmlNewCatalog(int sgml) {
3015 xmlCatalogPtr catal = NULL;
3016
3017 if (sgml) {
3018 catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE,
3019 xmlCatalogDefaultPrefer);
3020 if ((catal != NULL) && (catal->sgml == NULL))
3021 catal->sgml = xmlHashCreate(10);
3022 } else
3023 catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3024 xmlCatalogDefaultPrefer);
3025 return(catal);
3026}
3027
3028/**
3029 * xmlCatalogIsEmpty:
3030 * @catal: should this create an SGML catalog
3031 *
3032 * Check is a catalog is empty
3033 *
3034 * Returns 1 if the catalog is empty, 0 if not, amd -1 in case of error.
3035 */
3036int
3037xmlCatalogIsEmpty(xmlCatalogPtr catal) {
3038 if (catal == NULL)
3039 return(-1);
3040
3041 if (catal->type == XML_XML_CATALOG_TYPE) {
3042 if (catal->xml == NULL)
3043 return(1);
3044 if ((catal->xml->type != XML_CATA_CATALOG) &&
3045 (catal->xml->type != XML_CATA_BROKEN_CATALOG))
3046 return(-1);
3047 if (catal->xml->children == NULL)
3048 return(1);
3049 return(0);
3050 } else {
3051 int res;
3052
3053 if (catal->sgml == NULL)
3054 return(1);
3055 res = xmlHashSize(catal->sgml);
3056 if (res == 0)
3057 return(1);
3058 if (res < 0)
3059 return(-1);
3060 }
3061 return(0);
3062}
3063
Daniel Veillard75b96822001-10-11 18:59:45 +00003064/************************************************************************
3065 * *
3066 * Public interfaces manipulating the global shared default catalog *
Daniel Veillarda7374592001-05-10 14:17:55 +00003067 * *
3068 ************************************************************************/
3069
Daniel Veillard5e2dace2001-07-18 19:30:27 +00003070/**
Daniel Veillard81463942001-10-16 12:34:39 +00003071 * xmlInitializeCatalogData:
3072 *
3073 * Do the catalog initialization only of global data, doesn't try to load
3074 * any catalog actually.
3075 * this function is not thread safe, catalog initialization should
3076 * preferably be done once at startup
3077 */
3078static void
3079xmlInitializeCatalogData(void) {
3080 if (xmlCatalogInitialized != 0)
3081 return;
3082
3083 if (getenv("XML_DEBUG_CATALOG"))
3084 xmlDebugCatalogs = 1;
3085 xmlCatalogMutex = xmlNewRMutex();
3086
3087 xmlCatalogInitialized = 1;
3088}
3089/**
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003090 * xmlInitializeCatalog:
3091 *
3092 * Do the catalog initialization.
Daniel Veillard81463942001-10-16 12:34:39 +00003093 * this function is not thread safe, catalog initialization should
3094 * preferably be done once at startup
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003095 */
3096void
3097xmlInitializeCatalog(void) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003098 if (xmlCatalogInitialized != 0)
3099 return;
3100
Daniel Veillard81463942001-10-16 12:34:39 +00003101 xmlInitializeCatalogData();
3102 xmlRMutexLock(xmlCatalogMutex);
3103
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003104 if (getenv("XML_DEBUG_CATALOG"))
3105 xmlDebugCatalogs = 1;
Daniel Veillard81463942001-10-16 12:34:39 +00003106
Daniel Veillard75b96822001-10-11 18:59:45 +00003107 if (xmlDefaultCatalog == NULL) {
3108 const char *catalogs;
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003109 char *path;
3110 const char *cur, *paths;
Daniel Veillard75b96822001-10-11 18:59:45 +00003111 xmlCatalogPtr catal;
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003112 xmlCatalogEntryPtr *nextent;
Daniel Veillard75b96822001-10-11 18:59:45 +00003113
Daniel Veillardb44025c2001-10-11 22:55:55 +00003114 catalogs = (const char *) getenv("XML_CATALOG_FILES");
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003115 if (catalogs == NULL)
Daniel Veillardfb382b82004-06-14 12:13:12 +00003116#if defined(_WIN32) && defined(_MSC_VER)
3117 {
3118 void* hmodule;
3119 hmodule = GetModuleHandleA("libxml2.dll");
3120 if (hmodule == NULL)
3121 hmodule = GetModuleHandleA(NULL);
3122 if (hmodule != NULL) {
3123 char buf[256];
3124 unsigned long len = GetModuleFileNameA(hmodule, buf, 255);
3125 if (len != 0) {
3126 char* p = &(buf[len]);
3127 while (*p != '\\' && p > buf)
3128 p--;
3129 if (p != buf) {
3130 xmlChar* uri;
3131 strncpy(p, "\\..\\etc\\catalog", 255 - (p - buf));
3132 uri = xmlCanonicPath(buf);
3133 if (uri != NULL) {
3134 strncpy(XML_XML_DEFAULT_CATALOG, uri, 255);
3135 xmlFree(uri);
3136 }
3137 }
3138 }
3139 }
3140 catalogs = XML_XML_DEFAULT_CATALOG;
3141 }
3142#else
Daniel Veillard75b96822001-10-11 18:59:45 +00003143 catalogs = XML_XML_DEFAULT_CATALOG;
Daniel Veillardfb382b82004-06-14 12:13:12 +00003144#endif
Daniel Veillard75b96822001-10-11 18:59:45 +00003145
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003146 catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3147 xmlCatalogDefaultPrefer);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00003148 if (catal != NULL) {
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003149 /* the XML_CATALOG_FILES envvar is allowed to contain a
3150 space-separated list of entries. */
3151 cur = catalogs;
3152 nextent = &catal->xml;
3153 while (*cur != '\0') {
William M. Brack68aca052003-10-11 15:22:13 +00003154 while (xmlIsBlank_ch(*cur))
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003155 cur++;
3156 if (*cur != 0) {
3157 paths = cur;
William M. Brack68aca052003-10-11 15:22:13 +00003158 while ((*cur != 0) && (!xmlIsBlank_ch(*cur)))
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003159 cur++;
Daniel Veillarde645e8c2002-10-22 17:35:37 +00003160 path = (char *) xmlStrndup((const xmlChar *)paths, cur - paths);
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003161 if (path != NULL) {
3162 *nextent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00003163 NULL, BAD_CAST path, xmlCatalogDefaultPrefer, NULL);
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003164 if (*nextent != NULL)
3165 nextent = &((*nextent)->next);
3166 xmlFree(path);
3167 }
3168 }
3169 }
Daniel Veillard85c11fa2001-10-16 21:03:08 +00003170 xmlDefaultCatalog = catal;
3171 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003172 }
3173
Daniel Veillard81463942001-10-16 12:34:39 +00003174 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003175}
3176
Daniel Veillard82d75332001-10-08 15:01:59 +00003177
3178/**
Daniel Veillarda7374592001-05-10 14:17:55 +00003179 * xmlLoadCatalog:
3180 * @filename: a file path
3181 *
Daniel Veillard81418e32001-05-22 15:08:55 +00003182 * Load the catalog and makes its definitions effective for the default
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003183 * external entity loader. It will recurse in SGML CATALOG entries.
Daniel Veillard81463942001-10-16 12:34:39 +00003184 * this function is not thread safe, catalog initialization should
3185 * preferably be done once at startup
Daniel Veillarda7374592001-05-10 14:17:55 +00003186 *
3187 * Returns 0 in case of success -1 in case of error
3188 */
3189int
Daniel Veillard16756b62001-10-01 07:36:25 +00003190xmlLoadCatalog(const char *filename)
3191{
Daniel Veillard75b96822001-10-11 18:59:45 +00003192 int ret;
3193 xmlCatalogPtr catal;
Daniel Veillard16756b62001-10-01 07:36:25 +00003194
Daniel Veillard81463942001-10-16 12:34:39 +00003195 if (!xmlCatalogInitialized)
3196 xmlInitializeCatalogData();
3197
3198 xmlRMutexLock(xmlCatalogMutex);
3199
Daniel Veillard75b96822001-10-11 18:59:45 +00003200 if (xmlDefaultCatalog == NULL) {
3201 catal = xmlLoadACatalog(filename);
William M. Brack59002e72003-07-04 17:01:59 +00003202 if (catal == NULL) {
3203 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003204 return(-1);
William M. Brack59002e72003-07-04 17:01:59 +00003205 }
Daniel Veillarda7374592001-05-10 14:17:55 +00003206
Daniel Veillard75b96822001-10-11 18:59:45 +00003207 xmlDefaultCatalog = catal;
Daniel Veillard81463942001-10-16 12:34:39 +00003208 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003209 return(0);
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00003210 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00003211
Daniel Veillard75b96822001-10-11 18:59:45 +00003212 ret = xmlExpandCatalog(xmlDefaultCatalog, filename);
Daniel Veillard81463942001-10-16 12:34:39 +00003213 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003214 return(ret);
Daniel Veillarda7374592001-05-10 14:17:55 +00003215}
3216
Daniel Veillard5e2dace2001-07-18 19:30:27 +00003217/**
Daniel Veillard81418e32001-05-22 15:08:55 +00003218 * xmlLoadCatalogs:
Daniel Veillard5aad8322002-12-11 15:59:44 +00003219 * @pathss: a list of directories separated by a colon or a space.
Daniel Veillard81418e32001-05-22 15:08:55 +00003220 *
3221 * Load the catalogs and makes their definitions effective for the default
3222 * external entity loader.
Daniel Veillard81463942001-10-16 12:34:39 +00003223 * this function is not thread safe, catalog initialization should
3224 * preferably be done once at startup
Daniel Veillard81418e32001-05-22 15:08:55 +00003225 */
3226void
3227xmlLoadCatalogs(const char *pathss) {
3228 const char *cur;
3229 const char *paths;
3230 xmlChar *path;
Daniel Veillarded121382007-04-17 12:33:19 +00003231#ifdef _WIN32
3232 int i, iLen;
3233#endif
Daniel Veillard81418e32001-05-22 15:08:55 +00003234
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003235 if (pathss == NULL)
3236 return;
3237
Daniel Veillard81418e32001-05-22 15:08:55 +00003238 cur = pathss;
Daniel Veillard2728f842006-03-09 16:49:24 +00003239 while (*cur != 0) {
William M. Brack68aca052003-10-11 15:22:13 +00003240 while (xmlIsBlank_ch(*cur)) cur++;
Daniel Veillard81418e32001-05-22 15:08:55 +00003241 if (*cur != 0) {
3242 paths = cur;
Daniel Veillarded121382007-04-17 12:33:19 +00003243 while ((*cur != 0) && (*cur != PATH_SEAPARATOR) && (!xmlIsBlank_ch(*cur)))
Daniel Veillard81418e32001-05-22 15:08:55 +00003244 cur++;
3245 path = xmlStrndup((const xmlChar *)paths, cur - paths);
Daniel Veillarded121382007-04-17 12:33:19 +00003246#ifdef _WIN32
3247 iLen = strlen(path);
3248 for(i = 0; i < iLen; i++) {
3249 if(path[i] == '\\') {
3250 path[i] = '/';
3251 }
3252 }
3253#endif
Daniel Veillard81418e32001-05-22 15:08:55 +00003254 if (path != NULL) {
3255 xmlLoadCatalog((const char *) path);
3256 xmlFree(path);
3257 }
3258 }
Daniel Veillarded121382007-04-17 12:33:19 +00003259 while (*cur == PATH_SEAPARATOR)
Igor Zlatkovic130e5792002-11-06 22:51:58 +00003260 cur++;
Daniel Veillard81418e32001-05-22 15:08:55 +00003261 }
3262}
3263
Daniel Veillarda7374592001-05-10 14:17:55 +00003264/**
3265 * xmlCatalogCleanup:
3266 *
3267 * Free up all the memory associated with catalogs
3268 */
3269void
3270xmlCatalogCleanup(void) {
Daniel Veillard364789a2001-10-16 12:45:00 +00003271 if (xmlCatalogInitialized == 0)
3272 return;
3273
Daniel Veillard81463942001-10-16 12:34:39 +00003274 xmlRMutexLock(xmlCatalogMutex);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003275 if (xmlDebugCatalogs)
3276 xmlGenericError(xmlGenericErrorContext,
3277 "Catalogs cleanup\n");
Daniel Veillard6990bf32001-08-23 21:17:48 +00003278 if (xmlCatalogXMLFiles != NULL)
Daniel Veillard85c11fa2001-10-16 21:03:08 +00003279 xmlHashFree(xmlCatalogXMLFiles,
3280 (xmlHashDeallocator)xmlFreeCatalogHashEntryList);
Daniel Veillard6990bf32001-08-23 21:17:48 +00003281 xmlCatalogXMLFiles = NULL;
Daniel Veillarda7374592001-05-10 14:17:55 +00003282 if (xmlDefaultCatalog != NULL)
Daniel Veillard75b96822001-10-11 18:59:45 +00003283 xmlFreeCatalog(xmlDefaultCatalog);
Daniel Veillard6990bf32001-08-23 21:17:48 +00003284 xmlDefaultCatalog = NULL;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003285 xmlDebugCatalogs = 0;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003286 xmlCatalogInitialized = 0;
Daniel Veillard81463942001-10-16 12:34:39 +00003287 xmlRMutexUnlock(xmlCatalogMutex);
3288 xmlFreeRMutex(xmlCatalogMutex);
Daniel Veillarda7374592001-05-10 14:17:55 +00003289}
3290
3291/**
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003292 * xmlCatalogResolveSystem:
Daniel Veillard06d25242004-02-25 13:01:42 +00003293 * @sysID: the system ID string
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003294 *
3295 * Try to lookup the catalog resource for a system ID
3296 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003297 * Returns the resource if found or NULL otherwise, the value returned
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003298 * must be freed by the caller.
3299 */
3300xmlChar *
3301xmlCatalogResolveSystem(const xmlChar *sysID) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003302 xmlChar *ret;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003303
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003304 if (!xmlCatalogInitialized)
3305 xmlInitializeCatalog();
3306
Daniel Veillard75b96822001-10-11 18:59:45 +00003307 ret = xmlACatalogResolveSystem(xmlDefaultCatalog, sysID);
3308 return(ret);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003309}
3310
3311/**
3312 * xmlCatalogResolvePublic:
Daniel Veillard5aad8322002-12-11 15:59:44 +00003313 * @pubID: the public ID string
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003314 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003315 * Try to lookup the catalog reference associated to a public ID
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003316 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003317 * Returns the resource if found or NULL otherwise, the value returned
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003318 * must be freed by the caller.
3319 */
3320xmlChar *
3321xmlCatalogResolvePublic(const xmlChar *pubID) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003322 xmlChar *ret;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003323
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003324 if (!xmlCatalogInitialized)
3325 xmlInitializeCatalog();
3326
Daniel Veillard75b96822001-10-11 18:59:45 +00003327 ret = xmlACatalogResolvePublic(xmlDefaultCatalog, pubID);
3328 return(ret);
Daniel Veillard7d6fd212001-05-10 15:34:11 +00003329}
Daniel Veillard344cee72001-08-20 00:08:40 +00003330
Daniel Veillard7d6fd212001-05-10 15:34:11 +00003331/**
Daniel Veillardcda96922001-08-21 10:56:31 +00003332 * xmlCatalogResolve:
Daniel Veillard5aad8322002-12-11 15:59:44 +00003333 * @pubID: the public ID string
3334 * @sysID: the system ID string
Daniel Veillardcda96922001-08-21 10:56:31 +00003335 *
3336 * Do a complete resolution lookup of an External Identifier
3337 *
3338 * Returns the URI of the resource or NULL if not found, it must be freed
3339 * by the caller.
3340 */
3341xmlChar *
3342xmlCatalogResolve(const xmlChar *pubID, const xmlChar *sysID) {
Daniel Veillard75b96822001-10-11 18:59:45 +00003343 xmlChar *ret;
Daniel Veillard6990bf32001-08-23 21:17:48 +00003344
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003345 if (!xmlCatalogInitialized)
3346 xmlInitializeCatalog();
3347
Daniel Veillard75b96822001-10-11 18:59:45 +00003348 ret = xmlACatalogResolve(xmlDefaultCatalog, pubID, sysID);
3349 return(ret);
Daniel Veillardcda96922001-08-21 10:56:31 +00003350}
3351
3352/**
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003353 * xmlCatalogResolveURI:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00003354 * @URI: the URI
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003355 *
3356 * Do a complete resolution lookup of an URI
3357 *
3358 * Returns the URI of the resource or NULL if not found, it must be freed
3359 * by the caller.
3360 */
3361xmlChar *
3362xmlCatalogResolveURI(const xmlChar *URI) {
Daniel Veillard75b96822001-10-11 18:59:45 +00003363 xmlChar *ret;
3364
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003365 if (!xmlCatalogInitialized)
3366 xmlInitializeCatalog();
3367
Daniel Veillard75b96822001-10-11 18:59:45 +00003368 ret = xmlACatalogResolveURI(xmlDefaultCatalog, URI);
3369 return(ret);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003370}
3371
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003372#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003373/**
Daniel Veillarda7374592001-05-10 14:17:55 +00003374 * xmlCatalogDump:
3375 * @out: the file.
3376 *
Daniel Veillarda8dc2882004-03-29 12:21:26 +00003377 * Dump all the global catalog content to the given file.
Daniel Veillarda7374592001-05-10 14:17:55 +00003378 */
3379void
3380xmlCatalogDump(FILE *out) {
3381 if (out == NULL)
3382 return;
Daniel Veillard344cee72001-08-20 00:08:40 +00003383
Daniel Veillard75b96822001-10-11 18:59:45 +00003384 if (!xmlCatalogInitialized)
3385 xmlInitializeCatalog();
3386
3387 xmlACatalogDump(xmlDefaultCatalog, out);
Daniel Veillard344cee72001-08-20 00:08:40 +00003388}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003389#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard344cee72001-08-20 00:08:40 +00003390
3391/**
3392 * xmlCatalogAdd:
3393 * @type: the type of record to add to the catalog
3394 * @orig: the system, public or prefix to match
3395 * @replace: the replacement value for the match
3396 *
3397 * Add an entry in the catalog, it may overwrite existing but
3398 * different entries.
Daniel Veillardcbaf3992001-12-31 16:16:02 +00003399 * If called before any other catalog routine, allows to override the
Daniel Veillard75b96822001-10-11 18:59:45 +00003400 * default shared catalog put in place by xmlInitializeCatalog();
Daniel Veillard344cee72001-08-20 00:08:40 +00003401 *
3402 * Returns 0 if successful, -1 otherwise
3403 */
3404int
3405xmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace) {
3406 int res = -1;
3407
Daniel Veillard81463942001-10-16 12:34:39 +00003408 if (!xmlCatalogInitialized)
3409 xmlInitializeCatalogData();
3410
3411 xmlRMutexLock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003412 /*
3413 * Specific case where one want to override the default catalog
3414 * put in place by xmlInitializeCatalog();
3415 */
3416 if ((xmlDefaultCatalog == NULL) &&
Daniel Veillarde7ead2d2001-08-22 23:44:09 +00003417 (xmlStrEqual(type, BAD_CAST "catalog"))) {
Daniel Veillardcd21dc72001-11-04 20:03:38 +00003418 xmlDefaultCatalog = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
Daniel Veillard75b96822001-10-11 18:59:45 +00003419 xmlCatalogDefaultPrefer);
3420 xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00003421 orig, NULL, xmlCatalogDefaultPrefer, NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00003422
Daniel Veillard81463942001-10-16 12:34:39 +00003423 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillarde7ead2d2001-08-22 23:44:09 +00003424 return(0);
3425 }
3426
Daniel Veillard75b96822001-10-11 18:59:45 +00003427 res = xmlACatalogAdd(xmlDefaultCatalog, type, orig, replace);
Daniel Veillard81463942001-10-16 12:34:39 +00003428 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillard344cee72001-08-20 00:08:40 +00003429 return(res);
3430}
3431
3432/**
3433 * xmlCatalogRemove:
3434 * @value: the value to remove
3435 *
3436 * Remove an entry from the catalog
3437 *
Daniel Veillard82d75332001-10-08 15:01:59 +00003438 * Returns the number of entries removed if successful, -1 otherwise
Daniel Veillard344cee72001-08-20 00:08:40 +00003439 */
3440int
3441xmlCatalogRemove(const xmlChar *value) {
Daniel Veillard75b96822001-10-11 18:59:45 +00003442 int res;
Daniel Veillardcda96922001-08-21 10:56:31 +00003443
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003444 if (!xmlCatalogInitialized)
3445 xmlInitializeCatalog();
3446
Daniel Veillard81463942001-10-16 12:34:39 +00003447 xmlRMutexLock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003448 res = xmlACatalogRemove(xmlDefaultCatalog, value);
Daniel Veillard81463942001-10-16 12:34:39 +00003449 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillardcda96922001-08-21 10:56:31 +00003450 return(res);
Daniel Veillard344cee72001-08-20 00:08:40 +00003451}
3452
3453/**
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003454 * xmlCatalogConvert:
3455 *
3456 * Convert all the SGML catalog entries as XML ones
3457 *
3458 * Returns the number of entries converted if successful, -1 otherwise
3459 */
3460int
3461xmlCatalogConvert(void) {
3462 int res = -1;
3463
3464 if (!xmlCatalogInitialized)
3465 xmlInitializeCatalog();
3466
Daniel Veillard81463942001-10-16 12:34:39 +00003467 xmlRMutexLock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003468 res = xmlConvertSGMLCatalog(xmlDefaultCatalog);
Daniel Veillard81463942001-10-16 12:34:39 +00003469 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003470 return(res);
3471}
3472
Daniel Veillard75b96822001-10-11 18:59:45 +00003473/************************************************************************
3474 * *
3475 * Public interface manipulating the common preferences *
3476 * *
3477 ************************************************************************/
Daniel Veillard81463942001-10-16 12:34:39 +00003478
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003479/**
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003480 * xmlCatalogGetDefaults:
3481 *
3482 * Used to get the user preference w.r.t. to what catalogs should
3483 * be accepted
3484 *
3485 * Returns the current xmlCatalogAllow value
3486 */
3487xmlCatalogAllow
3488xmlCatalogGetDefaults(void) {
3489 return(xmlCatalogDefaultAllow);
3490}
3491
3492/**
3493 * xmlCatalogSetDefaults:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00003494 * @allow: what catalogs should be accepted
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003495 *
3496 * Used to set the user preference w.r.t. to what catalogs should
3497 * be accepted
3498 */
3499void
3500xmlCatalogSetDefaults(xmlCatalogAllow allow) {
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003501 if (xmlDebugCatalogs) {
3502 switch (allow) {
3503 case XML_CATA_ALLOW_NONE:
3504 xmlGenericError(xmlGenericErrorContext,
3505 "Disabling catalog usage\n");
3506 break;
3507 case XML_CATA_ALLOW_GLOBAL:
3508 xmlGenericError(xmlGenericErrorContext,
3509 "Allowing only global catalogs\n");
3510 break;
3511 case XML_CATA_ALLOW_DOCUMENT:
3512 xmlGenericError(xmlGenericErrorContext,
3513 "Allowing only catalogs from the document\n");
3514 break;
3515 case XML_CATA_ALLOW_ALL:
3516 xmlGenericError(xmlGenericErrorContext,
3517 "Allowing all catalogs\n");
3518 break;
3519 }
3520 }
3521 xmlCatalogDefaultAllow = allow;
3522}
3523
3524/**
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003525 * xmlCatalogSetDefaultPrefer:
3526 * @prefer: the default preference for delegation
3527 *
3528 * Allows to set the preference between public and system for deletion
3529 * in XML Catalog resolution. C.f. section 4.1.1 of the spec
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003530 * Values accepted are XML_CATA_PREFER_PUBLIC or XML_CATA_PREFER_SYSTEM
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003531 *
3532 * Returns the previous value of the default preference for delegation
3533 */
3534xmlCatalogPrefer
3535xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer) {
3536 xmlCatalogPrefer ret = xmlCatalogDefaultPrefer;
3537
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003538 if (prefer == XML_CATA_PREFER_NONE)
3539 return(ret);
3540
3541 if (xmlDebugCatalogs) {
3542 switch (prefer) {
3543 case XML_CATA_PREFER_PUBLIC:
3544 xmlGenericError(xmlGenericErrorContext,
3545 "Setting catalog preference to PUBLIC\n");
3546 break;
3547 case XML_CATA_PREFER_SYSTEM:
3548 xmlGenericError(xmlGenericErrorContext,
3549 "Setting catalog preference to SYSTEM\n");
3550 break;
3551 case XML_CATA_PREFER_NONE:
3552 break;
3553 }
3554 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003555 xmlCatalogDefaultPrefer = prefer;
3556 return(ret);
3557}
3558
3559/**
Daniel Veillard344cee72001-08-20 00:08:40 +00003560 * xmlCatalogSetDebug:
3561 * @level: the debug level of catalogs required
3562 *
3563 * Used to set the debug level for catalog operation, 0 disable
3564 * debugging, 1 enable it
3565 *
3566 * Returns the previous value of the catalog debugging level
3567 */
3568int
3569xmlCatalogSetDebug(int level) {
3570 int ret = xmlDebugCatalogs;
3571
3572 if (level <= 0)
3573 xmlDebugCatalogs = 0;
3574 else
3575 xmlDebugCatalogs = level;
3576 return(ret);
Daniel Veillarda7374592001-05-10 14:17:55 +00003577}
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003578
Daniel Veillard75b96822001-10-11 18:59:45 +00003579/************************************************************************
3580 * *
3581 * Minimal interfaces used for per-document catalogs by the parser *
3582 * *
3583 ************************************************************************/
3584
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003585/**
3586 * xmlCatalogFreeLocal:
3587 * @catalogs: a document's list of catalogs
3588 *
3589 * Free up the memory associated to the catalog list
3590 */
3591void
3592xmlCatalogFreeLocal(void *catalogs) {
3593 xmlCatalogEntryPtr catal;
3594
Daniel Veillard81463942001-10-16 12:34:39 +00003595 if (!xmlCatalogInitialized)
3596 xmlInitializeCatalog();
3597
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003598 catal = (xmlCatalogEntryPtr) catalogs;
3599 if (catal != NULL)
3600 xmlFreeCatalogEntryList(catal);
3601}
3602
3603
3604/**
3605 * xmlCatalogAddLocal:
3606 * @catalogs: a document's list of catalogs
3607 * @URL: the URL to a new local catalog
3608 *
3609 * Add the new entry to the catalog list
3610 *
3611 * Returns the updated list
3612 */
3613void *
3614xmlCatalogAddLocal(void *catalogs, const xmlChar *URL) {
3615 xmlCatalogEntryPtr catal, add;
3616
3617 if (!xmlCatalogInitialized)
3618 xmlInitializeCatalog();
Daniel Veillard81463942001-10-16 12:34:39 +00003619
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003620 if (URL == NULL)
3621 return(catalogs);
3622
3623 if (xmlDebugCatalogs)
3624 xmlGenericError(xmlGenericErrorContext,
3625 "Adding document catalog %s\n", URL);
3626
Daniel Veillardc853b322001-11-06 15:24:37 +00003627 add = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, URL, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00003628 xmlCatalogDefaultPrefer, NULL);
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003629 if (add == NULL)
3630 return(catalogs);
3631
3632 catal = (xmlCatalogEntryPtr) catalogs;
3633 if (catal == NULL)
3634 return((void *) add);
3635
3636 while (catal->next != NULL)
3637 catal = catal->next;
3638 catal->next = add;
3639 return(catalogs);
3640}
3641
3642/**
3643 * xmlCatalogLocalResolve:
3644 * @catalogs: a document's list of catalogs
Daniel Veillard5aad8322002-12-11 15:59:44 +00003645 * @pubID: the public ID string
3646 * @sysID: the system ID string
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003647 *
3648 * Do a complete resolution lookup of an External Identifier using a
3649 * document's private catalog list
3650 *
3651 * Returns the URI of the resource or NULL if not found, it must be freed
3652 * by the caller.
3653 */
3654xmlChar *
3655xmlCatalogLocalResolve(void *catalogs, const xmlChar *pubID,
3656 const xmlChar *sysID) {
3657 xmlCatalogEntryPtr catal;
Daniel Veillard6990bf32001-08-23 21:17:48 +00003658 xmlChar *ret;
3659
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003660 if (!xmlCatalogInitialized)
3661 xmlInitializeCatalog();
Daniel Veillard6990bf32001-08-23 21:17:48 +00003662
Daniel Veillard81463942001-10-16 12:34:39 +00003663 if ((pubID == NULL) && (sysID == NULL))
3664 return(NULL);
3665
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003666 if (xmlDebugCatalogs) {
Daniel Veillard770075b2004-02-25 10:44:30 +00003667 if ((pubID != NULL) && (sysID != NULL)) {
3668 xmlGenericError(xmlGenericErrorContext,
3669 "Local Resolve: pubID %s sysID %s\n", pubID, sysID);
3670 } else if (pubID != NULL) {
3671 xmlGenericError(xmlGenericErrorContext,
3672 "Local Resolve: pubID %s\n", pubID);
3673 } else {
3674 xmlGenericError(xmlGenericErrorContext,
3675 "Local Resolve: sysID %s\n", sysID);
3676 }
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003677 }
Daniel Veillard6990bf32001-08-23 21:17:48 +00003678
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003679 catal = (xmlCatalogEntryPtr) catalogs;
3680 if (catal == NULL)
3681 return(NULL);
Daniel Veillard6990bf32001-08-23 21:17:48 +00003682 ret = xmlCatalogListXMLResolve(catal, pubID, sysID);
3683 if ((ret != NULL) && (ret != XML_CATAL_BREAK))
3684 return(ret);
3685 return(NULL);
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003686}
3687
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003688/**
3689 * xmlCatalogLocalResolveURI:
3690 * @catalogs: a document's list of catalogs
Daniel Veillardcbaf3992001-12-31 16:16:02 +00003691 * @URI: the URI
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003692 *
3693 * Do a complete resolution lookup of an URI using a
3694 * document's private catalog list
3695 *
3696 * Returns the URI of the resource or NULL if not found, it must be freed
3697 * by the caller.
3698 */
3699xmlChar *
3700xmlCatalogLocalResolveURI(void *catalogs, const xmlChar *URI) {
3701 xmlCatalogEntryPtr catal;
Daniel Veillard6990bf32001-08-23 21:17:48 +00003702 xmlChar *ret;
3703
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003704 if (!xmlCatalogInitialized)
3705 xmlInitializeCatalog();
Daniel Veillard6990bf32001-08-23 21:17:48 +00003706
Daniel Veillard81463942001-10-16 12:34:39 +00003707 if (URI == NULL)
3708 return(NULL);
3709
Daniel Veillard6990bf32001-08-23 21:17:48 +00003710 if (xmlDebugCatalogs)
3711 xmlGenericError(xmlGenericErrorContext,
3712 "Resolve URI %s\n", URI);
3713
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003714 catal = (xmlCatalogEntryPtr) catalogs;
3715 if (catal == NULL)
3716 return(NULL);
Daniel Veillard6990bf32001-08-23 21:17:48 +00003717 ret = xmlCatalogListXMLResolveURI(catal, URI);
3718 if ((ret != NULL) && (ret != XML_CATAL_BREAK))
3719 return(ret);
3720 return(NULL);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003721}
3722
Daniel Veillard75b96822001-10-11 18:59:45 +00003723/************************************************************************
3724 * *
3725 * Deprecated interfaces *
3726 * *
3727 ************************************************************************/
3728/**
3729 * xmlCatalogGetSystem:
Daniel Veillard5aad8322002-12-11 15:59:44 +00003730 * @sysID: the system ID string
Daniel Veillard75b96822001-10-11 18:59:45 +00003731 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003732 * Try to lookup the catalog reference associated to a system ID
Daniel Veillard75b96822001-10-11 18:59:45 +00003733 * DEPRECATED, use xmlCatalogResolveSystem()
3734 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003735 * Returns the resource if found or NULL otherwise.
Daniel Veillard75b96822001-10-11 18:59:45 +00003736 */
3737const xmlChar *
3738xmlCatalogGetSystem(const xmlChar *sysID) {
Daniel Veillardab690c52004-06-14 12:19:09 +00003739 xmlChar *ret;
3740 static xmlChar result[1000];
3741 static int msg = 0;
3742
3743 if (!xmlCatalogInitialized)
3744 xmlInitializeCatalog();
3745
3746 if (msg == 0) {
3747 xmlGenericError(xmlGenericErrorContext,
3748 "Use of deprecated xmlCatalogGetSystem() call\n");
3749 msg++;
3750 }
3751
3752 if (sysID == NULL)
3753 return(NULL);
3754
3755 /*
3756 * Check first the XML catalogs
3757 */
3758 if (xmlDefaultCatalog != NULL) {
3759 ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, NULL, sysID);
3760 if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
3761 snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
3762 result[sizeof(result) - 1] = 0;
3763 return(result);
3764 }
3765 }
3766
3767 if (xmlDefaultCatalog != NULL)
3768 return(xmlCatalogGetSGMLSystem(xmlDefaultCatalog->sgml, sysID));
3769 return(NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00003770}
3771
3772/**
3773 * xmlCatalogGetPublic:
Daniel Veillard5aad8322002-12-11 15:59:44 +00003774 * @pubID: the public ID string
Daniel Veillard75b96822001-10-11 18:59:45 +00003775 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003776 * Try to lookup the catalog reference associated to a public ID
Daniel Veillard75b96822001-10-11 18:59:45 +00003777 * DEPRECATED, use xmlCatalogResolvePublic()
3778 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003779 * Returns the resource if found or NULL otherwise.
Daniel Veillard75b96822001-10-11 18:59:45 +00003780 */
3781const xmlChar *
3782xmlCatalogGetPublic(const xmlChar *pubID) {
Daniel Veillardab690c52004-06-14 12:19:09 +00003783 xmlChar *ret;
3784 static xmlChar result[1000];
3785 static int msg = 0;
3786
3787 if (!xmlCatalogInitialized)
3788 xmlInitializeCatalog();
3789
3790 if (msg == 0) {
3791 xmlGenericError(xmlGenericErrorContext,
3792 "Use of deprecated xmlCatalogGetPublic() call\n");
3793 msg++;
3794 }
3795
3796 if (pubID == NULL)
3797 return(NULL);
3798
3799 /*
3800 * Check first the XML catalogs
3801 */
3802 if (xmlDefaultCatalog != NULL) {
3803 ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, pubID, NULL);
3804 if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
3805 snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
3806 result[sizeof(result) - 1] = 0;
3807 return(result);
3808 }
3809 }
3810
3811 if (xmlDefaultCatalog != NULL)
3812 return(xmlCatalogGetSGMLPublic(xmlDefaultCatalog->sgml, pubID));
3813 return(NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00003814}
3815
Daniel Veillard5d4644e2005-04-01 13:11:58 +00003816#define bottom_catalog
3817#include "elfgcchack.h"
Daniel Veillarda7374592001-05-10 14:17:55 +00003818#endif /* LIBXML_CATALOG_ENABLED */