blob: 401e95c7e18253ae3d485f3aa67f3d3be561d846 [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 Veillard2a1d2422012-07-16 14:38:14 +0800917 inputStream->cur =
918 inputStream->base = xmlBufContent(buf->buffer);
919 inputStream->end = xmlBufEnd(buf->buffer);
Daniel Veillard9f7b84b2001-08-23 15:31:19 +0000920
921 inputPush(ctxt, inputStream);
922 if ((ctxt->directory == NULL) && (directory == NULL))
923 directory = xmlParserGetDirectory(filename);
924 if ((ctxt->directory == NULL) && (directory != NULL))
925 ctxt->directory = directory;
Daniel Veillard6990bf32001-08-23 21:17:48 +0000926 ctxt->valid = 0;
927 ctxt->validate = 0;
928 ctxt->loadsubset = 0;
929 ctxt->pedantic = 0;
Daniel Veillard03a53c32004-10-26 16:06:51 +0000930 ctxt->dictNames = 1;
Daniel Veillard9f7b84b2001-08-23 15:31:19 +0000931
932 xmlParseDocument(ctxt);
933
934 if (ctxt->wellFormed)
935 ret = ctxt->myDoc;
936 else {
937 ret = NULL;
938 xmlFreeDoc(ctxt->myDoc);
939 ctxt->myDoc = NULL;
940 }
941 xmlFreeParserCtxt(ctxt);
942
943 return(ret);
944}
945
Daniel Veillard75b96822001-10-11 18:59:45 +0000946/**
947 * xmlLoadFileContent:
948 * @filename: a file path
949 *
950 * Load a file content into memory.
951 *
952 * Returns a pointer to the 0 terminated string or NULL in case of error
953 */
954static xmlChar *
955xmlLoadFileContent(const char *filename)
956{
957#ifdef HAVE_STAT
958 int fd;
959#else
960 FILE *fd;
961#endif
962 int len;
963 long size;
964
965#ifdef HAVE_STAT
966 struct stat info;
967#endif
968 xmlChar *content;
969
970 if (filename == NULL)
971 return (NULL);
972
973#ifdef HAVE_STAT
974 if (stat(filename, &info) < 0)
975 return (NULL);
976#endif
977
978#ifdef HAVE_STAT
Daniel Veillard5aad8322002-12-11 15:59:44 +0000979 if ((fd = open(filename, O_RDONLY)) < 0)
Daniel Veillard75b96822001-10-11 18:59:45 +0000980#else
Daniel Veillard5aad8322002-12-11 15:59:44 +0000981 if ((fd = fopen(filename, "rb")) == NULL)
Daniel Veillard75b96822001-10-11 18:59:45 +0000982#endif
Daniel Veillard5aad8322002-12-11 15:59:44 +0000983 {
Daniel Veillard75b96822001-10-11 18:59:45 +0000984 return (NULL);
985 }
986#ifdef HAVE_STAT
987 size = info.st_size;
988#else
989 if (fseek(fd, 0, SEEK_END) || (size = ftell(fd)) == EOF || fseek(fd, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */
990 fclose(fd);
991 return (NULL);
992 }
993#endif
Daniel Veillard3c908dc2003-04-19 00:07:51 +0000994 content = xmlMallocAtomic(size + 10);
Daniel Veillard75b96822001-10-11 18:59:45 +0000995 if (content == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +0000996 xmlCatalogErrMemory("allocating catalog data");
Daniel Veillard75b96822001-10-11 18:59:45 +0000997 return (NULL);
998 }
999#ifdef HAVE_STAT
1000 len = read(fd, content, size);
Carlo Braminic43ac662010-10-14 14:27:54 +02001001 close(fd);
Daniel Veillard75b96822001-10-11 18:59:45 +00001002#else
1003 len = fread(content, 1, size, fd);
Carlo Braminic43ac662010-10-14 14:27:54 +02001004 fclose(fd);
Daniel Veillard75b96822001-10-11 18:59:45 +00001005#endif
1006 if (len < 0) {
1007 xmlFree(content);
1008 return (NULL);
1009 }
Daniel Veillard75b96822001-10-11 18:59:45 +00001010 content[len] = 0;
1011
1012 return(content);
1013}
1014
Daniel Veillardc8155052004-07-16 09:03:08 +00001015/**
1016 * xmlCatalogNormalizePublic:
1017 * @pubID: the public ID string
1018 *
1019 * Normalizes the Public Identifier
1020 *
1021 * Implements 6.2. Public Identifier Normalization
1022 * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1023 *
1024 * Returns the new string or NULL, the string must be deallocated
1025 * by the caller.
1026 */
1027static xmlChar *
1028xmlCatalogNormalizePublic(const xmlChar *pubID)
1029{
1030 int ok = 1;
1031 int white;
1032 const xmlChar *p;
1033 xmlChar *ret;
1034 xmlChar *q;
1035
1036 if (pubID == NULL)
1037 return(NULL);
1038
1039 white = 1;
1040 for (p = pubID;*p != 0 && ok;p++) {
1041 if (!xmlIsBlank_ch(*p))
1042 white = 0;
1043 else if (*p == 0x20 && !white)
1044 white = 1;
1045 else
1046 ok = 0;
1047 }
1048 if (ok && !white) /* is normalized */
1049 return(NULL);
1050
1051 ret = xmlStrdup(pubID);
1052 q = ret;
1053 white = 0;
1054 for (p = pubID;*p != 0;p++) {
1055 if (xmlIsBlank_ch(*p)) {
1056 if (q != ret)
1057 white = 1;
1058 } else {
1059 if (white) {
1060 *(q++) = 0x20;
1061 white = 0;
1062 }
1063 *(q++) = *p;
1064 }
1065 }
1066 *q = 0;
1067 return(ret);
1068}
1069
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001070/************************************************************************
1071 * *
Daniel Veillard344cee72001-08-20 00:08:40 +00001072 * The XML Catalog parser *
1073 * *
1074 ************************************************************************/
1075
1076static xmlCatalogEntryPtr
1077xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename);
Daniel Veillard344cee72001-08-20 00:08:40 +00001078static void
1079xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
William M. Brackb7b54de2004-10-06 16:38:01 +00001080 xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup);
Daniel Veillardcda96922001-08-21 10:56:31 +00001081static xmlChar *
1082xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1083 const xmlChar *sysID);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001084static xmlChar *
1085xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI);
1086
Daniel Veillard344cee72001-08-20 00:08:40 +00001087
Daniel Veillard75b96822001-10-11 18:59:45 +00001088/**
1089 * xmlGetXMLCatalogEntryType:
1090 * @name: the name
1091 *
1092 * lookup the internal type associated to an XML catalog entry name
1093 *
Daniel Veillard06d25242004-02-25 13:01:42 +00001094 * Returns the type associated with that name
Daniel Veillard75b96822001-10-11 18:59:45 +00001095 */
Daniel Veillard344cee72001-08-20 00:08:40 +00001096static xmlCatalogEntryType
1097xmlGetXMLCatalogEntryType(const xmlChar *name) {
1098 xmlCatalogEntryType type = XML_CATA_NONE;
1099 if (xmlStrEqual(name, (const xmlChar *) "system"))
1100 type = XML_CATA_SYSTEM;
1101 else if (xmlStrEqual(name, (const xmlChar *) "public"))
1102 type = XML_CATA_PUBLIC;
1103 else if (xmlStrEqual(name, (const xmlChar *) "rewriteSystem"))
1104 type = XML_CATA_REWRITE_SYSTEM;
1105 else if (xmlStrEqual(name, (const xmlChar *) "delegatePublic"))
1106 type = XML_CATA_DELEGATE_PUBLIC;
1107 else if (xmlStrEqual(name, (const xmlChar *) "delegateSystem"))
1108 type = XML_CATA_DELEGATE_SYSTEM;
1109 else if (xmlStrEqual(name, (const xmlChar *) "uri"))
1110 type = XML_CATA_URI;
1111 else if (xmlStrEqual(name, (const xmlChar *) "rewriteURI"))
1112 type = XML_CATA_REWRITE_URI;
1113 else if (xmlStrEqual(name, (const xmlChar *) "delegateURI"))
1114 type = XML_CATA_DELEGATE_URI;
1115 else if (xmlStrEqual(name, (const xmlChar *) "nextCatalog"))
1116 type = XML_CATA_NEXT_CATALOG;
1117 else if (xmlStrEqual(name, (const xmlChar *) "catalog"))
1118 type = XML_CATA_CATALOG;
1119 return(type);
1120}
1121
Daniel Veillard75b96822001-10-11 18:59:45 +00001122/**
1123 * xmlParseXMLCatalogOneNode:
1124 * @cur: the XML node
1125 * @type: the type of Catalog entry
1126 * @name: the name of the node
1127 * @attrName: the attribute holding the value
1128 * @uriAttrName: the attribute holding the URI-Reference
1129 * @prefer: the PUBLIC vs. SYSTEM current preference value
William M. Brackb7b54de2004-10-06 16:38:01 +00001130 * @cgroup: the group which includes this node
Daniel Veillard75b96822001-10-11 18:59:45 +00001131 *
1132 * Finishes the examination of an XML tree node of a catalog and build
1133 * a Catalog entry from it.
1134 *
1135 * Returns the new Catalog entry node or NULL in case of error.
1136 */
Daniel Veillard344cee72001-08-20 00:08:40 +00001137static xmlCatalogEntryPtr
1138xmlParseXMLCatalogOneNode(xmlNodePtr cur, xmlCatalogEntryType type,
1139 const xmlChar *name, const xmlChar *attrName,
William M. Brackb7b54de2004-10-06 16:38:01 +00001140 const xmlChar *uriAttrName, xmlCatalogPrefer prefer,
1141 xmlCatalogEntryPtr cgroup) {
Daniel Veillard344cee72001-08-20 00:08:40 +00001142 int ok = 1;
1143 xmlChar *uriValue;
1144 xmlChar *nameValue = NULL;
1145 xmlChar *base = NULL;
1146 xmlChar *URL = NULL;
1147 xmlCatalogEntryPtr ret = NULL;
1148
1149 if (attrName != NULL) {
1150 nameValue = xmlGetProp(cur, attrName);
1151 if (nameValue == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001152 xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
1153 "%s entry lacks '%s'\n", name, attrName, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001154 ok = 0;
1155 }
1156 }
1157 uriValue = xmlGetProp(cur, uriAttrName);
1158 if (uriValue == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001159 xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
1160 "%s entry lacks '%s'\n", name, uriAttrName, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001161 ok = 0;
1162 }
1163 if (!ok) {
1164 if (nameValue != NULL)
1165 xmlFree(nameValue);
1166 if (uriValue != NULL)
1167 xmlFree(uriValue);
1168 return(NULL);
1169 }
1170
1171 base = xmlNodeGetBase(cur->doc, cur);
1172 URL = xmlBuildURI(uriValue, base);
1173 if (URL != NULL) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001174 if (xmlDebugCatalogs > 1) {
Daniel Veillard344cee72001-08-20 00:08:40 +00001175 if (nameValue != NULL)
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001176 xmlGenericError(xmlGenericErrorContext,
1177 "Found %s: '%s' '%s'\n", name, nameValue, URL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001178 else
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001179 xmlGenericError(xmlGenericErrorContext,
1180 "Found %s: '%s'\n", name, URL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001181 }
William M. Brackb7b54de2004-10-06 16:38:01 +00001182 ret = xmlNewCatalogEntry(type, nameValue, uriValue, URL, prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001183 } else {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001184 xmlCatalogErr(ret, cur, XML_CATALOG_ENTRY_BROKEN,
Daniel Veillard344cee72001-08-20 00:08:40 +00001185 "%s entry '%s' broken ?: %s\n", name, uriAttrName, uriValue);
1186 }
1187 if (nameValue != NULL)
1188 xmlFree(nameValue);
1189 if (uriValue != NULL)
1190 xmlFree(uriValue);
1191 if (base != NULL)
1192 xmlFree(base);
1193 if (URL != NULL)
1194 xmlFree(URL);
1195 return(ret);
1196}
1197
Daniel Veillard75b96822001-10-11 18:59:45 +00001198/**
1199 * xmlParseXMLCatalogNode:
1200 * @cur: the XML node
1201 * @prefer: the PUBLIC vs. SYSTEM current preference value
1202 * @parent: the parent Catalog entry
William M. Brackb7b54de2004-10-06 16:38:01 +00001203 * @cgroup: the group which includes this node
Daniel Veillard75b96822001-10-11 18:59:45 +00001204 *
1205 * Examines an XML tree node of a catalog and build
1206 * a Catalog entry from it adding it to its parent. The examination can
1207 * be recursive.
1208 */
Daniel Veillard344cee72001-08-20 00:08:40 +00001209static void
1210xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer,
William M. Brackb7b54de2004-10-06 16:38:01 +00001211 xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup)
Daniel Veillard344cee72001-08-20 00:08:40 +00001212{
Daniel Veillard344cee72001-08-20 00:08:40 +00001213 xmlChar *base = NULL;
1214 xmlCatalogEntryPtr entry = NULL;
1215
1216 if (cur == NULL)
1217 return;
1218 if (xmlStrEqual(cur->name, BAD_CAST "group")) {
1219 xmlChar *prop;
William M. Brackb7b54de2004-10-06 16:38:01 +00001220 xmlCatalogPrefer pref = XML_CATA_PREFER_NONE;
Daniel Veillard344cee72001-08-20 00:08:40 +00001221
1222 prop = xmlGetProp(cur, BAD_CAST "prefer");
1223 if (prop != NULL) {
1224 if (xmlStrEqual(prop, BAD_CAST "system")) {
1225 prefer = XML_CATA_PREFER_SYSTEM;
1226 } else if (xmlStrEqual(prop, BAD_CAST "public")) {
1227 prefer = XML_CATA_PREFER_PUBLIC;
1228 } else {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001229 xmlCatalogErr(parent, cur, XML_CATALOG_PREFER_VALUE,
1230 "Invalid value for prefer: '%s'\n",
1231 prop, NULL, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001232 }
1233 xmlFree(prop);
William M. Brackb7b54de2004-10-06 16:38:01 +00001234 pref = prefer;
Daniel Veillard344cee72001-08-20 00:08:40 +00001235 }
William M. Brackb7b54de2004-10-06 16:38:01 +00001236 prop = xmlGetProp(cur, BAD_CAST "id");
1237 base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE);
1238 entry = xmlNewCatalogEntry(XML_CATA_GROUP, prop, base, NULL, pref, cgroup);
William M. Brack181a1ca2004-10-06 18:00:29 +00001239 xmlFree(prop);
Daniel Veillard344cee72001-08-20 00:08:40 +00001240 } else if (xmlStrEqual(cur->name, BAD_CAST "public")) {
1241 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_PUBLIC,
William M. Brackb7b54de2004-10-06 16:38:01 +00001242 BAD_CAST "public", BAD_CAST "publicId", BAD_CAST "uri", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001243 } else if (xmlStrEqual(cur->name, BAD_CAST "system")) {
1244 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_SYSTEM,
William M. Brackb7b54de2004-10-06 16:38:01 +00001245 BAD_CAST "system", BAD_CAST "systemId", BAD_CAST "uri", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001246 } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteSystem")) {
1247 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_SYSTEM,
1248 BAD_CAST "rewriteSystem", BAD_CAST "systemIdStartString",
William M. Brackb7b54de2004-10-06 16:38:01 +00001249 BAD_CAST "rewritePrefix", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001250 } else if (xmlStrEqual(cur->name, BAD_CAST "delegatePublic")) {
1251 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_PUBLIC,
1252 BAD_CAST "delegatePublic", BAD_CAST "publicIdStartString",
William M. Brackb7b54de2004-10-06 16:38:01 +00001253 BAD_CAST "catalog", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001254 } else if (xmlStrEqual(cur->name, BAD_CAST "delegateSystem")) {
1255 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_SYSTEM,
1256 BAD_CAST "delegateSystem", BAD_CAST "systemIdStartString",
William M. Brackb7b54de2004-10-06 16:38:01 +00001257 BAD_CAST "catalog", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001258 } else if (xmlStrEqual(cur->name, BAD_CAST "uri")) {
1259 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_URI,
1260 BAD_CAST "uri", BAD_CAST "name",
William M. Brackb7b54de2004-10-06 16:38:01 +00001261 BAD_CAST "uri", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001262 } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteURI")) {
1263 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_URI,
1264 BAD_CAST "rewriteURI", BAD_CAST "uriStartString",
William M. Brackb7b54de2004-10-06 16:38:01 +00001265 BAD_CAST "rewritePrefix", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001266 } else if (xmlStrEqual(cur->name, BAD_CAST "delegateURI")) {
1267 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_URI,
1268 BAD_CAST "delegateURI", BAD_CAST "uriStartString",
William M. Brackb7b54de2004-10-06 16:38:01 +00001269 BAD_CAST "catalog", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001270 } else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) {
1271 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG,
1272 BAD_CAST "nextCatalog", NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00001273 BAD_CAST "catalog", prefer, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001274 }
William M. Brackb031cef2004-11-05 16:34:22 +00001275 if (entry != NULL) {
1276 if (parent != NULL) {
1277 entry->parent = parent;
1278 if (parent->children == NULL)
1279 parent->children = entry;
1280 else {
1281 xmlCatalogEntryPtr prev;
Daniel Veillard344cee72001-08-20 00:08:40 +00001282
William M. Brackb031cef2004-11-05 16:34:22 +00001283 prev = parent->children;
1284 while (prev->next != NULL)
1285 prev = prev->next;
1286 prev->next = entry;
1287 }
Daniel Veillard344cee72001-08-20 00:08:40 +00001288 }
William M. Brackb031cef2004-11-05 16:34:22 +00001289 if (entry->type == XML_CATA_GROUP) {
1290 /*
1291 * Recurse to propagate prefer to the subtree
1292 * (xml:base handling is automated)
1293 */
1294 xmlParseXMLCatalogNodeList(cur->children, prefer, parent, entry);
1295 }
William M. Brackb7b54de2004-10-06 16:38:01 +00001296 }
Daniel Veillard344cee72001-08-20 00:08:40 +00001297 if (base != NULL)
1298 xmlFree(base);
Daniel Veillard344cee72001-08-20 00:08:40 +00001299}
1300
Daniel Veillard75b96822001-10-11 18:59:45 +00001301/**
1302 * xmlParseXMLCatalogNodeList:
1303 * @cur: the XML node list of siblings
1304 * @prefer: the PUBLIC vs. SYSTEM current preference value
1305 * @parent: the parent Catalog entry
William M. Brackb7b54de2004-10-06 16:38:01 +00001306 * @cgroup: the group which includes this list
Daniel Veillard75b96822001-10-11 18:59:45 +00001307 *
1308 * Examines a list of XML sibling nodes of a catalog and build
1309 * a list of Catalog entry from it adding it to the parent.
1310 * The examination will recurse to examine node subtrees.
1311 */
Daniel Veillard344cee72001-08-20 00:08:40 +00001312static void
1313xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
William M. Brackb7b54de2004-10-06 16:38:01 +00001314 xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup) {
Daniel Veillard344cee72001-08-20 00:08:40 +00001315 while (cur != NULL) {
1316 if ((cur->ns != NULL) && (cur->ns->href != NULL) &&
1317 (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) {
William M. Brackb7b54de2004-10-06 16:38:01 +00001318 xmlParseXMLCatalogNode(cur, prefer, parent, cgroup);
Daniel Veillard344cee72001-08-20 00:08:40 +00001319 }
1320 cur = cur->next;
1321 }
1322 /* TODO: sort the list according to REWRITE lengths and prefer value */
1323}
1324
Daniel Veillard75b96822001-10-11 18:59:45 +00001325/**
Daniel Veillard75b96822001-10-11 18:59:45 +00001326 * xmlParseXMLCatalogFile:
1327 * @prefer: the PUBLIC vs. SYSTEM current preference value
1328 * @filename: the filename for the catalog
1329 *
1330 * Parses the catalog file to extract the XML tree and then analyze the
1331 * tree to build a list of Catalog entries corresponding to this catalog
1332 *
1333 * Returns the resulting Catalog entries list
1334 */
Daniel Veillard344cee72001-08-20 00:08:40 +00001335static xmlCatalogEntryPtr
1336xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename) {
1337 xmlDocPtr doc;
1338 xmlNodePtr cur;
1339 xmlChar *prop;
1340 xmlCatalogEntryPtr parent = NULL;
1341
1342 if (filename == NULL)
1343 return(NULL);
1344
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00001345 doc = xmlParseCatalogFile((const char *) filename);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001346 if (doc == NULL) {
1347 if (xmlDebugCatalogs)
1348 xmlGenericError(xmlGenericErrorContext,
1349 "Failed to parse catalog %s\n", filename);
Daniel Veillard344cee72001-08-20 00:08:40 +00001350 return(NULL);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001351 }
1352
1353 if (xmlDebugCatalogs)
1354 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard3c01b1d2001-10-17 15:58:35 +00001355 "%d Parsing catalog %s\n", xmlGetThreadId(), filename);
Daniel Veillard344cee72001-08-20 00:08:40 +00001356
1357 cur = xmlDocGetRootElement(doc);
1358 if ((cur != NULL) && (xmlStrEqual(cur->name, BAD_CAST "catalog")) &&
1359 (cur->ns != NULL) && (cur->ns->href != NULL) &&
1360 (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) {
1361
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001362 parent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00001363 (const xmlChar *)filename, NULL, prefer, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001364 if (parent == NULL) {
1365 xmlFreeDoc(doc);
1366 return(NULL);
1367 }
1368
1369 prop = xmlGetProp(cur, BAD_CAST "prefer");
1370 if (prop != NULL) {
1371 if (xmlStrEqual(prop, BAD_CAST "system")) {
1372 prefer = XML_CATA_PREFER_SYSTEM;
1373 } else if (xmlStrEqual(prop, BAD_CAST "public")) {
1374 prefer = XML_CATA_PREFER_PUBLIC;
1375 } else {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001376 xmlCatalogErr(NULL, cur, XML_CATALOG_PREFER_VALUE,
1377 "Invalid value for prefer: '%s'\n",
1378 prop, NULL, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001379 }
1380 xmlFree(prop);
1381 }
1382 cur = cur->children;
William M. Brackb7b54de2004-10-06 16:38:01 +00001383 xmlParseXMLCatalogNodeList(cur, prefer, parent, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001384 } else {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001385 xmlCatalogErr(NULL, (xmlNodePtr) doc, XML_CATALOG_NOT_CATALOG,
1386 "File %s is not an XML Catalog\n",
1387 filename, NULL, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001388 xmlFreeDoc(doc);
1389 return(NULL);
1390 }
1391 xmlFreeDoc(doc);
1392 return(parent);
1393}
1394
Daniel Veillardcda96922001-08-21 10:56:31 +00001395/**
1396 * xmlFetchXMLCatalogFile:
1397 * @catal: an existing but incomplete catalog entry
1398 *
1399 * Fetch and parse the subcatalog referenced by an entry
Daniel Veillardcda96922001-08-21 10:56:31 +00001400 *
1401 * Returns 0 in case of success, -1 otherwise
1402 */
1403static int
1404xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) {
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001405 xmlCatalogEntryPtr doc;
Daniel Veillardcda96922001-08-21 10:56:31 +00001406
1407 if (catal == NULL)
1408 return(-1);
Daniel Veillardc853b322001-11-06 15:24:37 +00001409 if (catal->URL == NULL)
Daniel Veillardcda96922001-08-21 10:56:31 +00001410 return(-1);
Daniel Veillardcda96922001-08-21 10:56:31 +00001411
Daniel Veillard81463942001-10-16 12:34:39 +00001412 /*
1413 * lock the whole catalog for modification
1414 */
1415 xmlRMutexLock(xmlCatalogMutex);
1416 if (catal->children != NULL) {
1417 /* Okay someone else did it in the meantime */
1418 xmlRMutexUnlock(xmlCatalogMutex);
1419 return(0);
Daniel Veillard81463942001-10-16 12:34:39 +00001420 }
1421
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001422 if (xmlCatalogXMLFiles != NULL) {
1423 doc = (xmlCatalogEntryPtr)
Daniel Veillardc853b322001-11-06 15:24:37 +00001424 xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001425 if (doc != NULL) {
1426 if (xmlDebugCatalogs)
1427 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001428 "Found %s in file hash\n", catal->URL);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001429
1430 if (catal->type == XML_CATA_CATALOG)
1431 catal->children = doc->children;
1432 else
1433 catal->children = doc;
1434 catal->dealloc = 0;
1435 xmlRMutexUnlock(xmlCatalogMutex);
1436 return(0);
1437 }
1438 if (xmlDebugCatalogs)
1439 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001440 "%s not found in file hash\n", catal->URL);
Daniel Veillard6990bf32001-08-23 21:17:48 +00001441 }
1442
Daniel Veillardcda96922001-08-21 10:56:31 +00001443 /*
Daniel Veillard75b96822001-10-11 18:59:45 +00001444 * Fetch and parse. Note that xmlParseXMLCatalogFile does not
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001445 * use the existing catalog, there is no recursion allowed at
Daniel Veillard75b96822001-10-11 18:59:45 +00001446 * that level.
Daniel Veillardcda96922001-08-21 10:56:31 +00001447 */
Daniel Veillardc853b322001-11-06 15:24:37 +00001448 doc = xmlParseXMLCatalogFile(catal->prefer, catal->URL);
Daniel Veillard6990bf32001-08-23 21:17:48 +00001449 if (doc == NULL) {
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00001450 catal->type = XML_CATA_BROKEN_CATALOG;
Daniel Veillard81463942001-10-16 12:34:39 +00001451 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillardcda96922001-08-21 10:56:31 +00001452 return(-1);
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00001453 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001454
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001455 if (catal->type == XML_CATA_CATALOG)
1456 catal->children = doc->children;
1457 else
1458 catal->children = doc;
1459
1460 doc->dealloc = 1;
1461
Daniel Veillard81463942001-10-16 12:34:39 +00001462 if (xmlCatalogXMLFiles == NULL)
1463 xmlCatalogXMLFiles = xmlHashCreate(10);
1464 if (xmlCatalogXMLFiles != NULL) {
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001465 if (xmlDebugCatalogs)
1466 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001467 "%s added to file hash\n", catal->URL);
1468 xmlHashAddEntry(xmlCatalogXMLFiles, catal->URL, doc);
Daniel Veillardcda96922001-08-21 10:56:31 +00001469 }
Daniel Veillard81463942001-10-16 12:34:39 +00001470 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillardcda96922001-08-21 10:56:31 +00001471 return(0);
1472}
1473
Daniel Veillard75b96822001-10-11 18:59:45 +00001474/************************************************************************
1475 * *
1476 * XML Catalog handling *
1477 * *
1478 ************************************************************************/
Daniel Veillard344cee72001-08-20 00:08:40 +00001479
1480/**
1481 * xmlAddXMLCatalog:
1482 * @catal: top of an XML catalog
1483 * @type: the type of record to add to the catalog
Daniel Veillardcda96922001-08-21 10:56:31 +00001484 * @orig: the system, public or prefix to match (or NULL)
Daniel Veillard344cee72001-08-20 00:08:40 +00001485 * @replace: the replacement value for the match
1486 *
1487 * Add an entry in the XML catalog, it may overwrite existing but
1488 * different entries.
1489 *
1490 * Returns 0 if successful, -1 otherwise
1491 */
1492static int
1493xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type,
1494 const xmlChar *orig, const xmlChar *replace) {
1495 xmlCatalogEntryPtr cur;
1496 xmlCatalogEntryType typ;
Daniel Veillardc853b322001-11-06 15:24:37 +00001497 int doregister = 0;
Daniel Veillard344cee72001-08-20 00:08:40 +00001498
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00001499 if ((catal == NULL) ||
1500 ((catal->type != XML_CATA_CATALOG) &&
1501 (catal->type != XML_CATA_BROKEN_CATALOG)))
Daniel Veillard344cee72001-08-20 00:08:40 +00001502 return(-1);
Daniel Veillardffe09c92001-11-05 14:21:47 +00001503 if (catal->children == NULL) {
1504 xmlFetchXMLCatalogFile(catal);
1505 }
Daniel Veillardc853b322001-11-06 15:24:37 +00001506 if (catal->children == NULL)
1507 doregister = 1;
1508
Daniel Veillard344cee72001-08-20 00:08:40 +00001509 typ = xmlGetXMLCatalogEntryType(type);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001510 if (typ == XML_CATA_NONE) {
1511 if (xmlDebugCatalogs)
1512 xmlGenericError(xmlGenericErrorContext,
1513 "Failed to add unknown element %s to catalog\n", type);
Daniel Veillard344cee72001-08-20 00:08:40 +00001514 return(-1);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001515 }
Daniel Veillard344cee72001-08-20 00:08:40 +00001516
1517 cur = catal->children;
1518 /*
1519 * Might be a simple "update in place"
1520 */
1521 if (cur != NULL) {
1522 while (cur != NULL) {
Daniel Veillardcda96922001-08-21 10:56:31 +00001523 if ((orig != NULL) && (cur->type == typ) &&
1524 (xmlStrEqual(orig, cur->name))) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001525 if (xmlDebugCatalogs)
1526 xmlGenericError(xmlGenericErrorContext,
1527 "Updating element %s to catalog\n", type);
Daniel Veillard344cee72001-08-20 00:08:40 +00001528 if (cur->value != NULL)
1529 xmlFree(cur->value);
Daniel Veillardc853b322001-11-06 15:24:37 +00001530 if (cur->URL != NULL)
1531 xmlFree(cur->URL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001532 cur->value = xmlStrdup(replace);
Daniel Veillardc853b322001-11-06 15:24:37 +00001533 cur->URL = xmlStrdup(replace);
Daniel Veillardcda96922001-08-21 10:56:31 +00001534 return(0);
Daniel Veillard344cee72001-08-20 00:08:40 +00001535 }
1536 if (cur->next == NULL)
1537 break;
1538 cur = cur->next;
1539 }
1540 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001541 if (xmlDebugCatalogs)
1542 xmlGenericError(xmlGenericErrorContext,
1543 "Adding element %s to catalog\n", type);
Daniel Veillard344cee72001-08-20 00:08:40 +00001544 if (cur == NULL)
Daniel Veillardc853b322001-11-06 15:24:37 +00001545 catal->children = xmlNewCatalogEntry(typ, orig, replace,
William M. Brackb7b54de2004-10-06 16:38:01 +00001546 NULL, catal->prefer, NULL);
Daniel Veillard344cee72001-08-20 00:08:40 +00001547 else
Daniel Veillardc853b322001-11-06 15:24:37 +00001548 cur->next = xmlNewCatalogEntry(typ, orig, replace,
William M. Brackb7b54de2004-10-06 16:38:01 +00001549 NULL, catal->prefer, NULL);
Daniel Veillardc853b322001-11-06 15:24:37 +00001550 if (doregister) {
Daniel Veillard27bec142006-02-24 20:22:27 +00001551 catal->type = XML_CATA_CATALOG;
Daniel Veillardc853b322001-11-06 15:24:37 +00001552 cur = xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
1553 if (cur != NULL)
1554 cur->children = catal->children;
1555 }
1556
Daniel Veillardcda96922001-08-21 10:56:31 +00001557 return(0);
1558}
1559
1560/**
1561 * xmlDelXMLCatalog:
1562 * @catal: top of an XML catalog
Daniel Veillard60087f32001-10-10 09:45:09 +00001563 * @value: the value to remove from the catalog
Daniel Veillardcda96922001-08-21 10:56:31 +00001564 *
1565 * Remove entries in the XML catalog where the value or the URI
1566 * is equal to @value
1567 *
1568 * Returns the number of entries removed if successful, -1 otherwise
1569 */
1570static int
1571xmlDelXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *value) {
Daniel Veillardc853b322001-11-06 15:24:37 +00001572 xmlCatalogEntryPtr cur;
Daniel Veillardcda96922001-08-21 10:56:31 +00001573 int ret = 0;
1574
Daniel Veillard9f7b84b2001-08-23 15:31:19 +00001575 if ((catal == NULL) ||
1576 ((catal->type != XML_CATA_CATALOG) &&
1577 (catal->type != XML_CATA_BROKEN_CATALOG)))
Daniel Veillardcda96922001-08-21 10:56:31 +00001578 return(-1);
1579 if (value == NULL)
1580 return(-1);
Daniel Veillardffe09c92001-11-05 14:21:47 +00001581 if (catal->children == NULL) {
1582 xmlFetchXMLCatalogFile(catal);
1583 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001584
1585 /*
1586 * Scan the children
1587 */
1588 cur = catal->children;
Daniel Veillardcda96922001-08-21 10:56:31 +00001589 while (cur != NULL) {
1590 if (((cur->name != NULL) && (xmlStrEqual(value, cur->name))) ||
1591 (xmlStrEqual(value, cur->value))) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001592 if (xmlDebugCatalogs) {
1593 if (cur->name != NULL)
1594 xmlGenericError(xmlGenericErrorContext,
1595 "Removing element %s from catalog\n", cur->name);
1596 else
1597 xmlGenericError(xmlGenericErrorContext,
1598 "Removing element %s from catalog\n", cur->value);
1599 }
Daniel Veillardc853b322001-11-06 15:24:37 +00001600 cur->type = XML_CATA_REMOVED;
Daniel Veillardcda96922001-08-21 10:56:31 +00001601 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001602 cur = cur->next;
1603 }
1604 return(ret);
1605}
1606
1607/**
Daniel Veillardcda96922001-08-21 10:56:31 +00001608 * xmlCatalogXMLResolve:
1609 * @catal: a catalog list
Daniel Veillard06d25242004-02-25 13:01:42 +00001610 * @pubID: the public ID string
1611 * @sysID: the system ID string
Daniel Veillardcda96922001-08-21 10:56:31 +00001612 *
1613 * Do a complete resolution lookup of an External Identifier for a
1614 * list of catalog entries.
1615 *
1616 * Implements (or tries to) 7.1. External Identifier Resolution
1617 * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1618 *
1619 * Returns the URI of the resource or NULL if not found
1620 */
1621static xmlChar *
1622xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1623 const xmlChar *sysID) {
1624 xmlChar *ret = NULL;
1625 xmlCatalogEntryPtr cur;
1626 int haveDelegate = 0;
1627 int haveNext = 0;
1628
1629 /*
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001630 * protection against loops
1631 */
1632 if (catal->depth > MAX_CATAL_DEPTH) {
Daniel Veillard69d2c172003-10-09 11:46:07 +00001633 xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
1634 "Detected recursion in catalog %s\n",
1635 catal->name, NULL, NULL);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001636 return(NULL);
1637 }
1638 catal->depth++;
1639
1640 /*
Daniel Veillardcda96922001-08-21 10:56:31 +00001641 * First tries steps 2/ 3/ 4/ if a system ID is provided.
1642 */
1643 if (sysID != NULL) {
1644 xmlCatalogEntryPtr rewrite = NULL;
1645 int lenrewrite = 0, len;
1646 cur = catal;
1647 haveDelegate = 0;
1648 while (cur != NULL) {
1649 switch (cur->type) {
1650 case XML_CATA_SYSTEM:
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001651 if (xmlStrEqual(sysID, cur->name)) {
1652 if (xmlDebugCatalogs)
1653 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard890b5492006-02-23 08:14:00 +00001654 "Found system match %s, using %s\n",
1655 cur->name, cur->URL);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001656 catal->depth--;
Daniel Veillardc853b322001-11-06 15:24:37 +00001657 return(xmlStrdup(cur->URL));
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001658 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001659 break;
1660 case XML_CATA_REWRITE_SYSTEM:
1661 len = xmlStrlen(cur->name);
1662 if ((len > lenrewrite) &&
1663 (!xmlStrncmp(sysID, cur->name, len))) {
1664 lenrewrite = len;
1665 rewrite = cur;
1666 }
1667 break;
1668 case XML_CATA_DELEGATE_SYSTEM:
1669 if (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))
1670 haveDelegate++;
1671 break;
1672 case XML_CATA_NEXT_CATALOG:
1673 haveNext++;
1674 break;
1675 default:
1676 break;
1677 }
1678 cur = cur->next;
1679 }
1680 if (rewrite != NULL) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001681 if (xmlDebugCatalogs)
1682 xmlGenericError(xmlGenericErrorContext,
1683 "Using rewriting rule %s\n", rewrite->name);
Daniel Veillardc853b322001-11-06 15:24:37 +00001684 ret = xmlStrdup(rewrite->URL);
Daniel Veillardcda96922001-08-21 10:56:31 +00001685 if (ret != NULL)
1686 ret = xmlStrcat(ret, &sysID[lenrewrite]);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001687 catal->depth--;
Daniel Veillardcda96922001-08-21 10:56:31 +00001688 return(ret);
1689 }
1690 if (haveDelegate) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001691 const xmlChar *delegates[MAX_DELEGATE];
1692 int nbList = 0, i;
1693
Daniel Veillardcda96922001-08-21 10:56:31 +00001694 /*
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001695 * Assume the entries have been sorted by decreasing substring
Daniel Veillardcda96922001-08-21 10:56:31 +00001696 * matches when the list was produced.
1697 */
1698 cur = catal;
1699 while (cur != NULL) {
1700 if ((cur->type == XML_CATA_DELEGATE_SYSTEM) &&
1701 (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001702 for (i = 0;i < nbList;i++)
Daniel Veillardc853b322001-11-06 15:24:37 +00001703 if (xmlStrEqual(cur->URL, delegates[i]))
Daniel Veillard6990bf32001-08-23 21:17:48 +00001704 break;
1705 if (i < nbList) {
1706 cur = cur->next;
1707 continue;
1708 }
1709 if (nbList < MAX_DELEGATE)
Daniel Veillardc853b322001-11-06 15:24:37 +00001710 delegates[nbList++] = cur->URL;
Daniel Veillard6990bf32001-08-23 21:17:48 +00001711
Daniel Veillardcda96922001-08-21 10:56:31 +00001712 if (cur->children == NULL) {
1713 xmlFetchXMLCatalogFile(cur);
1714 }
1715 if (cur->children != NULL) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001716 if (xmlDebugCatalogs)
1717 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001718 "Trying system delegate %s\n", cur->URL);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001719 ret = xmlCatalogListXMLResolve(
1720 cur->children, NULL, sysID);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001721 if (ret != NULL) {
1722 catal->depth--;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001723 return(ret);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001724 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001725 }
1726 }
1727 cur = cur->next;
1728 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001729 /*
1730 * Apply the cut algorithm explained in 4/
1731 */
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001732 catal->depth--;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001733 return(XML_CATAL_BREAK);
Daniel Veillardcda96922001-08-21 10:56:31 +00001734 }
1735 }
1736 /*
1737 * Then tries 5/ 6/ if a public ID is provided
1738 */
1739 if (pubID != NULL) {
1740 cur = catal;
1741 haveDelegate = 0;
1742 while (cur != NULL) {
1743 switch (cur->type) {
1744 case XML_CATA_PUBLIC:
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001745 if (xmlStrEqual(pubID, cur->name)) {
1746 if (xmlDebugCatalogs)
1747 xmlGenericError(xmlGenericErrorContext,
1748 "Found public match %s\n", cur->name);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001749 catal->depth--;
Daniel Veillardc853b322001-11-06 15:24:37 +00001750 return(xmlStrdup(cur->URL));
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001751 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001752 break;
1753 case XML_CATA_DELEGATE_PUBLIC:
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001754 if (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)) &&
1755 (cur->prefer == XML_CATA_PREFER_PUBLIC))
Daniel Veillardcda96922001-08-21 10:56:31 +00001756 haveDelegate++;
1757 break;
1758 case XML_CATA_NEXT_CATALOG:
1759 if (sysID == NULL)
1760 haveNext++;
1761 break;
1762 default:
1763 break;
1764 }
1765 cur = cur->next;
1766 }
1767 if (haveDelegate) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001768 const xmlChar *delegates[MAX_DELEGATE];
1769 int nbList = 0, i;
1770
Daniel Veillardcda96922001-08-21 10:56:31 +00001771 /*
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001772 * Assume the entries have been sorted by decreasing substring
Daniel Veillardcda96922001-08-21 10:56:31 +00001773 * matches when the list was produced.
1774 */
1775 cur = catal;
1776 while (cur != NULL) {
1777 if ((cur->type == XML_CATA_DELEGATE_PUBLIC) &&
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001778 (cur->prefer == XML_CATA_PREFER_PUBLIC) &&
1779 (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)))) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001780
1781 for (i = 0;i < nbList;i++)
Daniel Veillardc853b322001-11-06 15:24:37 +00001782 if (xmlStrEqual(cur->URL, delegates[i]))
Daniel Veillard6990bf32001-08-23 21:17:48 +00001783 break;
1784 if (i < nbList) {
1785 cur = cur->next;
1786 continue;
1787 }
1788 if (nbList < MAX_DELEGATE)
Daniel Veillardc853b322001-11-06 15:24:37 +00001789 delegates[nbList++] = cur->URL;
Daniel Veillard6990bf32001-08-23 21:17:48 +00001790
Daniel Veillardcda96922001-08-21 10:56:31 +00001791 if (cur->children == NULL) {
1792 xmlFetchXMLCatalogFile(cur);
1793 }
1794 if (cur->children != NULL) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001795 if (xmlDebugCatalogs)
1796 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001797 "Trying public delegate %s\n", cur->URL);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001798 ret = xmlCatalogListXMLResolve(
1799 cur->children, pubID, NULL);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001800 if (ret != NULL) {
1801 catal->depth--;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001802 return(ret);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001803 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001804 }
1805 }
1806 cur = cur->next;
1807 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001808 /*
1809 * Apply the cut algorithm explained in 4/
1810 */
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001811 catal->depth--;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001812 return(XML_CATAL_BREAK);
Daniel Veillardcda96922001-08-21 10:56:31 +00001813 }
1814 }
1815 if (haveNext) {
1816 cur = catal;
1817 while (cur != NULL) {
1818 if (cur->type == XML_CATA_NEXT_CATALOG) {
1819 if (cur->children == NULL) {
1820 xmlFetchXMLCatalogFile(cur);
1821 }
1822 if (cur->children != NULL) {
Daniel Veillard64339542001-08-21 12:57:59 +00001823 ret = xmlCatalogListXMLResolve(cur->children, pubID, sysID);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001824 if (ret != NULL) {
1825 catal->depth--;
Daniel Veillard64339542001-08-21 12:57:59 +00001826 return(ret);
Daniel Veillardbe8d9d32007-06-12 09:14:11 +00001827 } else if (catal->depth > MAX_CATAL_DEPTH) {
1828 return(NULL);
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001829 }
Daniel Veillardcda96922001-08-21 10:56:31 +00001830 }
1831 }
1832 cur = cur->next;
1833 }
1834 }
1835
Daniel Veillard5ee43b02003-08-04 00:58:46 +00001836 catal->depth--;
Daniel Veillardcda96922001-08-21 10:56:31 +00001837 return(NULL);
1838}
1839
1840/**
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001841 * xmlCatalogXMLResolveURI:
1842 * @catal: a catalog list
1843 * @URI: the URI
Daniel Veillard06d25242004-02-25 13:01:42 +00001844 * @sysID: the system ID string
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001845 *
1846 * Do a complete resolution lookup of an External Identifier for a
1847 * list of catalog entries.
1848 *
1849 * Implements (or tries to) 7.2.2. URI Resolution
1850 * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1851 *
1852 * Returns the URI of the resource or NULL if not found
1853 */
1854static xmlChar *
1855xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
1856 xmlChar *ret = NULL;
1857 xmlCatalogEntryPtr cur;
1858 int haveDelegate = 0;
1859 int haveNext = 0;
1860 xmlCatalogEntryPtr rewrite = NULL;
1861 int lenrewrite = 0, len;
1862
1863 if (catal == NULL)
1864 return(NULL);
1865
1866 if (URI == NULL)
1867 return(NULL);
1868
Daniel Veillardbe8d9d32007-06-12 09:14:11 +00001869 if (catal->depth > MAX_CATAL_DEPTH) {
1870 xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
1871 "Detected recursion in catalog %s\n",
1872 catal->name, NULL, NULL);
1873 return(NULL);
1874 }
1875
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001876 /*
1877 * First tries steps 2/ 3/ 4/ if a system ID is provided.
1878 */
1879 cur = catal;
1880 haveDelegate = 0;
1881 while (cur != NULL) {
1882 switch (cur->type) {
1883 case XML_CATA_URI:
1884 if (xmlStrEqual(URI, cur->name)) {
1885 if (xmlDebugCatalogs)
1886 xmlGenericError(xmlGenericErrorContext,
1887 "Found URI match %s\n", cur->name);
Daniel Veillardc853b322001-11-06 15:24:37 +00001888 return(xmlStrdup(cur->URL));
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001889 }
1890 break;
1891 case XML_CATA_REWRITE_URI:
1892 len = xmlStrlen(cur->name);
1893 if ((len > lenrewrite) &&
1894 (!xmlStrncmp(URI, cur->name, len))) {
1895 lenrewrite = len;
1896 rewrite = cur;
1897 }
1898 break;
1899 case XML_CATA_DELEGATE_URI:
1900 if (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))
1901 haveDelegate++;
1902 break;
1903 case XML_CATA_NEXT_CATALOG:
1904 haveNext++;
1905 break;
1906 default:
1907 break;
1908 }
1909 cur = cur->next;
1910 }
1911 if (rewrite != NULL) {
1912 if (xmlDebugCatalogs)
1913 xmlGenericError(xmlGenericErrorContext,
1914 "Using rewriting rule %s\n", rewrite->name);
Daniel Veillardc853b322001-11-06 15:24:37 +00001915 ret = xmlStrdup(rewrite->URL);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001916 if (ret != NULL)
1917 ret = xmlStrcat(ret, &URI[lenrewrite]);
1918 return(ret);
1919 }
1920 if (haveDelegate) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001921 const xmlChar *delegates[MAX_DELEGATE];
1922 int nbList = 0, i;
1923
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001924 /*
1925 * Assume the entries have been sorted by decreasing substring
1926 * matches when the list was produced.
1927 */
1928 cur = catal;
1929 while (cur != NULL) {
Daniel Veillard652d8a92003-02-04 19:28:49 +00001930 if (((cur->type == XML_CATA_DELEGATE_SYSTEM) ||
1931 (cur->type == XML_CATA_DELEGATE_URI)) &&
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001932 (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))) {
Daniel Veillard6990bf32001-08-23 21:17:48 +00001933 for (i = 0;i < nbList;i++)
Daniel Veillardc853b322001-11-06 15:24:37 +00001934 if (xmlStrEqual(cur->URL, delegates[i]))
Daniel Veillard6990bf32001-08-23 21:17:48 +00001935 break;
1936 if (i < nbList) {
1937 cur = cur->next;
1938 continue;
1939 }
1940 if (nbList < MAX_DELEGATE)
Daniel Veillardc853b322001-11-06 15:24:37 +00001941 delegates[nbList++] = cur->URL;
Daniel Veillard6990bf32001-08-23 21:17:48 +00001942
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001943 if (cur->children == NULL) {
1944 xmlFetchXMLCatalogFile(cur);
1945 }
1946 if (cur->children != NULL) {
1947 if (xmlDebugCatalogs)
1948 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardc853b322001-11-06 15:24:37 +00001949 "Trying URI delegate %s\n", cur->URL);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00001950 ret = xmlCatalogListXMLResolveURI(
1951 cur->children, URI);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00001952 if (ret != NULL)
1953 return(ret);
1954 }
1955 }
1956 cur = cur->next;
1957 }
1958 /*
1959 * Apply the cut algorithm explained in 4/
1960 */
1961 return(XML_CATAL_BREAK);
1962 }
1963 if (haveNext) {
1964 cur = catal;
1965 while (cur != NULL) {
1966 if (cur->type == XML_CATA_NEXT_CATALOG) {
1967 if (cur->children == NULL) {
1968 xmlFetchXMLCatalogFile(cur);
1969 }
1970 if (cur->children != NULL) {
1971 ret = xmlCatalogListXMLResolveURI(cur->children, URI);
1972 if (ret != NULL)
1973 return(ret);
1974 }
1975 }
1976 cur = cur->next;
1977 }
1978 }
1979
1980 return(NULL);
1981}
1982
1983/**
Daniel Veillardcda96922001-08-21 10:56:31 +00001984 * xmlCatalogListXMLResolve:
1985 * @catal: a catalog list
Daniel Veillard06d25242004-02-25 13:01:42 +00001986 * @pubID: the public ID string
1987 * @sysID: the system ID string
Daniel Veillardcda96922001-08-21 10:56:31 +00001988 *
1989 * Do a complete resolution lookup of an External Identifier for a
1990 * list of catalogs
1991 *
1992 * Implements (or tries to) 7.1. External Identifier Resolution
1993 * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1994 *
1995 * Returns the URI of the resource or NULL if not found
1996 */
1997static xmlChar *
1998xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1999 const xmlChar *sysID) {
2000 xmlChar *ret = NULL;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002001 xmlChar *urnID = NULL;
Daniel Veillardc8155052004-07-16 09:03:08 +00002002 xmlChar *normid;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002003
2004 if (catal == NULL)
2005 return(NULL);
2006 if ((pubID == NULL) && (sysID == NULL))
2007 return(NULL);
2008
Daniel Veillardc8155052004-07-16 09:03:08 +00002009 normid = xmlCatalogNormalizePublic(pubID);
2010 if (normid != NULL)
2011 pubID = (*normid != 0 ? normid : NULL);
2012
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002013 if (!xmlStrncmp(pubID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2014 urnID = xmlCatalogUnWrapURN(pubID);
2015 if (xmlDebugCatalogs) {
2016 if (urnID == NULL)
2017 xmlGenericError(xmlGenericErrorContext,
2018 "Public URN ID %s expanded to NULL\n", pubID);
2019 else
2020 xmlGenericError(xmlGenericErrorContext,
2021 "Public URN ID expanded to %s\n", urnID);
2022 }
2023 ret = xmlCatalogListXMLResolve(catal, urnID, sysID);
2024 if (urnID != NULL)
2025 xmlFree(urnID);
Daniel Veillardc8155052004-07-16 09:03:08 +00002026 if (normid != NULL)
2027 xmlFree(normid);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002028 return(ret);
Daniel Veillardcda96922001-08-21 10:56:31 +00002029 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002030 if (!xmlStrncmp(sysID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2031 urnID = xmlCatalogUnWrapURN(sysID);
2032 if (xmlDebugCatalogs) {
2033 if (urnID == NULL)
2034 xmlGenericError(xmlGenericErrorContext,
2035 "System URN ID %s expanded to NULL\n", sysID);
2036 else
2037 xmlGenericError(xmlGenericErrorContext,
2038 "System URN ID expanded to %s\n", urnID);
2039 }
2040 if (pubID == NULL)
2041 ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
2042 else if (xmlStrEqual(pubID, urnID))
2043 ret = xmlCatalogListXMLResolve(catal, pubID, NULL);
2044 else {
Daniel Veillard770075b2004-02-25 10:44:30 +00002045 ret = xmlCatalogListXMLResolve(catal, pubID, urnID);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002046 }
2047 if (urnID != NULL)
2048 xmlFree(urnID);
Daniel Veillardc8155052004-07-16 09:03:08 +00002049 if (normid != NULL)
2050 xmlFree(normid);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002051 return(ret);
Daniel Veillardcda96922001-08-21 10:56:31 +00002052 }
2053 while (catal != NULL) {
2054 if (catal->type == XML_CATA_CATALOG) {
2055 if (catal->children == NULL) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002056 xmlFetchXMLCatalogFile(catal);
Daniel Veillardcda96922001-08-21 10:56:31 +00002057 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002058 if (catal->children != NULL) {
2059 ret = xmlCatalogXMLResolve(catal->children, pubID, sysID);
Daniel Veillardc8155052004-07-16 09:03:08 +00002060 if (ret != NULL) {
Daniel Veillardbe8d9d32007-06-12 09:14:11 +00002061 break;
2062 } else if ((catal->children != NULL) &&
2063 (catal->children->depth > MAX_CATAL_DEPTH)) {
2064 ret = NULL;
2065 break;
2066 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002067 }
Daniel Veillardcda96922001-08-21 10:56:31 +00002068 }
2069 catal = catal->next;
2070 }
Daniel Veillardbe8d9d32007-06-12 09:14:11 +00002071 if (normid != NULL)
2072 xmlFree(normid);
Daniel Veillardcda96922001-08-21 10:56:31 +00002073 return(ret);
Daniel Veillard344cee72001-08-20 00:08:40 +00002074}
2075
Daniel Veillarddc2cee22001-08-22 16:30:37 +00002076/**
2077 * xmlCatalogListXMLResolveURI:
2078 * @catal: a catalog list
2079 * @URI: the URI
2080 *
2081 * Do a complete resolution lookup of an URI for a list of catalogs
2082 *
2083 * Implements (or tries to) 7.2. URI Resolution
2084 * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
2085 *
2086 * Returns the URI of the resource or NULL if not found
2087 */
2088static xmlChar *
2089xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
2090 xmlChar *ret = NULL;
2091 xmlChar *urnID = NULL;
2092
2093 if (catal == NULL)
2094 return(NULL);
2095 if (URI == NULL)
2096 return(NULL);
2097
2098 if (!xmlStrncmp(URI, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2099 urnID = xmlCatalogUnWrapURN(URI);
2100 if (xmlDebugCatalogs) {
2101 if (urnID == NULL)
2102 xmlGenericError(xmlGenericErrorContext,
2103 "URN ID %s expanded to NULL\n", URI);
2104 else
2105 xmlGenericError(xmlGenericErrorContext,
2106 "URN ID expanded to %s\n", urnID);
2107 }
2108 ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
2109 if (urnID != NULL)
2110 xmlFree(urnID);
2111 return(ret);
2112 }
2113 while (catal != NULL) {
2114 if (catal->type == XML_CATA_CATALOG) {
2115 if (catal->children == NULL) {
2116 xmlFetchXMLCatalogFile(catal);
2117 }
2118 if (catal->children != NULL) {
2119 ret = xmlCatalogXMLResolveURI(catal->children, URI);
2120 if (ret != NULL)
2121 return(ret);
2122 }
2123 }
2124 catal = catal->next;
2125 }
2126 return(ret);
2127}
2128
Daniel Veillard344cee72001-08-20 00:08:40 +00002129/************************************************************************
2130 * *
2131 * The SGML Catalog parser *
Daniel Veillarda7374592001-05-10 14:17:55 +00002132 * *
2133 ************************************************************************/
2134
2135
2136#define RAW *cur
2137#define NEXT cur++;
2138#define SKIP(x) cur += x;
2139
William M. Brack272693c2003-11-14 16:20:34 +00002140#define SKIP_BLANKS while (IS_BLANK_CH(*cur)) NEXT;
Daniel Veillarda7374592001-05-10 14:17:55 +00002141
Daniel Veillard75b96822001-10-11 18:59:45 +00002142/**
2143 * xmlParseSGMLCatalogComment:
2144 * @cur: the current character
2145 *
2146 * Skip a comment in an SGML catalog
2147 *
2148 * Returns new current character
2149 */
Daniel Veillarda7374592001-05-10 14:17:55 +00002150static const xmlChar *
Daniel Veillardcda96922001-08-21 10:56:31 +00002151xmlParseSGMLCatalogComment(const xmlChar *cur) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002152 if ((cur[0] != '-') || (cur[1] != '-'))
2153 return(cur);
2154 SKIP(2);
2155 while ((cur[0] != 0) && ((cur[0] != '-') || ((cur[1] != '-'))))
2156 NEXT;
2157 if (cur[0] == 0) {
2158 return(NULL);
2159 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002160 return(cur + 2);
Daniel Veillarda7374592001-05-10 14:17:55 +00002161}
2162
Daniel Veillard75b96822001-10-11 18:59:45 +00002163/**
2164 * xmlParseSGMLCatalogPubid:
2165 * @cur: the current character
2166 * @id: the return location
2167 *
2168 * Parse an SGML catalog ID
2169 *
2170 * Returns new current character and store the value in @id
2171 */
Daniel Veillarda7374592001-05-10 14:17:55 +00002172static const xmlChar *
Daniel Veillardcda96922001-08-21 10:56:31 +00002173xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) {
Daniel Veillard69d2c172003-10-09 11:46:07 +00002174 xmlChar *buf = NULL, *tmp;
Daniel Veillarda7374592001-05-10 14:17:55 +00002175 int len = 0;
2176 int size = 50;
2177 xmlChar stop;
2178 int count = 0;
2179
2180 *id = NULL;
2181
2182 if (RAW == '"') {
2183 NEXT;
2184 stop = '"';
2185 } else if (RAW == '\'') {
2186 NEXT;
2187 stop = '\'';
2188 } else {
2189 stop = ' ';
2190 }
Daniel Veillard3c908dc2003-04-19 00:07:51 +00002191 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
Daniel Veillarda7374592001-05-10 14:17:55 +00002192 if (buf == NULL) {
Daniel Veillard69d2c172003-10-09 11:46:07 +00002193 xmlCatalogErrMemory("allocating public ID");
Daniel Veillarda7374592001-05-10 14:17:55 +00002194 return(NULL);
2195 }
William M. Brack76e95df2003-10-18 16:20:14 +00002196 while (IS_PUBIDCHAR_CH(*cur) || (*cur == '?')) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002197 if ((*cur == stop) && (stop != ' '))
2198 break;
William M. Brack76e95df2003-10-18 16:20:14 +00002199 if ((stop == ' ') && (IS_BLANK_CH(*cur)))
Daniel Veillarda7374592001-05-10 14:17:55 +00002200 break;
2201 if (len + 1 >= size) {
2202 size *= 2;
Daniel Veillard69d2c172003-10-09 11:46:07 +00002203 tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
2204 if (tmp == NULL) {
2205 xmlCatalogErrMemory("allocating public ID");
2206 xmlFree(buf);
Daniel Veillarda7374592001-05-10 14:17:55 +00002207 return(NULL);
2208 }
Daniel Veillard69d2c172003-10-09 11:46:07 +00002209 buf = tmp;
Daniel Veillarda7374592001-05-10 14:17:55 +00002210 }
2211 buf[len++] = *cur;
2212 count++;
2213 NEXT;
2214 }
2215 buf[len] = 0;
2216 if (stop == ' ') {
William M. Brack76e95df2003-10-18 16:20:14 +00002217 if (!IS_BLANK_CH(*cur)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002218 xmlFree(buf);
2219 return(NULL);
2220 }
2221 } else {
2222 if (*cur != stop) {
2223 xmlFree(buf);
2224 return(NULL);
2225 }
2226 NEXT;
2227 }
2228 *id = buf;
2229 return(cur);
2230}
2231
Daniel Veillard75b96822001-10-11 18:59:45 +00002232/**
2233 * xmlParseSGMLCatalogName:
2234 * @cur: the current character
2235 * @name: the return location
2236 *
2237 * Parse an SGML catalog name
2238 *
2239 * Returns new current character and store the value in @name
2240 */
Daniel Veillarda7374592001-05-10 14:17:55 +00002241static const xmlChar *
Daniel Veillardcda96922001-08-21 10:56:31 +00002242xmlParseSGMLCatalogName(const xmlChar *cur, xmlChar **name) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002243 xmlChar buf[XML_MAX_NAMELEN + 5];
2244 int len = 0;
2245 int c;
2246
2247 *name = NULL;
2248
2249 /*
2250 * Handler for more complex cases
2251 */
2252 c = *cur;
2253 if ((!IS_LETTER(c) && (c != '_') && (c != ':'))) {
2254 return(NULL);
2255 }
2256
2257 while (((IS_LETTER(c)) || (IS_DIGIT(c)) ||
2258 (c == '.') || (c == '-') ||
2259 (c == '_') || (c == ':'))) {
2260 buf[len++] = c;
2261 cur++;
2262 c = *cur;
2263 if (len >= XML_MAX_NAMELEN)
2264 return(NULL);
2265 }
2266 *name = xmlStrndup(buf, len);
2267 return(cur);
2268}
2269
Daniel Veillard75b96822001-10-11 18:59:45 +00002270/**
2271 * xmlGetSGMLCatalogEntryType:
2272 * @name: the entry name
2273 *
2274 * Get the Catalog entry type for a given SGML Catalog name
2275 *
2276 * Returns Catalog entry type
2277 */
Daniel Veillard344cee72001-08-20 00:08:40 +00002278static xmlCatalogEntryType
Daniel Veillardcda96922001-08-21 10:56:31 +00002279xmlGetSGMLCatalogEntryType(const xmlChar *name) {
Daniel Veillard344cee72001-08-20 00:08:40 +00002280 xmlCatalogEntryType type = XML_CATA_NONE;
2281 if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
2282 type = SGML_CATA_SYSTEM;
2283 else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
2284 type = SGML_CATA_PUBLIC;
2285 else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
2286 type = SGML_CATA_DELEGATE;
2287 else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
2288 type = SGML_CATA_ENTITY;
2289 else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
2290 type = SGML_CATA_DOCTYPE;
2291 else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
2292 type = SGML_CATA_LINKTYPE;
2293 else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
2294 type = SGML_CATA_NOTATION;
2295 else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
2296 type = SGML_CATA_SGMLDECL;
2297 else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
2298 type = SGML_CATA_DOCUMENT;
2299 else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
2300 type = SGML_CATA_CATALOG;
2301 else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
2302 type = SGML_CATA_BASE;
Daniel Veillard344cee72001-08-20 00:08:40 +00002303 return(type);
2304}
2305
Daniel Veillard75b96822001-10-11 18:59:45 +00002306/**
2307 * xmlParseSGMLCatalog:
2308 * @catal: the SGML Catalog
2309 * @value: the content of the SGML Catalog serialization
2310 * @file: the filepath for the catalog
2311 * @super: should this be handled as a Super Catalog in which case
2312 * parsing is not recursive
2313 *
2314 * Parse an SGML catalog content and fill up the @catal hash table with
2315 * the new entries found.
2316 *
2317 * Returns 0 in case of success, -1 in case of error.
2318 */
Daniel Veillarda7374592001-05-10 14:17:55 +00002319static int
Daniel Veillard75b96822001-10-11 18:59:45 +00002320xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value,
2321 const char *file, int super) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002322 const xmlChar *cur = value;
2323 xmlChar *base = NULL;
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002324 int res;
Daniel Veillarda7374592001-05-10 14:17:55 +00002325
2326 if ((cur == NULL) || (file == NULL))
2327 return(-1);
2328 base = xmlStrdup((const xmlChar *) file);
2329
Daniel Veillardbc2ddbe2001-08-23 10:24:27 +00002330 while ((cur != NULL) && (cur[0] != 0)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002331 SKIP_BLANKS;
Daniel Veillardbc2ddbe2001-08-23 10:24:27 +00002332 if (cur[0] == 0)
2333 break;
Daniel Veillarda7374592001-05-10 14:17:55 +00002334 if ((cur[0] == '-') && (cur[1] == '-')) {
Daniel Veillardcda96922001-08-21 10:56:31 +00002335 cur = xmlParseSGMLCatalogComment(cur);
Daniel Veillarda7374592001-05-10 14:17:55 +00002336 if (cur == NULL) {
2337 /* error */
2338 break;
2339 }
2340 } else {
2341 xmlChar *sysid = NULL;
2342 xmlChar *name = NULL;
2343 xmlCatalogEntryType type = XML_CATA_NONE;
2344
Daniel Veillardcda96922001-08-21 10:56:31 +00002345 cur = xmlParseSGMLCatalogName(cur, &name);
Daniel Veillarda7374592001-05-10 14:17:55 +00002346 if (name == NULL) {
2347 /* error */
2348 break;
2349 }
William M. Brack76e95df2003-10-18 16:20:14 +00002350 if (!IS_BLANK_CH(*cur)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002351 /* error */
2352 break;
2353 }
2354 SKIP_BLANKS;
2355 if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002356 type = SGML_CATA_SYSTEM;
Daniel Veillarda7374592001-05-10 14:17:55 +00002357 else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002358 type = SGML_CATA_PUBLIC;
Daniel Veillarda7374592001-05-10 14:17:55 +00002359 else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002360 type = SGML_CATA_DELEGATE;
Daniel Veillarda7374592001-05-10 14:17:55 +00002361 else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002362 type = SGML_CATA_ENTITY;
Daniel Veillarda7374592001-05-10 14:17:55 +00002363 else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002364 type = SGML_CATA_DOCTYPE;
Daniel Veillarda7374592001-05-10 14:17:55 +00002365 else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002366 type = SGML_CATA_LINKTYPE;
Daniel Veillarda7374592001-05-10 14:17:55 +00002367 else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002368 type = SGML_CATA_NOTATION;
Daniel Veillarda7374592001-05-10 14:17:55 +00002369 else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002370 type = SGML_CATA_SGMLDECL;
Daniel Veillarda7374592001-05-10 14:17:55 +00002371 else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002372 type = SGML_CATA_DOCUMENT;
Daniel Veillarda7374592001-05-10 14:17:55 +00002373 else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002374 type = SGML_CATA_CATALOG;
Daniel Veillarda7374592001-05-10 14:17:55 +00002375 else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
Daniel Veillard344cee72001-08-20 00:08:40 +00002376 type = SGML_CATA_BASE;
Daniel Veillarda7374592001-05-10 14:17:55 +00002377 else if (xmlStrEqual(name, (const xmlChar *) "OVERRIDE")) {
2378 xmlFree(name);
Daniel Veillardcda96922001-08-21 10:56:31 +00002379 cur = xmlParseSGMLCatalogName(cur, &name);
Daniel Veillarda7374592001-05-10 14:17:55 +00002380 if (name == NULL) {
2381 /* error */
2382 break;
2383 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002384 xmlFree(name);
Daniel Veillarda7374592001-05-10 14:17:55 +00002385 continue;
2386 }
2387 xmlFree(name);
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002388 name = NULL;
Daniel Veillarda7374592001-05-10 14:17:55 +00002389
2390 switch(type) {
Daniel Veillard344cee72001-08-20 00:08:40 +00002391 case SGML_CATA_ENTITY:
Daniel Veillarda7374592001-05-10 14:17:55 +00002392 if (*cur == '%')
Daniel Veillard344cee72001-08-20 00:08:40 +00002393 type = SGML_CATA_PENTITY;
2394 case SGML_CATA_PENTITY:
2395 case SGML_CATA_DOCTYPE:
2396 case SGML_CATA_LINKTYPE:
2397 case SGML_CATA_NOTATION:
Daniel Veillardcda96922001-08-21 10:56:31 +00002398 cur = xmlParseSGMLCatalogName(cur, &name);
Daniel Veillarda7374592001-05-10 14:17:55 +00002399 if (cur == NULL) {
2400 /* error */
2401 break;
2402 }
William M. Brack76e95df2003-10-18 16:20:14 +00002403 if (!IS_BLANK_CH(*cur)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002404 /* error */
2405 break;
2406 }
2407 SKIP_BLANKS;
Daniel Veillardcda96922001-08-21 10:56:31 +00002408 cur = xmlParseSGMLCatalogPubid(cur, &sysid);
Daniel Veillarda7374592001-05-10 14:17:55 +00002409 if (cur == NULL) {
2410 /* error */
2411 break;
2412 }
2413 break;
Daniel Veillard344cee72001-08-20 00:08:40 +00002414 case SGML_CATA_PUBLIC:
2415 case SGML_CATA_SYSTEM:
2416 case SGML_CATA_DELEGATE:
Daniel Veillardcda96922001-08-21 10:56:31 +00002417 cur = xmlParseSGMLCatalogPubid(cur, &name);
Daniel Veillarda7374592001-05-10 14:17:55 +00002418 if (cur == NULL) {
2419 /* error */
2420 break;
2421 }
Daniel Veillardc8155052004-07-16 09:03:08 +00002422 if (type != SGML_CATA_SYSTEM) {
2423 xmlChar *normid;
2424
2425 normid = xmlCatalogNormalizePublic(name);
2426 if (normid != NULL) {
2427 if (name != NULL)
2428 xmlFree(name);
2429 if (*normid != 0)
2430 name = normid;
2431 else {
2432 xmlFree(normid);
2433 name = NULL;
2434 }
2435 }
2436 }
William M. Brack76e95df2003-10-18 16:20:14 +00002437 if (!IS_BLANK_CH(*cur)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002438 /* error */
2439 break;
2440 }
2441 SKIP_BLANKS;
Daniel Veillardcda96922001-08-21 10:56:31 +00002442 cur = xmlParseSGMLCatalogPubid(cur, &sysid);
Daniel Veillarda7374592001-05-10 14:17:55 +00002443 if (cur == NULL) {
2444 /* error */
2445 break;
2446 }
2447 break;
Daniel Veillard344cee72001-08-20 00:08:40 +00002448 case SGML_CATA_BASE:
2449 case SGML_CATA_CATALOG:
2450 case SGML_CATA_DOCUMENT:
2451 case SGML_CATA_SGMLDECL:
Daniel Veillardcda96922001-08-21 10:56:31 +00002452 cur = xmlParseSGMLCatalogPubid(cur, &sysid);
Daniel Veillarda7374592001-05-10 14:17:55 +00002453 if (cur == NULL) {
2454 /* error */
2455 break;
2456 }
2457 break;
2458 default:
2459 break;
2460 }
2461 if (cur == NULL) {
2462 if (name != NULL)
2463 xmlFree(name);
2464 if (sysid != NULL)
2465 xmlFree(sysid);
2466 break;
Daniel Veillard344cee72001-08-20 00:08:40 +00002467 } else if (type == SGML_CATA_BASE) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002468 if (base != NULL)
2469 xmlFree(base);
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002470 base = xmlStrdup(sysid);
Daniel Veillard344cee72001-08-20 00:08:40 +00002471 } else if ((type == SGML_CATA_PUBLIC) ||
2472 (type == SGML_CATA_SYSTEM)) {
Daniel Veillarda7374592001-05-10 14:17:55 +00002473 xmlChar *filename;
2474
2475 filename = xmlBuildURI(sysid, base);
2476 if (filename != NULL) {
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002477 xmlCatalogEntryPtr entry;
Daniel Veillarda7374592001-05-10 14:17:55 +00002478
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002479 entry = xmlNewCatalogEntry(type, name, filename,
William M. Brackb7b54de2004-10-06 16:38:01 +00002480 NULL, XML_CATA_PREFER_NONE, NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00002481 res = xmlHashAddEntry(catal->sgml, name, entry);
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002482 if (res < 0) {
2483 xmlFreeCatalogEntry(entry);
2484 }
2485 xmlFree(filename);
Daniel Veillarda7374592001-05-10 14:17:55 +00002486 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002487
Daniel Veillard344cee72001-08-20 00:08:40 +00002488 } else if (type == SGML_CATA_CATALOG) {
Daniel Veillard82d75332001-10-08 15:01:59 +00002489 if (super) {
2490 xmlCatalogEntryPtr entry;
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002491
Daniel Veillardc853b322001-11-06 15:24:37 +00002492 entry = xmlNewCatalogEntry(type, sysid, NULL, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00002493 XML_CATA_PREFER_NONE, NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00002494 res = xmlHashAddEntry(catal->sgml, sysid, entry);
Daniel Veillard82d75332001-10-08 15:01:59 +00002495 if (res < 0) {
2496 xmlFreeCatalogEntry(entry);
2497 }
2498 } else {
2499 xmlChar *filename;
2500
2501 filename = xmlBuildURI(sysid, base);
2502 if (filename != NULL) {
Daniel Veillard75b96822001-10-11 18:59:45 +00002503 xmlExpandCatalog(catal, (const char *)filename);
Daniel Veillard82d75332001-10-08 15:01:59 +00002504 xmlFree(filename);
2505 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002506 }
Daniel Veillarda7374592001-05-10 14:17:55 +00002507 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00002508 /*
2509 * drop anything else we won't handle it
2510 */
2511 if (name != NULL)
2512 xmlFree(name);
2513 if (sysid != NULL)
2514 xmlFree(sysid);
Daniel Veillarda7374592001-05-10 14:17:55 +00002515 }
2516 }
2517 if (base != NULL)
2518 xmlFree(base);
2519 if (cur == NULL)
2520 return(-1);
2521 return(0);
2522}
2523
Daniel Veillard75b96822001-10-11 18:59:45 +00002524/************************************************************************
2525 * *
2526 * SGML Catalog handling *
2527 * *
2528 ************************************************************************/
2529
Daniel Veillardcda96922001-08-21 10:56:31 +00002530/**
2531 * xmlCatalogGetSGMLPublic:
2532 * @catal: an SGML catalog hash
Daniel Veillard06d25242004-02-25 13:01:42 +00002533 * @pubID: the public ID string
Daniel Veillardcda96922001-08-21 10:56:31 +00002534 *
Daniel Veillard06d25242004-02-25 13:01:42 +00002535 * Try to lookup the catalog local reference associated to a public ID
Daniel Veillardcda96922001-08-21 10:56:31 +00002536 *
Daniel Veillard06d25242004-02-25 13:01:42 +00002537 * Returns the local resource if found or NULL otherwise.
Daniel Veillardcda96922001-08-21 10:56:31 +00002538 */
2539static const xmlChar *
2540xmlCatalogGetSGMLPublic(xmlHashTablePtr catal, const xmlChar *pubID) {
2541 xmlCatalogEntryPtr entry;
Daniel Veillardc8155052004-07-16 09:03:08 +00002542 xmlChar *normid;
Daniel Veillardcda96922001-08-21 10:56:31 +00002543
2544 if (catal == NULL)
2545 return(NULL);
2546
Daniel Veillardc8155052004-07-16 09:03:08 +00002547 normid = xmlCatalogNormalizePublic(pubID);
2548 if (normid != NULL)
2549 pubID = (*normid != 0 ? normid : NULL);
2550
Daniel Veillardcda96922001-08-21 10:56:31 +00002551 entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, pubID);
Daniel Veillardc8155052004-07-16 09:03:08 +00002552 if (entry == NULL) {
2553 if (normid != NULL)
2554 xmlFree(normid);
Daniel Veillardcda96922001-08-21 10:56:31 +00002555 return(NULL);
Daniel Veillardc8155052004-07-16 09:03:08 +00002556 }
2557 if (entry->type == SGML_CATA_PUBLIC) {
2558 if (normid != NULL)
2559 xmlFree(normid);
Daniel Veillardc853b322001-11-06 15:24:37 +00002560 return(entry->URL);
Daniel Veillardc8155052004-07-16 09:03:08 +00002561 }
2562 if (normid != NULL)
2563 xmlFree(normid);
Daniel Veillardcda96922001-08-21 10:56:31 +00002564 return(NULL);
2565}
2566
2567/**
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002568 * xmlCatalogGetSGMLSystem:
2569 * @catal: an SGML catalog hash
Daniel Veillard06d25242004-02-25 13:01:42 +00002570 * @sysID: the system ID string
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002571 *
2572 * Try to lookup the catalog local reference for a system ID
2573 *
Daniel Veillard770075b2004-02-25 10:44:30 +00002574 * Returns the local resource if found or NULL otherwise.
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002575 */
2576static const xmlChar *
2577xmlCatalogGetSGMLSystem(xmlHashTablePtr catal, const xmlChar *sysID) {
2578 xmlCatalogEntryPtr entry;
2579
2580 if (catal == NULL)
2581 return(NULL);
2582
2583 entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, sysID);
2584 if (entry == NULL)
2585 return(NULL);
2586 if (entry->type == SGML_CATA_SYSTEM)
Daniel Veillardc853b322001-11-06 15:24:37 +00002587 return(entry->URL);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00002588 return(NULL);
2589}
2590
2591/**
Daniel Veillardcda96922001-08-21 10:56:31 +00002592 * xmlCatalogSGMLResolve:
Daniel Veillard75b96822001-10-11 18:59:45 +00002593 * @catal: the SGML catalog
Daniel Veillard06d25242004-02-25 13:01:42 +00002594 * @pubID: the public ID string
2595 * @sysID: the system ID string
Daniel Veillardcda96922001-08-21 10:56:31 +00002596 *
2597 * Do a complete resolution lookup of an External Identifier
2598 *
2599 * Returns the URI of the resource or NULL if not found
2600 */
2601static const xmlChar *
Daniel Veillard75b96822001-10-11 18:59:45 +00002602xmlCatalogSGMLResolve(xmlCatalogPtr catal, const xmlChar *pubID,
2603 const xmlChar *sysID) {
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00002604 const xmlChar *ret = NULL;
2605
Daniel Veillard75b96822001-10-11 18:59:45 +00002606 if (catal->sgml == NULL)
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00002607 return(NULL);
2608
2609 if (pubID != NULL)
Daniel Veillard75b96822001-10-11 18:59:45 +00002610 ret = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00002611 if (ret != NULL)
2612 return(ret);
2613 if (sysID != NULL)
Daniel Veillard75b96822001-10-11 18:59:45 +00002614 ret = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
Daniel Veillard63806b52008-06-10 14:56:11 +00002615 if (ret != NULL)
2616 return(ret);
Daniel Veillardcda96922001-08-21 10:56:31 +00002617 return(NULL);
2618}
2619
Daniel Veillarda7374592001-05-10 14:17:55 +00002620/************************************************************************
2621 * *
Daniel Veillard75b96822001-10-11 18:59:45 +00002622 * Specific Public interfaces *
2623 * *
2624 ************************************************************************/
2625
2626/**
2627 * xmlLoadSGMLSuperCatalog:
2628 * @filename: a file path
2629 *
2630 * Load an SGML super catalog. It won't expand CATALOG or DELEGATE
2631 * references. This is only needed for manipulating SGML Super Catalogs
2632 * like adding and removing CATALOG or DELEGATE entries.
2633 *
2634 * Returns the catalog parsed or NULL in case of error
2635 */
2636xmlCatalogPtr
2637xmlLoadSGMLSuperCatalog(const char *filename)
2638{
2639 xmlChar *content;
2640 xmlCatalogPtr catal;
2641 int ret;
2642
2643 content = xmlLoadFileContent(filename);
2644 if (content == NULL)
2645 return(NULL);
2646
Daniel Veillardcd21dc72001-11-04 20:03:38 +00002647 catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
Daniel Veillard75b96822001-10-11 18:59:45 +00002648 if (catal == NULL) {
2649 xmlFree(content);
2650 return(NULL);
2651 }
2652
2653 ret = xmlParseSGMLCatalog(catal, content, filename, 1);
2654 xmlFree(content);
2655 if (ret < 0) {
2656 xmlFreeCatalog(catal);
2657 return(NULL);
2658 }
2659 return (catal);
2660}
2661
2662/**
2663 * xmlLoadACatalog:
2664 * @filename: a file path
2665 *
2666 * Load the catalog and build the associated data structures.
2667 * This can be either an XML Catalog or an SGML Catalog
2668 * It will recurse in SGML CATALOG entries. On the other hand XML
2669 * Catalogs are not handled recursively.
2670 *
2671 * Returns the catalog parsed or NULL in case of error
2672 */
2673xmlCatalogPtr
2674xmlLoadACatalog(const char *filename)
2675{
2676 xmlChar *content;
2677 xmlChar *first;
2678 xmlCatalogPtr catal;
2679 int ret;
2680
2681 content = xmlLoadFileContent(filename);
2682 if (content == NULL)
2683 return(NULL);
2684
2685
2686 first = content;
2687
2688 while ((*first != 0) && (*first != '-') && (*first != '<') &&
2689 (!(((*first >= 'A') && (*first <= 'Z')) ||
2690 ((*first >= 'a') && (*first <= 'z')))))
2691 first++;
2692
2693 if (*first != '<') {
Daniel Veillardcd21dc72001-11-04 20:03:38 +00002694 catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
Daniel Veillard75b96822001-10-11 18:59:45 +00002695 if (catal == NULL) {
2696 xmlFree(content);
2697 return(NULL);
2698 }
2699 ret = xmlParseSGMLCatalog(catal, content, filename, 0);
2700 if (ret < 0) {
2701 xmlFreeCatalog(catal);
2702 xmlFree(content);
2703 return(NULL);
2704 }
2705 } else {
Daniel Veillardcd21dc72001-11-04 20:03:38 +00002706 catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
Daniel Veillard75b96822001-10-11 18:59:45 +00002707 if (catal == NULL) {
2708 xmlFree(content);
2709 return(NULL);
2710 }
Daniel Veillardc853b322001-11-06 15:24:37 +00002711 catal->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00002712 NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00002713 }
2714 xmlFree(content);
2715 return (catal);
2716}
2717
2718/**
2719 * xmlExpandCatalog:
2720 * @catal: a catalog
2721 * @filename: a file path
2722 *
2723 * Load the catalog and expand the existing catal structure.
2724 * This can be either an XML Catalog or an SGML Catalog
2725 *
2726 * Returns 0 in case of success, -1 in case of error
2727 */
Daniel Veillard85c11fa2001-10-16 21:03:08 +00002728static int
Daniel Veillard75b96822001-10-11 18:59:45 +00002729xmlExpandCatalog(xmlCatalogPtr catal, const char *filename)
2730{
Daniel Veillard75b96822001-10-11 18:59:45 +00002731 int ret;
2732
2733 if ((catal == NULL) || (filename == NULL))
2734 return(-1);
2735
Daniel Veillard75b96822001-10-11 18:59:45 +00002736
2737 if (catal->type == XML_SGML_CATALOG_TYPE) {
Daniel Veillard85c11fa2001-10-16 21:03:08 +00002738 xmlChar *content;
2739
2740 content = xmlLoadFileContent(filename);
2741 if (content == NULL)
2742 return(-1);
2743
Daniel Veillard75b96822001-10-11 18:59:45 +00002744 ret = xmlParseSGMLCatalog(catal, content, filename, 0);
2745 if (ret < 0) {
2746 xmlFree(content);
2747 return(-1);
2748 }
Daniel Veillard85c11fa2001-10-16 21:03:08 +00002749 xmlFree(content);
Daniel Veillard75b96822001-10-11 18:59:45 +00002750 } else {
2751 xmlCatalogEntryPtr tmp, cur;
Daniel Veillardc853b322001-11-06 15:24:37 +00002752 tmp = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00002753 NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00002754
Daniel Veillard75b96822001-10-11 18:59:45 +00002755 cur = catal->xml;
2756 if (cur == NULL) {
2757 catal->xml = tmp;
2758 } else {
2759 while (cur->next != NULL) cur = cur->next;
2760 cur->next = tmp;
2761 }
Daniel Veillard75b96822001-10-11 18:59:45 +00002762 }
Daniel Veillard75b96822001-10-11 18:59:45 +00002763 return (0);
2764}
2765
2766/**
2767 * xmlACatalogResolveSystem:
2768 * @catal: a Catalog
Daniel Veillard06d25242004-02-25 13:01:42 +00002769 * @sysID: the system ID string
Daniel Veillard75b96822001-10-11 18:59:45 +00002770 *
2771 * Try to lookup the catalog resource for a system ID
2772 *
Daniel Veillard06d25242004-02-25 13:01:42 +00002773 * Returns the resource if found or NULL otherwise, the value returned
Daniel Veillard75b96822001-10-11 18:59:45 +00002774 * must be freed by the caller.
2775 */
2776xmlChar *
2777xmlACatalogResolveSystem(xmlCatalogPtr catal, const xmlChar *sysID) {
2778 xmlChar *ret = NULL;
2779
2780 if ((sysID == NULL) || (catal == NULL))
2781 return(NULL);
2782
2783 if (xmlDebugCatalogs)
2784 xmlGenericError(xmlGenericErrorContext,
2785 "Resolve sysID %s\n", sysID);
2786
2787 if (catal->type == XML_XML_CATALOG_TYPE) {
2788 ret = xmlCatalogListXMLResolve(catal->xml, NULL, sysID);
2789 if (ret == XML_CATAL_BREAK)
2790 ret = NULL;
2791 } else {
2792 const xmlChar *sgml;
2793
2794 sgml = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
2795 if (sgml != NULL)
2796 ret = xmlStrdup(sgml);
2797 }
2798 return(ret);
2799}
2800
2801/**
2802 * xmlACatalogResolvePublic:
2803 * @catal: a Catalog
Daniel Veillard5aad8322002-12-11 15:59:44 +00002804 * @pubID: the public ID string
Daniel Veillard75b96822001-10-11 18:59:45 +00002805 *
Daniel Veillard06d25242004-02-25 13:01:42 +00002806 * Try to lookup the catalog local reference associated to a public ID in that catalog
Daniel Veillard75b96822001-10-11 18:59:45 +00002807 *
Daniel Veillard06d25242004-02-25 13:01:42 +00002808 * Returns the local resource if found or NULL otherwise, the value returned
Daniel Veillard75b96822001-10-11 18:59:45 +00002809 * must be freed by the caller.
2810 */
2811xmlChar *
2812xmlACatalogResolvePublic(xmlCatalogPtr catal, const xmlChar *pubID) {
2813 xmlChar *ret = NULL;
2814
2815 if ((pubID == NULL) || (catal == NULL))
2816 return(NULL);
2817
2818 if (xmlDebugCatalogs)
2819 xmlGenericError(xmlGenericErrorContext,
2820 "Resolve pubID %s\n", pubID);
2821
2822 if (catal->type == XML_XML_CATALOG_TYPE) {
2823 ret = xmlCatalogListXMLResolve(catal->xml, pubID, NULL);
2824 if (ret == XML_CATAL_BREAK)
2825 ret = NULL;
2826 } else {
2827 const xmlChar *sgml;
2828
2829 sgml = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
2830 if (sgml != NULL)
2831 ret = xmlStrdup(sgml);
2832 }
2833 return(ret);
2834}
2835
2836/**
2837 * xmlACatalogResolve:
2838 * @catal: a Catalog
Daniel Veillard5aad8322002-12-11 15:59:44 +00002839 * @pubID: the public ID string
2840 * @sysID: the system ID string
Daniel Veillard75b96822001-10-11 18:59:45 +00002841 *
2842 * Do a complete resolution lookup of an External Identifier
2843 *
2844 * Returns the URI of the resource or NULL if not found, it must be freed
2845 * by the caller.
2846 */
2847xmlChar *
2848xmlACatalogResolve(xmlCatalogPtr catal, const xmlChar * pubID,
2849 const xmlChar * sysID)
2850{
2851 xmlChar *ret = NULL;
2852
2853 if (((pubID == NULL) && (sysID == NULL)) || (catal == NULL))
2854 return (NULL);
2855
2856 if (xmlDebugCatalogs) {
Daniel Veillard770075b2004-02-25 10:44:30 +00002857 if ((pubID != NULL) && (sysID != NULL)) {
2858 xmlGenericError(xmlGenericErrorContext,
2859 "Resolve: pubID %s sysID %s\n", pubID, sysID);
2860 } else if (pubID != NULL) {
2861 xmlGenericError(xmlGenericErrorContext,
2862 "Resolve: pubID %s\n", pubID);
2863 } else {
2864 xmlGenericError(xmlGenericErrorContext,
2865 "Resolve: sysID %s\n", sysID);
2866 }
Daniel Veillard75b96822001-10-11 18:59:45 +00002867 }
2868
2869 if (catal->type == XML_XML_CATALOG_TYPE) {
2870 ret = xmlCatalogListXMLResolve(catal->xml, pubID, sysID);
2871 if (ret == XML_CATAL_BREAK)
2872 ret = NULL;
2873 } else {
2874 const xmlChar *sgml;
2875
2876 sgml = xmlCatalogSGMLResolve(catal, pubID, sysID);
2877 if (sgml != NULL)
2878 ret = xmlStrdup(sgml);
2879 }
2880 return (ret);
2881}
2882
2883/**
2884 * xmlACatalogResolveURI:
2885 * @catal: a Catalog
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002886 * @URI: the URI
Daniel Veillard75b96822001-10-11 18:59:45 +00002887 *
2888 * Do a complete resolution lookup of an URI
2889 *
2890 * Returns the URI of the resource or NULL if not found, it must be freed
2891 * by the caller.
2892 */
2893xmlChar *
2894xmlACatalogResolveURI(xmlCatalogPtr catal, const xmlChar *URI) {
2895 xmlChar *ret = NULL;
2896
2897 if ((URI == NULL) || (catal == NULL))
2898 return(NULL);
2899
Daniel Veillardb44025c2001-10-11 22:55:55 +00002900 if (xmlDebugCatalogs)
Daniel Veillard75b96822001-10-11 18:59:45 +00002901 xmlGenericError(xmlGenericErrorContext,
2902 "Resolve URI %s\n", URI);
2903
2904 if (catal->type == XML_XML_CATALOG_TYPE) {
2905 ret = xmlCatalogListXMLResolveURI(catal->xml, URI);
2906 if (ret == XML_CATAL_BREAK)
2907 ret = NULL;
2908 } else {
2909 const xmlChar *sgml;
2910
2911 sgml = xmlCatalogSGMLResolve(catal, NULL, URI);
2912 if (sgml != NULL)
Daniel Veillard63806b52008-06-10 14:56:11 +00002913 ret = xmlStrdup(sgml);
Daniel Veillard75b96822001-10-11 18:59:45 +00002914 }
2915 return(ret);
2916}
2917
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002918#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard75b96822001-10-11 18:59:45 +00002919/**
2920 * xmlACatalogDump:
2921 * @catal: a Catalog
2922 * @out: the file.
2923 *
Daniel Veillarda8dc2882004-03-29 12:21:26 +00002924 * Dump the given catalog to the given file.
Daniel Veillard75b96822001-10-11 18:59:45 +00002925 */
2926void
2927xmlACatalogDump(xmlCatalogPtr catal, FILE *out) {
Daniel Veillardcd21dc72001-11-04 20:03:38 +00002928 if ((out == NULL) || (catal == NULL))
Daniel Veillard75b96822001-10-11 18:59:45 +00002929 return;
2930
2931 if (catal->type == XML_XML_CATALOG_TYPE) {
2932 xmlDumpXMLCatalog(out, catal->xml);
2933 } else {
2934 xmlHashScan(catal->sgml,
2935 (xmlHashScanner) xmlCatalogDumpEntry, out);
2936 }
2937}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002938#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard75b96822001-10-11 18:59:45 +00002939
2940/**
2941 * xmlACatalogAdd:
2942 * @catal: a Catalog
2943 * @type: the type of record to add to the catalog
2944 * @orig: the system, public or prefix to match
2945 * @replace: the replacement value for the match
2946 *
2947 * Add an entry in the catalog, it may overwrite existing but
2948 * different entries.
2949 *
2950 * Returns 0 if successful, -1 otherwise
2951 */
2952int
2953xmlACatalogAdd(xmlCatalogPtr catal, const xmlChar * type,
2954 const xmlChar * orig, const xmlChar * replace)
2955{
2956 int res = -1;
2957
2958 if (catal == NULL)
2959 return(-1);
2960
2961 if (catal->type == XML_XML_CATALOG_TYPE) {
2962 res = xmlAddXMLCatalog(catal->xml, type, orig, replace);
2963 } else {
2964 xmlCatalogEntryType cattype;
2965
2966 cattype = xmlGetSGMLCatalogEntryType(type);
2967 if (cattype != XML_CATA_NONE) {
2968 xmlCatalogEntryPtr entry;
2969
Daniel Veillardc853b322001-11-06 15:24:37 +00002970 entry = xmlNewCatalogEntry(cattype, orig, replace, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00002971 XML_CATA_PREFER_NONE, NULL);
Daniel Veillardcd21dc72001-11-04 20:03:38 +00002972 if (catal->sgml == NULL)
2973 catal->sgml = xmlHashCreate(10);
Daniel Veillard75b96822001-10-11 18:59:45 +00002974 res = xmlHashAddEntry(catal->sgml, orig, entry);
2975 }
2976 }
2977 return (res);
2978}
2979
2980/**
2981 * xmlACatalogRemove:
2982 * @catal: a Catalog
2983 * @value: the value to remove
2984 *
2985 * Remove an entry from the catalog
2986 *
2987 * Returns the number of entries removed if successful, -1 otherwise
2988 */
2989int
2990xmlACatalogRemove(xmlCatalogPtr catal, const xmlChar *value) {
2991 int res = -1;
2992
2993 if ((catal == NULL) || (value == NULL))
2994 return(-1);
2995
2996 if (catal->type == XML_XML_CATALOG_TYPE) {
2997 res = xmlDelXMLCatalog(catal->xml, value);
2998 } else {
2999 res = xmlHashRemoveEntry(catal->sgml, value,
3000 (xmlHashDeallocator) xmlFreeCatalogEntry);
3001 if (res == 0)
3002 res = 1;
3003 }
3004 return(res);
3005}
3006
Daniel Veillardcd21dc72001-11-04 20:03:38 +00003007/**
3008 * xmlNewCatalog:
3009 * @sgml: should this create an SGML catalog
3010 *
3011 * create a new Catalog.
3012 *
3013 * Returns the xmlCatalogPtr or NULL in case of error
3014 */
3015xmlCatalogPtr
3016xmlNewCatalog(int sgml) {
3017 xmlCatalogPtr catal = NULL;
3018
3019 if (sgml) {
3020 catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE,
3021 xmlCatalogDefaultPrefer);
3022 if ((catal != NULL) && (catal->sgml == NULL))
3023 catal->sgml = xmlHashCreate(10);
3024 } else
3025 catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3026 xmlCatalogDefaultPrefer);
3027 return(catal);
3028}
3029
3030/**
3031 * xmlCatalogIsEmpty:
3032 * @catal: should this create an SGML catalog
3033 *
3034 * Check is a catalog is empty
3035 *
3036 * Returns 1 if the catalog is empty, 0 if not, amd -1 in case of error.
3037 */
3038int
3039xmlCatalogIsEmpty(xmlCatalogPtr catal) {
3040 if (catal == NULL)
3041 return(-1);
3042
3043 if (catal->type == XML_XML_CATALOG_TYPE) {
3044 if (catal->xml == NULL)
3045 return(1);
3046 if ((catal->xml->type != XML_CATA_CATALOG) &&
3047 (catal->xml->type != XML_CATA_BROKEN_CATALOG))
3048 return(-1);
3049 if (catal->xml->children == NULL)
3050 return(1);
3051 return(0);
3052 } else {
3053 int res;
3054
3055 if (catal->sgml == NULL)
3056 return(1);
3057 res = xmlHashSize(catal->sgml);
3058 if (res == 0)
3059 return(1);
3060 if (res < 0)
3061 return(-1);
3062 }
3063 return(0);
3064}
3065
Daniel Veillard75b96822001-10-11 18:59:45 +00003066/************************************************************************
3067 * *
3068 * Public interfaces manipulating the global shared default catalog *
Daniel Veillarda7374592001-05-10 14:17:55 +00003069 * *
3070 ************************************************************************/
3071
Daniel Veillard5e2dace2001-07-18 19:30:27 +00003072/**
Daniel Veillard81463942001-10-16 12:34:39 +00003073 * xmlInitializeCatalogData:
3074 *
3075 * Do the catalog initialization only of global data, doesn't try to load
3076 * any catalog actually.
3077 * this function is not thread safe, catalog initialization should
3078 * preferably be done once at startup
3079 */
3080static void
3081xmlInitializeCatalogData(void) {
3082 if (xmlCatalogInitialized != 0)
3083 return;
3084
3085 if (getenv("XML_DEBUG_CATALOG"))
3086 xmlDebugCatalogs = 1;
3087 xmlCatalogMutex = xmlNewRMutex();
3088
3089 xmlCatalogInitialized = 1;
3090}
3091/**
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003092 * xmlInitializeCatalog:
3093 *
3094 * Do the catalog initialization.
Daniel Veillard81463942001-10-16 12:34:39 +00003095 * this function is not thread safe, catalog initialization should
3096 * preferably be done once at startup
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003097 */
3098void
3099xmlInitializeCatalog(void) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003100 if (xmlCatalogInitialized != 0)
3101 return;
3102
Daniel Veillard81463942001-10-16 12:34:39 +00003103 xmlInitializeCatalogData();
3104 xmlRMutexLock(xmlCatalogMutex);
3105
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003106 if (getenv("XML_DEBUG_CATALOG"))
3107 xmlDebugCatalogs = 1;
Daniel Veillard81463942001-10-16 12:34:39 +00003108
Daniel Veillard75b96822001-10-11 18:59:45 +00003109 if (xmlDefaultCatalog == NULL) {
3110 const char *catalogs;
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003111 char *path;
3112 const char *cur, *paths;
Daniel Veillard75b96822001-10-11 18:59:45 +00003113 xmlCatalogPtr catal;
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003114 xmlCatalogEntryPtr *nextent;
Daniel Veillard75b96822001-10-11 18:59:45 +00003115
Daniel Veillardb44025c2001-10-11 22:55:55 +00003116 catalogs = (const char *) getenv("XML_CATALOG_FILES");
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003117 if (catalogs == NULL)
Daniel Veillardfb382b82004-06-14 12:13:12 +00003118#if defined(_WIN32) && defined(_MSC_VER)
3119 {
3120 void* hmodule;
3121 hmodule = GetModuleHandleA("libxml2.dll");
3122 if (hmodule == NULL)
3123 hmodule = GetModuleHandleA(NULL);
3124 if (hmodule != NULL) {
3125 char buf[256];
3126 unsigned long len = GetModuleFileNameA(hmodule, buf, 255);
3127 if (len != 0) {
3128 char* p = &(buf[len]);
3129 while (*p != '\\' && p > buf)
3130 p--;
3131 if (p != buf) {
3132 xmlChar* uri;
3133 strncpy(p, "\\..\\etc\\catalog", 255 - (p - buf));
3134 uri = xmlCanonicPath(buf);
3135 if (uri != NULL) {
3136 strncpy(XML_XML_DEFAULT_CATALOG, uri, 255);
3137 xmlFree(uri);
3138 }
3139 }
3140 }
3141 }
3142 catalogs = XML_XML_DEFAULT_CATALOG;
3143 }
3144#else
Daniel Veillard75b96822001-10-11 18:59:45 +00003145 catalogs = XML_XML_DEFAULT_CATALOG;
Daniel Veillardfb382b82004-06-14 12:13:12 +00003146#endif
Daniel Veillard75b96822001-10-11 18:59:45 +00003147
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003148 catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3149 xmlCatalogDefaultPrefer);
Daniel Veillard85c11fa2001-10-16 21:03:08 +00003150 if (catal != NULL) {
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003151 /* the XML_CATALOG_FILES envvar is allowed to contain a
3152 space-separated list of entries. */
3153 cur = catalogs;
3154 nextent = &catal->xml;
3155 while (*cur != '\0') {
William M. Brack68aca052003-10-11 15:22:13 +00003156 while (xmlIsBlank_ch(*cur))
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003157 cur++;
3158 if (*cur != 0) {
3159 paths = cur;
William M. Brack68aca052003-10-11 15:22:13 +00003160 while ((*cur != 0) && (!xmlIsBlank_ch(*cur)))
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003161 cur++;
Daniel Veillarde645e8c2002-10-22 17:35:37 +00003162 path = (char *) xmlStrndup((const xmlChar *)paths, cur - paths);
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003163 if (path != NULL) {
3164 *nextent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00003165 NULL, BAD_CAST path, xmlCatalogDefaultPrefer, NULL);
Igor Zlatkovic124ec312002-10-04 13:32:49 +00003166 if (*nextent != NULL)
3167 nextent = &((*nextent)->next);
3168 xmlFree(path);
3169 }
3170 }
3171 }
Daniel Veillard85c11fa2001-10-16 21:03:08 +00003172 xmlDefaultCatalog = catal;
3173 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003174 }
3175
Daniel Veillard81463942001-10-16 12:34:39 +00003176 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003177}
3178
Daniel Veillard82d75332001-10-08 15:01:59 +00003179
3180/**
Daniel Veillarda7374592001-05-10 14:17:55 +00003181 * xmlLoadCatalog:
3182 * @filename: a file path
3183 *
Daniel Veillard81418e32001-05-22 15:08:55 +00003184 * Load the catalog and makes its definitions effective for the default
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003185 * external entity loader. It will recurse in SGML CATALOG entries.
Daniel Veillard81463942001-10-16 12:34:39 +00003186 * this function is not thread safe, catalog initialization should
3187 * preferably be done once at startup
Daniel Veillarda7374592001-05-10 14:17:55 +00003188 *
3189 * Returns 0 in case of success -1 in case of error
3190 */
3191int
Daniel Veillard16756b62001-10-01 07:36:25 +00003192xmlLoadCatalog(const char *filename)
3193{
Daniel Veillard75b96822001-10-11 18:59:45 +00003194 int ret;
3195 xmlCatalogPtr catal;
Daniel Veillard16756b62001-10-01 07:36:25 +00003196
Daniel Veillard81463942001-10-16 12:34:39 +00003197 if (!xmlCatalogInitialized)
3198 xmlInitializeCatalogData();
3199
3200 xmlRMutexLock(xmlCatalogMutex);
3201
Daniel Veillard75b96822001-10-11 18:59:45 +00003202 if (xmlDefaultCatalog == NULL) {
3203 catal = xmlLoadACatalog(filename);
William M. Brack59002e72003-07-04 17:01:59 +00003204 if (catal == NULL) {
3205 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003206 return(-1);
William M. Brack59002e72003-07-04 17:01:59 +00003207 }
Daniel Veillarda7374592001-05-10 14:17:55 +00003208
Daniel Veillard75b96822001-10-11 18:59:45 +00003209 xmlDefaultCatalog = catal;
Daniel Veillard81463942001-10-16 12:34:39 +00003210 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003211 return(0);
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00003212 }
Daniel Veillardaf86c7f2001-05-21 14:11:26 +00003213
Daniel Veillard75b96822001-10-11 18:59:45 +00003214 ret = xmlExpandCatalog(xmlDefaultCatalog, filename);
Daniel Veillard81463942001-10-16 12:34:39 +00003215 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003216 return(ret);
Daniel Veillarda7374592001-05-10 14:17:55 +00003217}
3218
Daniel Veillard5e2dace2001-07-18 19:30:27 +00003219/**
Daniel Veillard81418e32001-05-22 15:08:55 +00003220 * xmlLoadCatalogs:
Daniel Veillard5aad8322002-12-11 15:59:44 +00003221 * @pathss: a list of directories separated by a colon or a space.
Daniel Veillard81418e32001-05-22 15:08:55 +00003222 *
3223 * Load the catalogs and makes their definitions effective for the default
3224 * external entity loader.
Daniel Veillard81463942001-10-16 12:34:39 +00003225 * this function is not thread safe, catalog initialization should
3226 * preferably be done once at startup
Daniel Veillard81418e32001-05-22 15:08:55 +00003227 */
3228void
3229xmlLoadCatalogs(const char *pathss) {
3230 const char *cur;
3231 const char *paths;
3232 xmlChar *path;
Daniel Veillarded121382007-04-17 12:33:19 +00003233#ifdef _WIN32
3234 int i, iLen;
3235#endif
Daniel Veillard81418e32001-05-22 15:08:55 +00003236
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003237 if (pathss == NULL)
3238 return;
3239
Daniel Veillard81418e32001-05-22 15:08:55 +00003240 cur = pathss;
Daniel Veillard2728f842006-03-09 16:49:24 +00003241 while (*cur != 0) {
William M. Brack68aca052003-10-11 15:22:13 +00003242 while (xmlIsBlank_ch(*cur)) cur++;
Daniel Veillard81418e32001-05-22 15:08:55 +00003243 if (*cur != 0) {
3244 paths = cur;
Daniel Veillarded121382007-04-17 12:33:19 +00003245 while ((*cur != 0) && (*cur != PATH_SEAPARATOR) && (!xmlIsBlank_ch(*cur)))
Daniel Veillard81418e32001-05-22 15:08:55 +00003246 cur++;
3247 path = xmlStrndup((const xmlChar *)paths, cur - paths);
Daniel Veillarded121382007-04-17 12:33:19 +00003248#ifdef _WIN32
3249 iLen = strlen(path);
3250 for(i = 0; i < iLen; i++) {
3251 if(path[i] == '\\') {
3252 path[i] = '/';
3253 }
3254 }
3255#endif
Daniel Veillard81418e32001-05-22 15:08:55 +00003256 if (path != NULL) {
3257 xmlLoadCatalog((const char *) path);
3258 xmlFree(path);
3259 }
3260 }
Daniel Veillarded121382007-04-17 12:33:19 +00003261 while (*cur == PATH_SEAPARATOR)
Igor Zlatkovic130e5792002-11-06 22:51:58 +00003262 cur++;
Daniel Veillard81418e32001-05-22 15:08:55 +00003263 }
3264}
3265
Daniel Veillarda7374592001-05-10 14:17:55 +00003266/**
3267 * xmlCatalogCleanup:
3268 *
3269 * Free up all the memory associated with catalogs
3270 */
3271void
3272xmlCatalogCleanup(void) {
Daniel Veillard364789a2001-10-16 12:45:00 +00003273 if (xmlCatalogInitialized == 0)
3274 return;
3275
Daniel Veillard81463942001-10-16 12:34:39 +00003276 xmlRMutexLock(xmlCatalogMutex);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003277 if (xmlDebugCatalogs)
3278 xmlGenericError(xmlGenericErrorContext,
3279 "Catalogs cleanup\n");
Daniel Veillard6990bf32001-08-23 21:17:48 +00003280 if (xmlCatalogXMLFiles != NULL)
Daniel Veillard85c11fa2001-10-16 21:03:08 +00003281 xmlHashFree(xmlCatalogXMLFiles,
3282 (xmlHashDeallocator)xmlFreeCatalogHashEntryList);
Daniel Veillard6990bf32001-08-23 21:17:48 +00003283 xmlCatalogXMLFiles = NULL;
Daniel Veillarda7374592001-05-10 14:17:55 +00003284 if (xmlDefaultCatalog != NULL)
Daniel Veillard75b96822001-10-11 18:59:45 +00003285 xmlFreeCatalog(xmlDefaultCatalog);
Daniel Veillard6990bf32001-08-23 21:17:48 +00003286 xmlDefaultCatalog = NULL;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003287 xmlDebugCatalogs = 0;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003288 xmlCatalogInitialized = 0;
Daniel Veillard81463942001-10-16 12:34:39 +00003289 xmlRMutexUnlock(xmlCatalogMutex);
3290 xmlFreeRMutex(xmlCatalogMutex);
Daniel Veillarda7374592001-05-10 14:17:55 +00003291}
3292
3293/**
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003294 * xmlCatalogResolveSystem:
Daniel Veillard06d25242004-02-25 13:01:42 +00003295 * @sysID: the system ID string
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003296 *
3297 * Try to lookup the catalog resource for a system ID
3298 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003299 * Returns the resource if found or NULL otherwise, the value returned
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003300 * must be freed by the caller.
3301 */
3302xmlChar *
3303xmlCatalogResolveSystem(const xmlChar *sysID) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003304 xmlChar *ret;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003305
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003306 if (!xmlCatalogInitialized)
3307 xmlInitializeCatalog();
3308
Daniel Veillard75b96822001-10-11 18:59:45 +00003309 ret = xmlACatalogResolveSystem(xmlDefaultCatalog, sysID);
3310 return(ret);
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003311}
3312
3313/**
3314 * xmlCatalogResolvePublic:
Daniel Veillard5aad8322002-12-11 15:59:44 +00003315 * @pubID: the public ID string
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003316 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003317 * Try to lookup the catalog reference associated to a public ID
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003318 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003319 * Returns the resource if found or NULL otherwise, the value returned
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003320 * must be freed by the caller.
3321 */
3322xmlChar *
3323xmlCatalogResolvePublic(const xmlChar *pubID) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003324 xmlChar *ret;
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003325
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003326 if (!xmlCatalogInitialized)
3327 xmlInitializeCatalog();
3328
Daniel Veillard75b96822001-10-11 18:59:45 +00003329 ret = xmlACatalogResolvePublic(xmlDefaultCatalog, pubID);
3330 return(ret);
Daniel Veillard7d6fd212001-05-10 15:34:11 +00003331}
Daniel Veillard344cee72001-08-20 00:08:40 +00003332
Daniel Veillard7d6fd212001-05-10 15:34:11 +00003333/**
Daniel Veillardcda96922001-08-21 10:56:31 +00003334 * xmlCatalogResolve:
Daniel Veillard5aad8322002-12-11 15:59:44 +00003335 * @pubID: the public ID string
3336 * @sysID: the system ID string
Daniel Veillardcda96922001-08-21 10:56:31 +00003337 *
3338 * Do a complete resolution lookup of an External Identifier
3339 *
3340 * Returns the URI of the resource or NULL if not found, it must be freed
3341 * by the caller.
3342 */
3343xmlChar *
3344xmlCatalogResolve(const xmlChar *pubID, const xmlChar *sysID) {
Daniel Veillard75b96822001-10-11 18:59:45 +00003345 xmlChar *ret;
Daniel Veillard6990bf32001-08-23 21:17:48 +00003346
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003347 if (!xmlCatalogInitialized)
3348 xmlInitializeCatalog();
3349
Daniel Veillard75b96822001-10-11 18:59:45 +00003350 ret = xmlACatalogResolve(xmlDefaultCatalog, pubID, sysID);
3351 return(ret);
Daniel Veillardcda96922001-08-21 10:56:31 +00003352}
3353
3354/**
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003355 * xmlCatalogResolveURI:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00003356 * @URI: the URI
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003357 *
3358 * Do a complete resolution lookup of an URI
3359 *
3360 * Returns the URI of the resource or NULL if not found, it must be freed
3361 * by the caller.
3362 */
3363xmlChar *
3364xmlCatalogResolveURI(const xmlChar *URI) {
Daniel Veillard75b96822001-10-11 18:59:45 +00003365 xmlChar *ret;
3366
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003367 if (!xmlCatalogInitialized)
3368 xmlInitializeCatalog();
3369
Daniel Veillard75b96822001-10-11 18:59:45 +00003370 ret = xmlACatalogResolveURI(xmlDefaultCatalog, URI);
3371 return(ret);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003372}
3373
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003374#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003375/**
Daniel Veillarda7374592001-05-10 14:17:55 +00003376 * xmlCatalogDump:
3377 * @out: the file.
3378 *
Daniel Veillarda8dc2882004-03-29 12:21:26 +00003379 * Dump all the global catalog content to the given file.
Daniel Veillarda7374592001-05-10 14:17:55 +00003380 */
3381void
3382xmlCatalogDump(FILE *out) {
3383 if (out == NULL)
3384 return;
Daniel Veillard344cee72001-08-20 00:08:40 +00003385
Daniel Veillard75b96822001-10-11 18:59:45 +00003386 if (!xmlCatalogInitialized)
3387 xmlInitializeCatalog();
3388
3389 xmlACatalogDump(xmlDefaultCatalog, out);
Daniel Veillard344cee72001-08-20 00:08:40 +00003390}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003391#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard344cee72001-08-20 00:08:40 +00003392
3393/**
3394 * xmlCatalogAdd:
3395 * @type: the type of record to add to the catalog
3396 * @orig: the system, public or prefix to match
3397 * @replace: the replacement value for the match
3398 *
3399 * Add an entry in the catalog, it may overwrite existing but
3400 * different entries.
Daniel Veillardcbaf3992001-12-31 16:16:02 +00003401 * If called before any other catalog routine, allows to override the
Daniel Veillard75b96822001-10-11 18:59:45 +00003402 * default shared catalog put in place by xmlInitializeCatalog();
Daniel Veillard344cee72001-08-20 00:08:40 +00003403 *
3404 * Returns 0 if successful, -1 otherwise
3405 */
3406int
3407xmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace) {
3408 int res = -1;
3409
Daniel Veillard81463942001-10-16 12:34:39 +00003410 if (!xmlCatalogInitialized)
3411 xmlInitializeCatalogData();
3412
3413 xmlRMutexLock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003414 /*
3415 * Specific case where one want to override the default catalog
3416 * put in place by xmlInitializeCatalog();
3417 */
3418 if ((xmlDefaultCatalog == NULL) &&
Daniel Veillarde7ead2d2001-08-22 23:44:09 +00003419 (xmlStrEqual(type, BAD_CAST "catalog"))) {
Daniel Veillardcd21dc72001-11-04 20:03:38 +00003420 xmlDefaultCatalog = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
Daniel Veillard75b96822001-10-11 18:59:45 +00003421 xmlCatalogDefaultPrefer);
3422 xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00003423 orig, NULL, xmlCatalogDefaultPrefer, NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00003424
Daniel Veillard81463942001-10-16 12:34:39 +00003425 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillarde7ead2d2001-08-22 23:44:09 +00003426 return(0);
3427 }
3428
Daniel Veillard75b96822001-10-11 18:59:45 +00003429 res = xmlACatalogAdd(xmlDefaultCatalog, type, orig, replace);
Daniel Veillard81463942001-10-16 12:34:39 +00003430 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillard344cee72001-08-20 00:08:40 +00003431 return(res);
3432}
3433
3434/**
3435 * xmlCatalogRemove:
3436 * @value: the value to remove
3437 *
3438 * Remove an entry from the catalog
3439 *
Daniel Veillard82d75332001-10-08 15:01:59 +00003440 * Returns the number of entries removed if successful, -1 otherwise
Daniel Veillard344cee72001-08-20 00:08:40 +00003441 */
3442int
3443xmlCatalogRemove(const xmlChar *value) {
Daniel Veillard75b96822001-10-11 18:59:45 +00003444 int res;
Daniel Veillardcda96922001-08-21 10:56:31 +00003445
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003446 if (!xmlCatalogInitialized)
3447 xmlInitializeCatalog();
3448
Daniel Veillard81463942001-10-16 12:34:39 +00003449 xmlRMutexLock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003450 res = xmlACatalogRemove(xmlDefaultCatalog, value);
Daniel Veillard81463942001-10-16 12:34:39 +00003451 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillardcda96922001-08-21 10:56:31 +00003452 return(res);
Daniel Veillard344cee72001-08-20 00:08:40 +00003453}
3454
3455/**
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003456 * xmlCatalogConvert:
3457 *
3458 * Convert all the SGML catalog entries as XML ones
3459 *
3460 * Returns the number of entries converted if successful, -1 otherwise
3461 */
3462int
3463xmlCatalogConvert(void) {
3464 int res = -1;
3465
3466 if (!xmlCatalogInitialized)
3467 xmlInitializeCatalog();
3468
Daniel Veillard81463942001-10-16 12:34:39 +00003469 xmlRMutexLock(xmlCatalogMutex);
Daniel Veillard75b96822001-10-11 18:59:45 +00003470 res = xmlConvertSGMLCatalog(xmlDefaultCatalog);
Daniel Veillard81463942001-10-16 12:34:39 +00003471 xmlRMutexUnlock(xmlCatalogMutex);
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003472 return(res);
3473}
3474
Daniel Veillard75b96822001-10-11 18:59:45 +00003475/************************************************************************
3476 * *
3477 * Public interface manipulating the common preferences *
3478 * *
3479 ************************************************************************/
Daniel Veillard81463942001-10-16 12:34:39 +00003480
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003481/**
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003482 * xmlCatalogGetDefaults:
3483 *
3484 * Used to get the user preference w.r.t. to what catalogs should
3485 * be accepted
3486 *
3487 * Returns the current xmlCatalogAllow value
3488 */
3489xmlCatalogAllow
3490xmlCatalogGetDefaults(void) {
3491 return(xmlCatalogDefaultAllow);
3492}
3493
3494/**
3495 * xmlCatalogSetDefaults:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00003496 * @allow: what catalogs should be accepted
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003497 *
3498 * Used to set the user preference w.r.t. to what catalogs should
3499 * be accepted
3500 */
3501void
3502xmlCatalogSetDefaults(xmlCatalogAllow allow) {
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003503 if (xmlDebugCatalogs) {
3504 switch (allow) {
3505 case XML_CATA_ALLOW_NONE:
3506 xmlGenericError(xmlGenericErrorContext,
3507 "Disabling catalog usage\n");
3508 break;
3509 case XML_CATA_ALLOW_GLOBAL:
3510 xmlGenericError(xmlGenericErrorContext,
3511 "Allowing only global catalogs\n");
3512 break;
3513 case XML_CATA_ALLOW_DOCUMENT:
3514 xmlGenericError(xmlGenericErrorContext,
3515 "Allowing only catalogs from the document\n");
3516 break;
3517 case XML_CATA_ALLOW_ALL:
3518 xmlGenericError(xmlGenericErrorContext,
3519 "Allowing all catalogs\n");
3520 break;
3521 }
3522 }
3523 xmlCatalogDefaultAllow = allow;
3524}
3525
3526/**
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003527 * xmlCatalogSetDefaultPrefer:
3528 * @prefer: the default preference for delegation
3529 *
3530 * Allows to set the preference between public and system for deletion
3531 * in XML Catalog resolution. C.f. section 4.1.1 of the spec
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003532 * Values accepted are XML_CATA_PREFER_PUBLIC or XML_CATA_PREFER_SYSTEM
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003533 *
3534 * Returns the previous value of the default preference for delegation
3535 */
3536xmlCatalogPrefer
3537xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer) {
3538 xmlCatalogPrefer ret = xmlCatalogDefaultPrefer;
3539
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003540 if (prefer == XML_CATA_PREFER_NONE)
3541 return(ret);
3542
3543 if (xmlDebugCatalogs) {
3544 switch (prefer) {
3545 case XML_CATA_PREFER_PUBLIC:
3546 xmlGenericError(xmlGenericErrorContext,
3547 "Setting catalog preference to PUBLIC\n");
3548 break;
3549 case XML_CATA_PREFER_SYSTEM:
3550 xmlGenericError(xmlGenericErrorContext,
3551 "Setting catalog preference to SYSTEM\n");
3552 break;
3553 case XML_CATA_PREFER_NONE:
3554 break;
3555 }
3556 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00003557 xmlCatalogDefaultPrefer = prefer;
3558 return(ret);
3559}
3560
3561/**
Daniel Veillard344cee72001-08-20 00:08:40 +00003562 * xmlCatalogSetDebug:
3563 * @level: the debug level of catalogs required
3564 *
3565 * Used to set the debug level for catalog operation, 0 disable
3566 * debugging, 1 enable it
3567 *
3568 * Returns the previous value of the catalog debugging level
3569 */
3570int
3571xmlCatalogSetDebug(int level) {
3572 int ret = xmlDebugCatalogs;
3573
3574 if (level <= 0)
3575 xmlDebugCatalogs = 0;
3576 else
3577 xmlDebugCatalogs = level;
3578 return(ret);
Daniel Veillarda7374592001-05-10 14:17:55 +00003579}
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003580
Daniel Veillard75b96822001-10-11 18:59:45 +00003581/************************************************************************
3582 * *
3583 * Minimal interfaces used for per-document catalogs by the parser *
3584 * *
3585 ************************************************************************/
3586
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003587/**
3588 * xmlCatalogFreeLocal:
3589 * @catalogs: a document's list of catalogs
3590 *
3591 * Free up the memory associated to the catalog list
3592 */
3593void
3594xmlCatalogFreeLocal(void *catalogs) {
3595 xmlCatalogEntryPtr catal;
3596
Daniel Veillard81463942001-10-16 12:34:39 +00003597 if (!xmlCatalogInitialized)
3598 xmlInitializeCatalog();
3599
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003600 catal = (xmlCatalogEntryPtr) catalogs;
3601 if (catal != NULL)
3602 xmlFreeCatalogEntryList(catal);
3603}
3604
3605
3606/**
3607 * xmlCatalogAddLocal:
3608 * @catalogs: a document's list of catalogs
3609 * @URL: the URL to a new local catalog
3610 *
3611 * Add the new entry to the catalog list
3612 *
3613 * Returns the updated list
3614 */
3615void *
3616xmlCatalogAddLocal(void *catalogs, const xmlChar *URL) {
3617 xmlCatalogEntryPtr catal, add;
3618
3619 if (!xmlCatalogInitialized)
3620 xmlInitializeCatalog();
Daniel Veillard81463942001-10-16 12:34:39 +00003621
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003622 if (URL == NULL)
3623 return(catalogs);
3624
3625 if (xmlDebugCatalogs)
3626 xmlGenericError(xmlGenericErrorContext,
3627 "Adding document catalog %s\n", URL);
3628
Daniel Veillardc853b322001-11-06 15:24:37 +00003629 add = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, URL, NULL,
William M. Brackb7b54de2004-10-06 16:38:01 +00003630 xmlCatalogDefaultPrefer, NULL);
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003631 if (add == NULL)
3632 return(catalogs);
3633
3634 catal = (xmlCatalogEntryPtr) catalogs;
3635 if (catal == NULL)
3636 return((void *) add);
3637
3638 while (catal->next != NULL)
3639 catal = catal->next;
3640 catal->next = add;
3641 return(catalogs);
3642}
3643
3644/**
3645 * xmlCatalogLocalResolve:
3646 * @catalogs: a document's list of catalogs
Daniel Veillard5aad8322002-12-11 15:59:44 +00003647 * @pubID: the public ID string
3648 * @sysID: the system ID string
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003649 *
3650 * Do a complete resolution lookup of an External Identifier using a
3651 * document's private catalog list
3652 *
3653 * Returns the URI of the resource or NULL if not found, it must be freed
3654 * by the caller.
3655 */
3656xmlChar *
3657xmlCatalogLocalResolve(void *catalogs, const xmlChar *pubID,
3658 const xmlChar *sysID) {
3659 xmlCatalogEntryPtr catal;
Daniel Veillard6990bf32001-08-23 21:17:48 +00003660 xmlChar *ret;
3661
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003662 if (!xmlCatalogInitialized)
3663 xmlInitializeCatalog();
Daniel Veillard6990bf32001-08-23 21:17:48 +00003664
Daniel Veillard81463942001-10-16 12:34:39 +00003665 if ((pubID == NULL) && (sysID == NULL))
3666 return(NULL);
3667
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003668 if (xmlDebugCatalogs) {
Daniel Veillard770075b2004-02-25 10:44:30 +00003669 if ((pubID != NULL) && (sysID != NULL)) {
3670 xmlGenericError(xmlGenericErrorContext,
3671 "Local Resolve: pubID %s sysID %s\n", pubID, sysID);
3672 } else if (pubID != NULL) {
3673 xmlGenericError(xmlGenericErrorContext,
3674 "Local Resolve: pubID %s\n", pubID);
3675 } else {
3676 xmlGenericError(xmlGenericErrorContext,
3677 "Local Resolve: sysID %s\n", sysID);
3678 }
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00003679 }
Daniel Veillard6990bf32001-08-23 21:17:48 +00003680
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003681 catal = (xmlCatalogEntryPtr) catalogs;
3682 if (catal == NULL)
3683 return(NULL);
Daniel Veillard6990bf32001-08-23 21:17:48 +00003684 ret = xmlCatalogListXMLResolve(catal, pubID, sysID);
3685 if ((ret != NULL) && (ret != XML_CATAL_BREAK))
3686 return(ret);
3687 return(NULL);
Daniel Veillard5d90b6c2001-08-22 14:29:45 +00003688}
3689
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003690/**
3691 * xmlCatalogLocalResolveURI:
3692 * @catalogs: a document's list of catalogs
Daniel Veillardcbaf3992001-12-31 16:16:02 +00003693 * @URI: the URI
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003694 *
3695 * Do a complete resolution lookup of an URI using a
3696 * document's private catalog list
3697 *
3698 * Returns the URI of the resource or NULL if not found, it must be freed
3699 * by the caller.
3700 */
3701xmlChar *
3702xmlCatalogLocalResolveURI(void *catalogs, const xmlChar *URI) {
3703 xmlCatalogEntryPtr catal;
Daniel Veillard6990bf32001-08-23 21:17:48 +00003704 xmlChar *ret;
3705
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003706 if (!xmlCatalogInitialized)
3707 xmlInitializeCatalog();
Daniel Veillard6990bf32001-08-23 21:17:48 +00003708
Daniel Veillard81463942001-10-16 12:34:39 +00003709 if (URI == NULL)
3710 return(NULL);
3711
Daniel Veillard6990bf32001-08-23 21:17:48 +00003712 if (xmlDebugCatalogs)
3713 xmlGenericError(xmlGenericErrorContext,
3714 "Resolve URI %s\n", URI);
3715
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003716 catal = (xmlCatalogEntryPtr) catalogs;
3717 if (catal == NULL)
3718 return(NULL);
Daniel Veillard6990bf32001-08-23 21:17:48 +00003719 ret = xmlCatalogListXMLResolveURI(catal, URI);
3720 if ((ret != NULL) && (ret != XML_CATAL_BREAK))
3721 return(ret);
3722 return(NULL);
Daniel Veillarddc2cee22001-08-22 16:30:37 +00003723}
3724
Daniel Veillard75b96822001-10-11 18:59:45 +00003725/************************************************************************
3726 * *
3727 * Deprecated interfaces *
3728 * *
3729 ************************************************************************/
3730/**
3731 * xmlCatalogGetSystem:
Daniel Veillard5aad8322002-12-11 15:59:44 +00003732 * @sysID: the system ID string
Daniel Veillard75b96822001-10-11 18:59:45 +00003733 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003734 * Try to lookup the catalog reference associated to a system ID
Daniel Veillard75b96822001-10-11 18:59:45 +00003735 * DEPRECATED, use xmlCatalogResolveSystem()
3736 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003737 * Returns the resource if found or NULL otherwise.
Daniel Veillard75b96822001-10-11 18:59:45 +00003738 */
3739const xmlChar *
3740xmlCatalogGetSystem(const xmlChar *sysID) {
Daniel Veillardab690c52004-06-14 12:19:09 +00003741 xmlChar *ret;
3742 static xmlChar result[1000];
3743 static int msg = 0;
3744
3745 if (!xmlCatalogInitialized)
3746 xmlInitializeCatalog();
3747
3748 if (msg == 0) {
3749 xmlGenericError(xmlGenericErrorContext,
3750 "Use of deprecated xmlCatalogGetSystem() call\n");
3751 msg++;
3752 }
3753
3754 if (sysID == NULL)
3755 return(NULL);
3756
3757 /*
3758 * Check first the XML catalogs
3759 */
3760 if (xmlDefaultCatalog != NULL) {
3761 ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, NULL, sysID);
3762 if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
3763 snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
3764 result[sizeof(result) - 1] = 0;
3765 return(result);
3766 }
3767 }
3768
3769 if (xmlDefaultCatalog != NULL)
3770 return(xmlCatalogGetSGMLSystem(xmlDefaultCatalog->sgml, sysID));
3771 return(NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00003772}
3773
3774/**
3775 * xmlCatalogGetPublic:
Daniel Veillard5aad8322002-12-11 15:59:44 +00003776 * @pubID: the public ID string
Daniel Veillard75b96822001-10-11 18:59:45 +00003777 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003778 * Try to lookup the catalog reference associated to a public ID
Daniel Veillard75b96822001-10-11 18:59:45 +00003779 * DEPRECATED, use xmlCatalogResolvePublic()
3780 *
Daniel Veillard06d25242004-02-25 13:01:42 +00003781 * Returns the resource if found or NULL otherwise.
Daniel Veillard75b96822001-10-11 18:59:45 +00003782 */
3783const xmlChar *
3784xmlCatalogGetPublic(const xmlChar *pubID) {
Daniel Veillardab690c52004-06-14 12:19:09 +00003785 xmlChar *ret;
3786 static xmlChar result[1000];
3787 static int msg = 0;
3788
3789 if (!xmlCatalogInitialized)
3790 xmlInitializeCatalog();
3791
3792 if (msg == 0) {
3793 xmlGenericError(xmlGenericErrorContext,
3794 "Use of deprecated xmlCatalogGetPublic() call\n");
3795 msg++;
3796 }
3797
3798 if (pubID == NULL)
3799 return(NULL);
3800
3801 /*
3802 * Check first the XML catalogs
3803 */
3804 if (xmlDefaultCatalog != NULL) {
3805 ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, pubID, NULL);
3806 if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
3807 snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
3808 result[sizeof(result) - 1] = 0;
3809 return(result);
3810 }
3811 }
3812
3813 if (xmlDefaultCatalog != NULL)
3814 return(xmlCatalogGetSGMLPublic(xmlDefaultCatalog->sgml, pubID));
3815 return(NULL);
Daniel Veillard75b96822001-10-11 18:59:45 +00003816}
3817
Daniel Veillard5d4644e2005-04-01 13:11:58 +00003818#define bottom_catalog
3819#include "elfgcchack.h"
Daniel Veillarda7374592001-05-10 14:17:55 +00003820#endif /* LIBXML_CATALOG_ENABLED */