2
* catalog.c: set of generic Catalog related routines
4
* Reference: SGML Open Technical Resolution TR9401:1997.
5
* http://www.jclark.com/sp/catalog.htm
7
* XML Catalogs Working Draft 06 August 2001
8
* http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
10
* See Copyright for the status of this software.
12
* Daniel.Veillard@imag.fr
18
#ifdef LIBXML_CATALOG_ENABLED
19
#ifdef HAVE_SYS_TYPES_H
20
#include <sys/types.h>
22
#ifdef HAVE_SYS_STAT_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>
41
#include <libxml/threads.h>
42
#include <libxml/globals.h>
46
#define MAX_DELEGATE 50
47
#define MAX_CATAL_DEPTH 50
50
# define PATH_SEAPARATOR ';'
52
# define PATH_SEAPARATOR ':'
58
* macro to flag unimplemented blocks
59
* 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
66
xmlGenericError(xmlGenericErrorContext, \
67
"Unimplemented block at %s:%d\n", \
70
#define XML_URN_PUBID "urn:publicid:"
71
#define XML_CATAL_BREAK ((xmlChar *) -1)
72
#ifndef XML_XML_DEFAULT_CATALOG
73
#define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog"
75
#ifndef XML_SGML_DEFAULT_CATALOG
76
#define XML_SGML_DEFAULT_CATALOG "file:///etc/sgml/catalog"
79
#if defined(_WIN32) && defined(_MSC_VER)
80
#undef XML_XML_DEFAULT_CATALOG
81
static char XML_XML_DEFAULT_CATALOG[256] = "file:///etc/xml/catalog";
82
#if defined(_WIN32_WCE)
83
/* Windows CE don't have a A variant */
84
#define GetModuleHandleA GetModuleHandle
85
#define GetModuleFileNameA GetModuleFileName
87
#if !defined(_WINDOWS_)
88
void* __stdcall GetModuleHandleA(const char*);
89
unsigned long __stdcall GetModuleFileNameA(void*, char*, unsigned long);
94
static xmlChar *xmlCatalogNormalizePublic(const xmlChar *pubID);
95
static int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename);
97
/************************************************************************
99
* Types, all private *
101
************************************************************************/
104
XML_CATA_REMOVED = -1,
107
XML_CATA_BROKEN_CATALOG,
108
XML_CATA_NEXT_CATALOG,
112
XML_CATA_REWRITE_SYSTEM,
113
XML_CATA_DELEGATE_PUBLIC,
114
XML_CATA_DELEGATE_SYSTEM,
116
XML_CATA_REWRITE_URI,
117
XML_CATA_DELEGATE_URI,
130
} xmlCatalogEntryType;
132
typedef struct _xmlCatalogEntry xmlCatalogEntry;
133
typedef xmlCatalogEntry *xmlCatalogEntryPtr;
134
struct _xmlCatalogEntry {
135
struct _xmlCatalogEntry *next;
136
struct _xmlCatalogEntry *parent;
137
struct _xmlCatalogEntry *children;
138
xmlCatalogEntryType type;
141
xmlChar *URL; /* The expanded URL using the base */
142
xmlCatalogPrefer prefer;
145
struct _xmlCatalogEntry *group;
149
XML_XML_CATALOG_TYPE = 1,
150
XML_SGML_CATALOG_TYPE
153
#define XML_MAX_SGML_CATA_DEPTH 10
155
xmlCatalogType type; /* either XML or SGML */
158
* SGML Catalogs are stored as a simple hash table of catalog entries
159
* Catalog stack to check against overflows when building the
162
char *catalTab[XML_MAX_SGML_CATA_DEPTH]; /* stack of catals */
163
int catalNr; /* Number of current catal streams */
164
int catalMax; /* Max number of catal streams */
165
xmlHashTablePtr sgml;
168
* XML Catalogs are stored as a tree of Catalog entries
170
xmlCatalogPrefer prefer;
171
xmlCatalogEntryPtr xml;
174
/************************************************************************
178
************************************************************************/
181
* Those are preferences
183
static int xmlDebugCatalogs = 0; /* used for debugging */
184
static xmlCatalogAllow xmlCatalogDefaultAllow = XML_CATA_ALLOW_ALL;
185
static xmlCatalogPrefer xmlCatalogDefaultPrefer = XML_CATA_PREFER_PUBLIC;
188
* Hash table containing all the trees of XML catalogs parsed by
191
static xmlHashTablePtr xmlCatalogXMLFiles = NULL;
194
* The default catalog in use by the application
196
static xmlCatalogPtr xmlDefaultCatalog = NULL;
199
* A mutex for modifying the shared global catalog(s)
200
* xmlDefaultCatalog tree.
201
* It also protects xmlCatalogXMLFiles
202
* The core of this readers/writer scheme is in xmlFetchXMLCatalogFile()
204
static xmlRMutexPtr xmlCatalogMutex = NULL;
207
* Whether the catalog support was initialized.
209
static int xmlCatalogInitialized = 0;
211
/************************************************************************
213
* Catalog error handlers *
215
************************************************************************/
218
* xmlCatalogErrMemory:
219
* @extra: extra informations
221
* Handle an out of memory condition
224
xmlCatalogErrMemory(const char *extra)
226
__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_CATALOG,
227
XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0,
228
extra, NULL, NULL, 0, 0,
229
"Memory allocation failed : %s\n", extra);
234
* @catal: the Catalog entry
235
* @node: the context node
236
* @msg: the error message
237
* @extra: extra informations
239
* Handle a catalog error
242
xmlCatalogErr(xmlCatalogEntryPtr catal, xmlNodePtr node, int error,
243
const char *msg, const xmlChar *str1, const xmlChar *str2,
246
__xmlRaiseError(NULL, NULL, NULL, catal, node, XML_FROM_CATALOG,
247
error, XML_ERR_ERROR, NULL, 0,
248
(const char *) str1, (const char *) str2,
249
(const char *) str3, 0, 0,
250
msg, str1, str2, str3);
254
/************************************************************************
256
* Allocation and Freeing *
258
************************************************************************/
261
* xmlNewCatalogEntry:
262
* @type: type of entry
263
* @name: name of the entry
264
* @value: value of the entry
265
* @prefer: the PUBLIC vs. SYSTEM current preference value
266
* @group: for members of a group, the group entry
268
* create a new Catalog entry, this type is shared both by XML and
269
* SGML catalogs, but the acceptable types values differs.
271
* Returns the xmlCatalogEntryPtr or NULL in case of error
273
static xmlCatalogEntryPtr
274
xmlNewCatalogEntry(xmlCatalogEntryType type, const xmlChar *name,
275
const xmlChar *value, const xmlChar *URL, xmlCatalogPrefer prefer,
276
xmlCatalogEntryPtr group) {
277
xmlCatalogEntryPtr ret;
278
xmlChar *normid = NULL;
280
ret = (xmlCatalogEntryPtr) xmlMalloc(sizeof(xmlCatalogEntry));
282
xmlCatalogErrMemory("allocating catalog entry");
287
ret->children = NULL;
289
if (type == XML_CATA_PUBLIC || type == XML_CATA_DELEGATE_PUBLIC) {
290
normid = xmlCatalogNormalizePublic(name);
292
name = (*normid != 0 ? normid : NULL);
295
ret->name = xmlStrdup(name);
301
ret->value = xmlStrdup(value);
307
ret->URL = xmlStrdup(URL);
310
ret->prefer = prefer;
318
xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret);
321
* xmlFreeCatalogEntry:
322
* @ret: a Catalog entry
324
* Free the memory allocated to a Catalog entry
327
xmlFreeCatalogEntry(xmlCatalogEntryPtr ret) {
331
* Entries stored in the file hash must be deallocated
332
* only by the file hash cleaner !
334
if (ret->dealloc == 1)
337
if (xmlDebugCatalogs) {
338
if (ret->name != NULL)
339
xmlGenericError(xmlGenericErrorContext,
340
"Free catalog entry %s\n", ret->name);
341
else if (ret->value != NULL)
342
xmlGenericError(xmlGenericErrorContext,
343
"Free catalog entry %s\n", ret->value);
345
xmlGenericError(xmlGenericErrorContext,
346
"Free catalog entry\n");
349
if (ret->name != NULL)
351
if (ret->value != NULL)
353
if (ret->URL != NULL)
359
* xmlFreeCatalogEntryList:
360
* @ret: a Catalog entry list
362
* Free the memory allocated to a full chained list of Catalog entries
365
xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret) {
366
xmlCatalogEntryPtr next;
368
while (ret != NULL) {
370
xmlFreeCatalogEntry(ret);
376
* xmlFreeCatalogHashEntryList:
377
* @ret: a Catalog entry list
379
* Free the memory allocated to list of Catalog entries from the
383
xmlFreeCatalogHashEntryList(xmlCatalogEntryPtr catal) {
384
xmlCatalogEntryPtr children, next;
389
children = catal->children;
390
while (children != NULL) {
391
next = children->next;
392
children->dealloc = 0;
393
children->children = NULL;
394
xmlFreeCatalogEntry(children);
398
xmlFreeCatalogEntry(catal);
402
* xmlCreateNewCatalog:
403
* @type: type of catalog
404
* @prefer: the PUBLIC vs. SYSTEM current preference value
406
* create a new Catalog, this type is shared both by XML and
407
* SGML catalogs, but the acceptable types values differs.
409
* Returns the xmlCatalogPtr or NULL in case of error
412
xmlCreateNewCatalog(xmlCatalogType type, xmlCatalogPrefer prefer) {
415
ret = (xmlCatalogPtr) xmlMalloc(sizeof(xmlCatalog));
417
xmlCatalogErrMemory("allocating catalog");
420
memset(ret, 0, sizeof(xmlCatalog));
423
ret->catalMax = XML_MAX_SGML_CATA_DEPTH;
424
ret->prefer = prefer;
425
if (ret->type == XML_SGML_CATALOG_TYPE)
426
ret->sgml = xmlHashCreate(10);
434
* Free the memory allocated to a Catalog
437
xmlFreeCatalog(xmlCatalogPtr catal) {
440
if (catal->xml != NULL)
441
xmlFreeCatalogEntryList(catal->xml);
442
if (catal->sgml != NULL)
443
xmlHashFree(catal->sgml,
444
(xmlHashDeallocator) xmlFreeCatalogEntry);
448
/************************************************************************
450
* Serializing Catalogs *
452
************************************************************************/
454
#ifdef LIBXML_OUTPUT_ENABLED
456
* xmlCatalogDumpEntry:
457
* @entry: the catalog entry
460
* Serialize an SGML Catalog entry
463
xmlCatalogDumpEntry(xmlCatalogEntryPtr entry, FILE *out) {
464
if ((entry == NULL) || (out == NULL))
466
switch (entry->type) {
467
case SGML_CATA_ENTITY:
468
fprintf(out, "ENTITY "); break;
469
case SGML_CATA_PENTITY:
470
fprintf(out, "ENTITY %%"); break;
471
case SGML_CATA_DOCTYPE:
472
fprintf(out, "DOCTYPE "); break;
473
case SGML_CATA_LINKTYPE:
474
fprintf(out, "LINKTYPE "); break;
475
case SGML_CATA_NOTATION:
476
fprintf(out, "NOTATION "); break;
477
case SGML_CATA_PUBLIC:
478
fprintf(out, "PUBLIC "); break;
479
case SGML_CATA_SYSTEM:
480
fprintf(out, "SYSTEM "); break;
481
case SGML_CATA_DELEGATE:
482
fprintf(out, "DELEGATE "); break;
484
fprintf(out, "BASE "); break;
485
case SGML_CATA_CATALOG:
486
fprintf(out, "CATALOG "); break;
487
case SGML_CATA_DOCUMENT:
488
fprintf(out, "DOCUMENT "); break;
489
case SGML_CATA_SGMLDECL:
490
fprintf(out, "SGMLDECL "); break;
494
switch (entry->type) {
495
case SGML_CATA_ENTITY:
496
case SGML_CATA_PENTITY:
497
case SGML_CATA_DOCTYPE:
498
case SGML_CATA_LINKTYPE:
499
case SGML_CATA_NOTATION:
500
fprintf(out, "%s", (const char *) entry->name); break;
501
case SGML_CATA_PUBLIC:
502
case SGML_CATA_SYSTEM:
503
case SGML_CATA_SGMLDECL:
504
case SGML_CATA_DOCUMENT:
505
case SGML_CATA_CATALOG:
507
case SGML_CATA_DELEGATE:
508
fprintf(out, "\"%s\"", entry->name); break;
512
switch (entry->type) {
513
case SGML_CATA_ENTITY:
514
case SGML_CATA_PENTITY:
515
case SGML_CATA_DOCTYPE:
516
case SGML_CATA_LINKTYPE:
517
case SGML_CATA_NOTATION:
518
case SGML_CATA_PUBLIC:
519
case SGML_CATA_SYSTEM:
520
case SGML_CATA_DELEGATE:
521
fprintf(out, " \"%s\"", entry->value); break;
529
* xmlDumpXMLCatalogNode:
530
* @catal: top catalog entry
531
* @catalog: pointer to the xml tree
532
* @doc: the containing document
533
* @ns: the current namespace
534
* @cgroup: group node for group members
536
* Serializes a Catalog entry, called by xmlDumpXMLCatalog and recursively
539
static void xmlDumpXMLCatalogNode(xmlCatalogEntryPtr catal, xmlNodePtr catalog,
540
xmlDocPtr doc, xmlNsPtr ns, xmlCatalogEntryPtr cgroup) {
542
xmlCatalogEntryPtr cur;
544
* add all the catalog entries
547
while (cur != NULL) {
548
if (cur->group == cgroup) {
550
case XML_CATA_REMOVED:
552
case XML_CATA_BROKEN_CATALOG:
553
case XML_CATA_CATALOG:
559
case XML_CATA_NEXT_CATALOG:
560
node = xmlNewDocNode(doc, ns, BAD_CAST "nextCatalog", NULL);
561
xmlSetProp(node, BAD_CAST "catalog", cur->value);
562
xmlAddChild(catalog, node);
567
node = xmlNewDocNode(doc, ns, BAD_CAST "group", NULL);
568
xmlSetProp(node, BAD_CAST "id", cur->name);
569
if (cur->value != NULL) {
571
xns = xmlSearchNsByHref(doc, node, XML_XML_NAMESPACE);
573
xmlSetNsProp(node, xns, BAD_CAST "base",
576
switch (cur->prefer) {
577
case XML_CATA_PREFER_NONE:
579
case XML_CATA_PREFER_PUBLIC:
580
xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "public");
582
case XML_CATA_PREFER_SYSTEM:
583
xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "system");
586
xmlDumpXMLCatalogNode(cur->next, node, doc, ns, cur);
587
xmlAddChild(catalog, node);
589
case XML_CATA_PUBLIC:
590
node = xmlNewDocNode(doc, ns, BAD_CAST "public", NULL);
591
xmlSetProp(node, BAD_CAST "publicId", cur->name);
592
xmlSetProp(node, BAD_CAST "uri", cur->value);
593
xmlAddChild(catalog, node);
595
case XML_CATA_SYSTEM:
596
node = xmlNewDocNode(doc, ns, BAD_CAST "system", NULL);
597
xmlSetProp(node, BAD_CAST "systemId", cur->name);
598
xmlSetProp(node, BAD_CAST "uri", cur->value);
599
xmlAddChild(catalog, node);
601
case XML_CATA_REWRITE_SYSTEM:
602
node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteSystem", NULL);
603
xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
604
xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
605
xmlAddChild(catalog, node);
607
case XML_CATA_DELEGATE_PUBLIC:
608
node = xmlNewDocNode(doc, ns, BAD_CAST "delegatePublic", NULL);
609
xmlSetProp(node, BAD_CAST "publicIdStartString", cur->name);
610
xmlSetProp(node, BAD_CAST "catalog", cur->value);
611
xmlAddChild(catalog, node);
613
case XML_CATA_DELEGATE_SYSTEM:
614
node = xmlNewDocNode(doc, ns, BAD_CAST "delegateSystem", NULL);
615
xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
616
xmlSetProp(node, BAD_CAST "catalog", cur->value);
617
xmlAddChild(catalog, node);
620
node = xmlNewDocNode(doc, ns, BAD_CAST "uri", NULL);
621
xmlSetProp(node, BAD_CAST "name", cur->name);
622
xmlSetProp(node, BAD_CAST "uri", cur->value);
623
xmlAddChild(catalog, node);
625
case XML_CATA_REWRITE_URI:
626
node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteURI", NULL);
627
xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
628
xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
629
xmlAddChild(catalog, node);
631
case XML_CATA_DELEGATE_URI:
632
node = xmlNewDocNode(doc, ns, BAD_CAST "delegateURI", NULL);
633
xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
634
xmlSetProp(node, BAD_CAST "catalog", cur->value);
635
xmlAddChild(catalog, node);
637
case SGML_CATA_SYSTEM:
638
case SGML_CATA_PUBLIC:
639
case SGML_CATA_ENTITY:
640
case SGML_CATA_PENTITY:
641
case SGML_CATA_DOCTYPE:
642
case SGML_CATA_LINKTYPE:
643
case SGML_CATA_NOTATION:
644
case SGML_CATA_DELEGATE:
646
case SGML_CATA_CATALOG:
647
case SGML_CATA_DOCUMENT:
648
case SGML_CATA_SGMLDECL:
657
xmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) {
663
xmlOutputBufferPtr buf;
668
doc = xmlNewDoc(NULL);
671
dtd = xmlNewDtd(doc, BAD_CAST "catalog",
672
BAD_CAST "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN",
673
BAD_CAST "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd");
675
xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd);
677
ns = xmlNewNs(NULL, XML_CATALOGS_NAMESPACE, NULL);
682
catalog = xmlNewDocNode(doc, ns, BAD_CAST "catalog", NULL);
683
if (catalog == NULL) {
689
xmlAddChild((xmlNodePtr) doc, catalog);
691
xmlDumpXMLCatalogNode(catal, catalog, doc, ns, NULL);
696
buf = xmlOutputBufferCreateFile(out, NULL);
701
ret = xmlSaveFormatFileTo(buf, doc, NULL, 1);
710
#endif /* LIBXML_OUTPUT_ENABLED */
712
/************************************************************************
714
* Converting SGML Catalogs to XML *
716
************************************************************************/
719
* xmlCatalogConvertEntry:
721
* @catal: pointer to the catalog being converted
723
* Convert one entry from the catalog
726
xmlCatalogConvertEntry(xmlCatalogEntryPtr entry, xmlCatalogPtr catal) {
727
if ((entry == NULL) || (catal == NULL) || (catal->sgml == NULL) ||
728
(catal->xml == NULL))
730
switch (entry->type) {
731
case SGML_CATA_ENTITY:
732
entry->type = XML_CATA_PUBLIC;
734
case SGML_CATA_PENTITY:
735
entry->type = XML_CATA_PUBLIC;
737
case SGML_CATA_DOCTYPE:
738
entry->type = XML_CATA_PUBLIC;
740
case SGML_CATA_LINKTYPE:
741
entry->type = XML_CATA_PUBLIC;
743
case SGML_CATA_NOTATION:
744
entry->type = XML_CATA_PUBLIC;
746
case SGML_CATA_PUBLIC:
747
entry->type = XML_CATA_PUBLIC;
749
case SGML_CATA_SYSTEM:
750
entry->type = XML_CATA_SYSTEM;
752
case SGML_CATA_DELEGATE:
753
entry->type = XML_CATA_DELEGATE_PUBLIC;
755
case SGML_CATA_CATALOG:
756
entry->type = XML_CATA_CATALOG;
759
xmlHashRemoveEntry(catal->sgml, entry->name,
760
(xmlHashDeallocator) xmlFreeCatalogEntry);
764
* Conversion successful, remove from the SGML catalog
765
* and add it to the default XML one
767
xmlHashRemoveEntry(catal->sgml, entry->name, NULL);
768
entry->parent = catal->xml;
770
if (catal->xml->children == NULL)
771
catal->xml->children = entry;
773
xmlCatalogEntryPtr prev;
775
prev = catal->xml->children;
776
while (prev->next != NULL)
783
* xmlConvertSGMLCatalog:
784
* @catal: the catalog
786
* Convert all the SGML catalog entries as XML ones
788
* Returns the number of entries converted if successful, -1 otherwise
791
xmlConvertSGMLCatalog(xmlCatalogPtr catal) {
793
if ((catal == NULL) || (catal->type != XML_SGML_CATALOG_TYPE))
796
if (xmlDebugCatalogs) {
797
xmlGenericError(xmlGenericErrorContext,
798
"Converting SGML catalog to XML\n");
800
xmlHashScan(catal->sgml,
801
(xmlHashScanner) xmlCatalogConvertEntry,
806
/************************************************************************
810
************************************************************************/
813
* xmlCatalogUnWrapURN:
814
* @urn: an "urn:publicid:" to unwrap
816
* Expand the URN into the equivalent Public Identifier
818
* Returns the new identifier or NULL, the string must be deallocated
822
xmlCatalogUnWrapURN(const xmlChar *urn) {
823
xmlChar result[2000];
826
if (xmlStrncmp(urn, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1))
828
urn += sizeof(XML_URN_PUBID) - 1;
831
if (i > sizeof(result) - 4)
836
} else if (*urn == ':') {
840
} else if (*urn == ';') {
844
} else if (*urn == '%') {
845
if ((urn[1] == '2') && (urn[2] == 'B'))
847
else if ((urn[1] == '3') && (urn[2] == 'A'))
849
else if ((urn[1] == '2') && (urn[2] == 'F'))
851
else if ((urn[1] == '3') && (urn[2] == 'B'))
853
else if ((urn[1] == '2') && (urn[2] == '7'))
855
else if ((urn[1] == '3') && (urn[2] == 'F'))
857
else if ((urn[1] == '2') && (urn[2] == '3'))
859
else if ((urn[1] == '2') && (urn[2] == '5'))
874
return(xmlStrdup(result));
878
* xmlParseCatalogFile:
879
* @filename: the filename
881
* parse an XML file and build a tree. It's like xmlParseFile()
882
* except it bypass all catalog lookups.
884
* Returns the resulting document tree or NULL in case of error
888
xmlParseCatalogFile(const char *filename) {
890
xmlParserCtxtPtr ctxt;
891
char *directory = NULL;
892
xmlParserInputPtr inputStream;
893
xmlParserInputBufferPtr buf;
895
ctxt = xmlNewParserCtxt();
897
#ifdef LIBXML_SAX1_ENABLED
898
if (xmlDefaultSAXHandler.error != NULL) {
899
xmlDefaultSAXHandler.error(NULL, "out of memory\n");
905
buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
907
xmlFreeParserCtxt(ctxt);
911
inputStream = xmlNewInputStream(ctxt);
912
if (inputStream == NULL) {
913
xmlFreeParserCtxt(ctxt);
917
inputStream->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
918
inputStream->buf = buf;
919
xmlBufResetInput(buf->buffer, inputStream);
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;
928
ctxt->loadsubset = 0;
932
xmlParseDocument(ctxt);
934
if (ctxt->wellFormed)
938
xmlFreeDoc(ctxt->myDoc);
941
xmlFreeParserCtxt(ctxt);
947
* xmlLoadFileContent:
948
* @filename: a file path
950
* Load a file content into memory.
952
* Returns a pointer to the 0 terminated string or NULL in case of error
955
xmlLoadFileContent(const char *filename)
970
if (filename == NULL)
974
if (stat(filename, &info) < 0)
979
if ((fd = open(filename, O_RDONLY)) < 0)
981
if ((fd = fopen(filename, "rb")) == NULL)
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 */
994
content = (xmlChar*)xmlMallocAtomic(size + 10);
995
if (content == NULL) {
996
xmlCatalogErrMemory("allocating catalog data");
1000
len = read(fd, content, size);
1003
len = fread(content, 1, size, fd);
1016
* xmlCatalogNormalizePublic:
1017
* @pubID: the public ID string
1019
* Normalizes the Public Identifier
1021
* Implements 6.2. Public Identifier Normalization
1022
* from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1024
* Returns the new string or NULL, the string must be deallocated
1028
xmlCatalogNormalizePublic(const xmlChar *pubID)
1040
for (p = pubID;*p != 0 && ok;p++) {
1041
if (!xmlIsBlank_ch(*p))
1043
else if (*p == 0x20 && !white)
1048
if (ok && !white) /* is normalized */
1051
ret = xmlStrdup(pubID);
1054
for (p = pubID;*p != 0;p++) {
1055
if (xmlIsBlank_ch(*p)) {
1070
/************************************************************************
1072
* The XML Catalog parser *
1074
************************************************************************/
1076
static xmlCatalogEntryPtr
1077
xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename);
1079
xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
1080
xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup);
1082
xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1083
const xmlChar *sysID);
1085
xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI);
1089
* xmlGetXMLCatalogEntryType:
1092
* lookup the internal type associated to an XML catalog entry name
1094
* Returns the type associated with that name
1096
static xmlCatalogEntryType
1097
xmlGetXMLCatalogEntryType(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;
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
1130
* @cgroup: the group which includes this node
1132
* Finishes the examination of an XML tree node of a catalog and build
1133
* a Catalog entry from it.
1135
* Returns the new Catalog entry node or NULL in case of error.
1137
static xmlCatalogEntryPtr
1138
xmlParseXMLCatalogOneNode(xmlNodePtr cur, xmlCatalogEntryType type,
1139
const xmlChar *name, const xmlChar *attrName,
1140
const xmlChar *uriAttrName, xmlCatalogPrefer prefer,
1141
xmlCatalogEntryPtr cgroup) {
1144
xmlChar *nameValue = NULL;
1145
xmlChar *base = NULL;
1146
xmlChar *URL = NULL;
1147
xmlCatalogEntryPtr ret = NULL;
1149
if (attrName != NULL) {
1150
nameValue = xmlGetProp(cur, attrName);
1151
if (nameValue == NULL) {
1152
xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
1153
"%s entry lacks '%s'\n", name, attrName, NULL);
1157
uriValue = xmlGetProp(cur, uriAttrName);
1158
if (uriValue == NULL) {
1159
xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
1160
"%s entry lacks '%s'\n", name, uriAttrName, NULL);
1164
if (nameValue != NULL)
1166
if (uriValue != NULL)
1171
base = xmlNodeGetBase(cur->doc, cur);
1172
URL = xmlBuildURI(uriValue, base);
1174
if (xmlDebugCatalogs > 1) {
1175
if (nameValue != NULL)
1176
xmlGenericError(xmlGenericErrorContext,
1177
"Found %s: '%s' '%s'\n", name, nameValue, URL);
1179
xmlGenericError(xmlGenericErrorContext,
1180
"Found %s: '%s'\n", name, URL);
1182
ret = xmlNewCatalogEntry(type, nameValue, uriValue, URL, prefer, cgroup);
1184
xmlCatalogErr(ret, cur, XML_CATALOG_ENTRY_BROKEN,
1185
"%s entry '%s' broken ?: %s\n", name, uriAttrName, uriValue);
1187
if (nameValue != NULL)
1189
if (uriValue != NULL)
1199
* xmlParseXMLCatalogNode:
1200
* @cur: the XML node
1201
* @prefer: the PUBLIC vs. SYSTEM current preference value
1202
* @parent: the parent Catalog entry
1203
* @cgroup: the group which includes this node
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
1210
xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer,
1211
xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup)
1213
xmlChar *base = NULL;
1214
xmlCatalogEntryPtr entry = NULL;
1218
if (xmlStrEqual(cur->name, BAD_CAST "group")) {
1220
xmlCatalogPrefer pref = XML_CATA_PREFER_NONE;
1222
prop = xmlGetProp(cur, BAD_CAST "prefer");
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;
1229
xmlCatalogErr(parent, cur, XML_CATALOG_PREFER_VALUE,
1230
"Invalid value for prefer: '%s'\n",
1236
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);
1240
} else if (xmlStrEqual(cur->name, BAD_CAST "public")) {
1241
entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_PUBLIC,
1242
BAD_CAST "public", BAD_CAST "publicId", BAD_CAST "uri", prefer, cgroup);
1243
} else if (xmlStrEqual(cur->name, BAD_CAST "system")) {
1244
entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_SYSTEM,
1245
BAD_CAST "system", BAD_CAST "systemId", BAD_CAST "uri", prefer, cgroup);
1246
} else if (xmlStrEqual(cur->name, BAD_CAST "rewriteSystem")) {
1247
entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_SYSTEM,
1248
BAD_CAST "rewriteSystem", BAD_CAST "systemIdStartString",
1249
BAD_CAST "rewritePrefix", prefer, cgroup);
1250
} else if (xmlStrEqual(cur->name, BAD_CAST "delegatePublic")) {
1251
entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_PUBLIC,
1252
BAD_CAST "delegatePublic", BAD_CAST "publicIdStartString",
1253
BAD_CAST "catalog", prefer, cgroup);
1254
} else if (xmlStrEqual(cur->name, BAD_CAST "delegateSystem")) {
1255
entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_SYSTEM,
1256
BAD_CAST "delegateSystem", BAD_CAST "systemIdStartString",
1257
BAD_CAST "catalog", prefer, cgroup);
1258
} else if (xmlStrEqual(cur->name, BAD_CAST "uri")) {
1259
entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_URI,
1260
BAD_CAST "uri", BAD_CAST "name",
1261
BAD_CAST "uri", prefer, cgroup);
1262
} else if (xmlStrEqual(cur->name, BAD_CAST "rewriteURI")) {
1263
entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_URI,
1264
BAD_CAST "rewriteURI", BAD_CAST "uriStartString",
1265
BAD_CAST "rewritePrefix", prefer, cgroup);
1266
} else if (xmlStrEqual(cur->name, BAD_CAST "delegateURI")) {
1267
entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_URI,
1268
BAD_CAST "delegateURI", BAD_CAST "uriStartString",
1269
BAD_CAST "catalog", prefer, cgroup);
1270
} else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) {
1271
entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG,
1272
BAD_CAST "nextCatalog", NULL,
1273
BAD_CAST "catalog", prefer, cgroup);
1275
if (entry != NULL) {
1276
if (parent != NULL) {
1277
entry->parent = parent;
1278
if (parent->children == NULL)
1279
parent->children = entry;
1281
xmlCatalogEntryPtr prev;
1283
prev = parent->children;
1284
while (prev->next != NULL)
1289
if (entry->type == XML_CATA_GROUP) {
1291
* Recurse to propagate prefer to the subtree
1292
* (xml:base handling is automated)
1294
xmlParseXMLCatalogNodeList(cur->children, prefer, parent, entry);
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
1306
* @cgroup: the group which includes this list
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.
1313
xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
1314
xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup) {
1315
while (cur != NULL) {
1316
if ((cur->ns != NULL) && (cur->ns->href != NULL) &&
1317
(xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) {
1318
xmlParseXMLCatalogNode(cur, prefer, parent, cgroup);
1322
/* TODO: sort the list according to REWRITE lengths and prefer value */
1326
* xmlParseXMLCatalogFile:
1327
* @prefer: the PUBLIC vs. SYSTEM current preference value
1328
* @filename: the filename for the catalog
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
1333
* Returns the resulting Catalog entries list
1335
static xmlCatalogEntryPtr
1336
xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename) {
1340
xmlCatalogEntryPtr parent = NULL;
1342
if (filename == NULL)
1345
doc = xmlParseCatalogFile((const char *) filename);
1347
if (xmlDebugCatalogs)
1348
xmlGenericError(xmlGenericErrorContext,
1349
"Failed to parse catalog %s\n", filename);
1353
if (xmlDebugCatalogs)
1354
xmlGenericError(xmlGenericErrorContext,
1355
"%d Parsing catalog %s\n", xmlGetThreadId(), filename);
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))) {
1362
parent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
1363
(const xmlChar *)filename, NULL, prefer, NULL);
1364
if (parent == NULL) {
1369
prop = xmlGetProp(cur, BAD_CAST "prefer");
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;
1376
xmlCatalogErr(NULL, cur, XML_CATALOG_PREFER_VALUE,
1377
"Invalid value for prefer: '%s'\n",
1382
cur = cur->children;
1383
xmlParseXMLCatalogNodeList(cur, prefer, parent, NULL);
1385
xmlCatalogErr(NULL, (xmlNodePtr) doc, XML_CATALOG_NOT_CATALOG,
1386
"File %s is not an XML Catalog\n",
1387
filename, NULL, NULL);
1396
* xmlFetchXMLCatalogFile:
1397
* @catal: an existing but incomplete catalog entry
1399
* Fetch and parse the subcatalog referenced by an entry
1401
* Returns 0 in case of success, -1 otherwise
1404
xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) {
1405
xmlCatalogEntryPtr doc;
1409
if (catal->URL == NULL)
1413
* lock the whole catalog for modification
1415
xmlRMutexLock(xmlCatalogMutex);
1416
if (catal->children != NULL) {
1417
/* Okay someone else did it in the meantime */
1418
xmlRMutexUnlock(xmlCatalogMutex);
1422
if (xmlCatalogXMLFiles != NULL) {
1423
doc = (xmlCatalogEntryPtr)
1424
xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
1426
if (xmlDebugCatalogs)
1427
xmlGenericError(xmlGenericErrorContext,
1428
"Found %s in file hash\n", catal->URL);
1430
if (catal->type == XML_CATA_CATALOG)
1431
catal->children = doc->children;
1433
catal->children = doc;
1435
xmlRMutexUnlock(xmlCatalogMutex);
1438
if (xmlDebugCatalogs)
1439
xmlGenericError(xmlGenericErrorContext,
1440
"%s not found in file hash\n", catal->URL);
1444
* Fetch and parse. Note that xmlParseXMLCatalogFile does not
1445
* use the existing catalog, there is no recursion allowed at
1448
doc = xmlParseXMLCatalogFile(catal->prefer, catal->URL);
1450
catal->type = XML_CATA_BROKEN_CATALOG;
1451
xmlRMutexUnlock(xmlCatalogMutex);
1455
if (catal->type == XML_CATA_CATALOG)
1456
catal->children = doc->children;
1458
catal->children = doc;
1462
if (xmlCatalogXMLFiles == NULL)
1463
xmlCatalogXMLFiles = xmlHashCreate(10);
1464
if (xmlCatalogXMLFiles != NULL) {
1465
if (xmlDebugCatalogs)
1466
xmlGenericError(xmlGenericErrorContext,
1467
"%s added to file hash\n", catal->URL);
1468
xmlHashAddEntry(xmlCatalogXMLFiles, catal->URL, doc);
1470
xmlRMutexUnlock(xmlCatalogMutex);
1474
/************************************************************************
1476
* XML Catalog handling *
1478
************************************************************************/
1482
* @catal: top of an XML catalog
1483
* @type: the type of record to add to the catalog
1484
* @orig: the system, public or prefix to match (or NULL)
1485
* @replace: the replacement value for the match
1487
* Add an entry in the XML catalog, it may overwrite existing but
1488
* different entries.
1490
* Returns 0 if successful, -1 otherwise
1493
xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type,
1494
const xmlChar *orig, const xmlChar *replace) {
1495
xmlCatalogEntryPtr cur;
1496
xmlCatalogEntryType typ;
1499
if ((catal == NULL) ||
1500
((catal->type != XML_CATA_CATALOG) &&
1501
(catal->type != XML_CATA_BROKEN_CATALOG)))
1503
if (catal->children == NULL) {
1504
xmlFetchXMLCatalogFile(catal);
1506
if (catal->children == NULL)
1509
typ = xmlGetXMLCatalogEntryType(type);
1510
if (typ == XML_CATA_NONE) {
1511
if (xmlDebugCatalogs)
1512
xmlGenericError(xmlGenericErrorContext,
1513
"Failed to add unknown element %s to catalog\n", type);
1517
cur = catal->children;
1519
* Might be a simple "update in place"
1522
while (cur != NULL) {
1523
if ((orig != NULL) && (cur->type == typ) &&
1524
(xmlStrEqual(orig, cur->name))) {
1525
if (xmlDebugCatalogs)
1526
xmlGenericError(xmlGenericErrorContext,
1527
"Updating element %s to catalog\n", type);
1528
if (cur->value != NULL)
1529
xmlFree(cur->value);
1530
if (cur->URL != NULL)
1532
cur->value = xmlStrdup(replace);
1533
cur->URL = xmlStrdup(replace);
1536
if (cur->next == NULL)
1541
if (xmlDebugCatalogs)
1542
xmlGenericError(xmlGenericErrorContext,
1543
"Adding element %s to catalog\n", type);
1545
catal->children = xmlNewCatalogEntry(typ, orig, replace,
1546
NULL, catal->prefer, NULL);
1548
cur->next = xmlNewCatalogEntry(typ, orig, replace,
1549
NULL, catal->prefer, NULL);
1551
catal->type = XML_CATA_CATALOG;
1552
cur = (xmlCatalogEntryPtr)xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
1554
cur->children = catal->children;
1562
* @catal: top of an XML catalog
1563
* @value: the value to remove from the catalog
1565
* Remove entries in the XML catalog where the value or the URI
1566
* is equal to @value
1568
* Returns the number of entries removed if successful, -1 otherwise
1571
xmlDelXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *value) {
1572
xmlCatalogEntryPtr cur;
1575
if ((catal == NULL) ||
1576
((catal->type != XML_CATA_CATALOG) &&
1577
(catal->type != XML_CATA_BROKEN_CATALOG)))
1581
if (catal->children == NULL) {
1582
xmlFetchXMLCatalogFile(catal);
1588
cur = catal->children;
1589
while (cur != NULL) {
1590
if (((cur->name != NULL) && (xmlStrEqual(value, cur->name))) ||
1591
(xmlStrEqual(value, cur->value))) {
1592
if (xmlDebugCatalogs) {
1593
if (cur->name != NULL)
1594
xmlGenericError(xmlGenericErrorContext,
1595
"Removing element %s from catalog\n", cur->name);
1597
xmlGenericError(xmlGenericErrorContext,
1598
"Removing element %s from catalog\n", cur->value);
1600
cur->type = XML_CATA_REMOVED;
1608
* xmlCatalogXMLResolve:
1609
* @catal: a catalog list
1610
* @pubID: the public ID string
1611
* @sysID: the system ID string
1613
* Do a complete resolution lookup of an External Identifier for a
1614
* list of catalog entries.
1616
* Implements (or tries to) 7.1. External Identifier Resolution
1617
* from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1619
* Returns the URI of the resource or NULL if not found
1622
xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1623
const xmlChar *sysID) {
1624
xmlChar *ret = NULL;
1625
xmlCatalogEntryPtr cur;
1626
int haveDelegate = 0;
1630
* protection against loops
1632
if (catal->depth > MAX_CATAL_DEPTH) {
1633
xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
1634
"Detected recursion in catalog %s\n",
1635
catal->name, NULL, NULL);
1641
* First tries steps 2/ 3/ 4/ if a system ID is provided.
1643
if (sysID != NULL) {
1644
xmlCatalogEntryPtr rewrite = NULL;
1645
int lenrewrite = 0, len;
1648
while (cur != NULL) {
1649
switch (cur->type) {
1650
case XML_CATA_SYSTEM:
1651
if (xmlStrEqual(sysID, cur->name)) {
1652
if (xmlDebugCatalogs)
1653
xmlGenericError(xmlGenericErrorContext,
1654
"Found system match %s, using %s\n",
1655
cur->name, cur->URL);
1657
return(xmlStrdup(cur->URL));
1660
case XML_CATA_REWRITE_SYSTEM:
1661
len = xmlStrlen(cur->name);
1662
if ((len > lenrewrite) &&
1663
(!xmlStrncmp(sysID, cur->name, len))) {
1668
case XML_CATA_DELEGATE_SYSTEM:
1669
if (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))
1672
case XML_CATA_NEXT_CATALOG:
1680
if (rewrite != NULL) {
1681
if (xmlDebugCatalogs)
1682
xmlGenericError(xmlGenericErrorContext,
1683
"Using rewriting rule %s\n", rewrite->name);
1684
ret = xmlStrdup(rewrite->URL);
1686
ret = xmlStrcat(ret, &sysID[lenrewrite]);
1691
const xmlChar *delegates[MAX_DELEGATE];
1695
* Assume the entries have been sorted by decreasing substring
1696
* matches when the list was produced.
1699
while (cur != NULL) {
1700
if ((cur->type == XML_CATA_DELEGATE_SYSTEM) &&
1701
(!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))) {
1702
for (i = 0;i < nbList;i++)
1703
if (xmlStrEqual(cur->URL, delegates[i]))
1709
if (nbList < MAX_DELEGATE)
1710
delegates[nbList++] = cur->URL;
1712
if (cur->children == NULL) {
1713
xmlFetchXMLCatalogFile(cur);
1715
if (cur->children != NULL) {
1716
if (xmlDebugCatalogs)
1717
xmlGenericError(xmlGenericErrorContext,
1718
"Trying system delegate %s\n", cur->URL);
1719
ret = xmlCatalogListXMLResolve(
1720
cur->children, NULL, sysID);
1730
* Apply the cut algorithm explained in 4/
1733
return(XML_CATAL_BREAK);
1737
* Then tries 5/ 6/ if a public ID is provided
1739
if (pubID != NULL) {
1742
while (cur != NULL) {
1743
switch (cur->type) {
1744
case XML_CATA_PUBLIC:
1745
if (xmlStrEqual(pubID, cur->name)) {
1746
if (xmlDebugCatalogs)
1747
xmlGenericError(xmlGenericErrorContext,
1748
"Found public match %s\n", cur->name);
1750
return(xmlStrdup(cur->URL));
1753
case XML_CATA_DELEGATE_PUBLIC:
1754
if (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)) &&
1755
(cur->prefer == XML_CATA_PREFER_PUBLIC))
1758
case XML_CATA_NEXT_CATALOG:
1768
const xmlChar *delegates[MAX_DELEGATE];
1772
* Assume the entries have been sorted by decreasing substring
1773
* matches when the list was produced.
1776
while (cur != NULL) {
1777
if ((cur->type == XML_CATA_DELEGATE_PUBLIC) &&
1778
(cur->prefer == XML_CATA_PREFER_PUBLIC) &&
1779
(!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)))) {
1781
for (i = 0;i < nbList;i++)
1782
if (xmlStrEqual(cur->URL, delegates[i]))
1788
if (nbList < MAX_DELEGATE)
1789
delegates[nbList++] = cur->URL;
1791
if (cur->children == NULL) {
1792
xmlFetchXMLCatalogFile(cur);
1794
if (cur->children != NULL) {
1795
if (xmlDebugCatalogs)
1796
xmlGenericError(xmlGenericErrorContext,
1797
"Trying public delegate %s\n", cur->URL);
1798
ret = xmlCatalogListXMLResolve(
1799
cur->children, pubID, NULL);
1809
* Apply the cut algorithm explained in 4/
1812
return(XML_CATAL_BREAK);
1817
while (cur != NULL) {
1818
if (cur->type == XML_CATA_NEXT_CATALOG) {
1819
if (cur->children == NULL) {
1820
xmlFetchXMLCatalogFile(cur);
1822
if (cur->children != NULL) {
1823
ret = xmlCatalogListXMLResolve(cur->children, pubID, sysID);
1827
} else if (catal->depth > MAX_CATAL_DEPTH) {
1841
* xmlCatalogXMLResolveURI:
1842
* @catal: a catalog list
1844
* @sysID: the system ID string
1846
* Do a complete resolution lookup of an External Identifier for a
1847
* list of catalog entries.
1849
* Implements (or tries to) 7.2.2. URI Resolution
1850
* from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1852
* Returns the URI of the resource or NULL if not found
1855
xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
1856
xmlChar *ret = NULL;
1857
xmlCatalogEntryPtr cur;
1858
int haveDelegate = 0;
1860
xmlCatalogEntryPtr rewrite = NULL;
1861
int lenrewrite = 0, len;
1869
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);
1877
* First tries steps 2/ 3/ 4/ if a system ID is provided.
1881
while (cur != NULL) {
1882
switch (cur->type) {
1884
if (xmlStrEqual(URI, cur->name)) {
1885
if (xmlDebugCatalogs)
1886
xmlGenericError(xmlGenericErrorContext,
1887
"Found URI match %s\n", cur->name);
1888
return(xmlStrdup(cur->URL));
1891
case XML_CATA_REWRITE_URI:
1892
len = xmlStrlen(cur->name);
1893
if ((len > lenrewrite) &&
1894
(!xmlStrncmp(URI, cur->name, len))) {
1899
case XML_CATA_DELEGATE_URI:
1900
if (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))
1903
case XML_CATA_NEXT_CATALOG:
1911
if (rewrite != NULL) {
1912
if (xmlDebugCatalogs)
1913
xmlGenericError(xmlGenericErrorContext,
1914
"Using rewriting rule %s\n", rewrite->name);
1915
ret = xmlStrdup(rewrite->URL);
1917
ret = xmlStrcat(ret, &URI[lenrewrite]);
1921
const xmlChar *delegates[MAX_DELEGATE];
1925
* Assume the entries have been sorted by decreasing substring
1926
* matches when the list was produced.
1929
while (cur != NULL) {
1930
if (((cur->type == XML_CATA_DELEGATE_SYSTEM) ||
1931
(cur->type == XML_CATA_DELEGATE_URI)) &&
1932
(!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))) {
1933
for (i = 0;i < nbList;i++)
1934
if (xmlStrEqual(cur->URL, delegates[i]))
1940
if (nbList < MAX_DELEGATE)
1941
delegates[nbList++] = cur->URL;
1943
if (cur->children == NULL) {
1944
xmlFetchXMLCatalogFile(cur);
1946
if (cur->children != NULL) {
1947
if (xmlDebugCatalogs)
1948
xmlGenericError(xmlGenericErrorContext,
1949
"Trying URI delegate %s\n", cur->URL);
1950
ret = xmlCatalogListXMLResolveURI(
1951
cur->children, URI);
1959
* Apply the cut algorithm explained in 4/
1961
return(XML_CATAL_BREAK);
1965
while (cur != NULL) {
1966
if (cur->type == XML_CATA_NEXT_CATALOG) {
1967
if (cur->children == NULL) {
1968
xmlFetchXMLCatalogFile(cur);
1970
if (cur->children != NULL) {
1971
ret = xmlCatalogListXMLResolveURI(cur->children, URI);
1984
* xmlCatalogListXMLResolve:
1985
* @catal: a catalog list
1986
* @pubID: the public ID string
1987
* @sysID: the system ID string
1989
* Do a complete resolution lookup of an External Identifier for a
1992
* Implements (or tries to) 7.1. External Identifier Resolution
1993
* from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
1995
* Returns the URI of the resource or NULL if not found
1998
xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1999
const xmlChar *sysID) {
2000
xmlChar *ret = NULL;
2001
xmlChar *urnID = NULL;
2006
if ((pubID == NULL) && (sysID == NULL))
2009
normid = xmlCatalogNormalizePublic(pubID);
2011
pubID = (*normid != 0 ? normid : NULL);
2013
if (!xmlStrncmp(pubID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2014
urnID = xmlCatalogUnWrapURN(pubID);
2015
if (xmlDebugCatalogs) {
2017
xmlGenericError(xmlGenericErrorContext,
2018
"Public URN ID %s expanded to NULL\n", pubID);
2020
xmlGenericError(xmlGenericErrorContext,
2021
"Public URN ID expanded to %s\n", urnID);
2023
ret = xmlCatalogListXMLResolve(catal, urnID, sysID);
2030
if (!xmlStrncmp(sysID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2031
urnID = xmlCatalogUnWrapURN(sysID);
2032
if (xmlDebugCatalogs) {
2034
xmlGenericError(xmlGenericErrorContext,
2035
"System URN ID %s expanded to NULL\n", sysID);
2037
xmlGenericError(xmlGenericErrorContext,
2038
"System URN ID expanded to %s\n", urnID);
2041
ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
2042
else if (xmlStrEqual(pubID, urnID))
2043
ret = xmlCatalogListXMLResolve(catal, pubID, NULL);
2045
ret = xmlCatalogListXMLResolve(catal, pubID, urnID);
2053
while (catal != NULL) {
2054
if (catal->type == XML_CATA_CATALOG) {
2055
if (catal->children == NULL) {
2056
xmlFetchXMLCatalogFile(catal);
2058
if (catal->children != NULL) {
2059
ret = xmlCatalogXMLResolve(catal->children, pubID, sysID);
2062
} else if ((catal->children != NULL) &&
2063
(catal->children->depth > MAX_CATAL_DEPTH)) {
2069
catal = catal->next;
2077
* xmlCatalogListXMLResolveURI:
2078
* @catal: a catalog list
2081
* Do a complete resolution lookup of an URI for a list of catalogs
2083
* Implements (or tries to) 7.2. URI Resolution
2084
* from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
2086
* Returns the URI of the resource or NULL if not found
2089
xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
2090
xmlChar *ret = NULL;
2091
xmlChar *urnID = NULL;
2098
if (!xmlStrncmp(URI, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2099
urnID = xmlCatalogUnWrapURN(URI);
2100
if (xmlDebugCatalogs) {
2102
xmlGenericError(xmlGenericErrorContext,
2103
"URN ID %s expanded to NULL\n", URI);
2105
xmlGenericError(xmlGenericErrorContext,
2106
"URN ID expanded to %s\n", urnID);
2108
ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
2113
while (catal != NULL) {
2114
if (catal->type == XML_CATA_CATALOG) {
2115
if (catal->children == NULL) {
2116
xmlFetchXMLCatalogFile(catal);
2118
if (catal->children != NULL) {
2119
ret = xmlCatalogXMLResolveURI(catal->children, URI);
2124
catal = catal->next;
2129
/************************************************************************
2131
* The SGML Catalog parser *
2133
************************************************************************/
2138
#define SKIP(x) cur += x;
2140
#define SKIP_BLANKS while (IS_BLANK_CH(*cur)) NEXT;
2143
* xmlParseSGMLCatalogComment:
2144
* @cur: the current character
2146
* Skip a comment in an SGML catalog
2148
* Returns new current character
2150
static const xmlChar *
2151
xmlParseSGMLCatalogComment(const xmlChar *cur) {
2152
if ((cur[0] != '-') || (cur[1] != '-'))
2155
while ((cur[0] != 0) && ((cur[0] != '-') || ((cur[1] != '-'))))
2164
* xmlParseSGMLCatalogPubid:
2165
* @cur: the current character
2166
* @id: the return location
2168
* Parse an SGML catalog ID
2170
* Returns new current character and store the value in @id
2172
static const xmlChar *
2173
xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) {
2174
xmlChar *buf = NULL, *tmp;
2185
} else if (RAW == '\'') {
2191
buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
2193
xmlCatalogErrMemory("allocating public ID");
2196
while (IS_PUBIDCHAR_CH(*cur) || (*cur == '?')) {
2197
if ((*cur == stop) && (stop != ' '))
2199
if ((stop == ' ') && (IS_BLANK_CH(*cur)))
2201
if (len + 1 >= size) {
2203
tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
2205
xmlCatalogErrMemory("allocating public ID");
2217
if (!IS_BLANK_CH(*cur)) {
2233
* xmlParseSGMLCatalogName:
2234
* @cur: the current character
2235
* @name: the return location
2237
* Parse an SGML catalog name
2239
* Returns new current character and store the value in @name
2241
static const xmlChar *
2242
xmlParseSGMLCatalogName(const xmlChar *cur, xmlChar **name) {
2243
xmlChar buf[XML_MAX_NAMELEN + 5];
2250
* Handler for more complex cases
2253
if ((!IS_LETTER(c) && (c != '_') && (c != ':'))) {
2257
while (((IS_LETTER(c)) || (IS_DIGIT(c)) ||
2258
(c == '.') || (c == '-') ||
2259
(c == '_') || (c == ':'))) {
2263
if (len >= XML_MAX_NAMELEN)
2266
*name = xmlStrndup(buf, len);
2271
* xmlGetSGMLCatalogEntryType:
2272
* @name: the entry name
2274
* Get the Catalog entry type for a given SGML Catalog name
2276
* Returns Catalog entry type
2278
static xmlCatalogEntryType
2279
xmlGetSGMLCatalogEntryType(const xmlChar *name) {
2280
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;
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
2314
* Parse an SGML catalog content and fill up the @catal hash table with
2315
* the new entries found.
2317
* Returns 0 in case of success, -1 in case of error.
2320
xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value,
2321
const char *file, int super) {
2322
const xmlChar *cur = value;
2323
xmlChar *base = NULL;
2326
if ((cur == NULL) || (file == NULL))
2328
base = xmlStrdup((const xmlChar *) file);
2330
while ((cur != NULL) && (cur[0] != 0)) {
2334
if ((cur[0] == '-') && (cur[1] == '-')) {
2335
cur = xmlParseSGMLCatalogComment(cur);
2341
xmlChar *sysid = NULL;
2342
xmlChar *name = NULL;
2343
xmlCatalogEntryType type = XML_CATA_NONE;
2345
cur = xmlParseSGMLCatalogName(cur, &name);
2350
if (!IS_BLANK_CH(*cur)) {
2355
if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
2356
type = SGML_CATA_SYSTEM;
2357
else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
2358
type = SGML_CATA_PUBLIC;
2359
else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
2360
type = SGML_CATA_DELEGATE;
2361
else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
2362
type = SGML_CATA_ENTITY;
2363
else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
2364
type = SGML_CATA_DOCTYPE;
2365
else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
2366
type = SGML_CATA_LINKTYPE;
2367
else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
2368
type = SGML_CATA_NOTATION;
2369
else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
2370
type = SGML_CATA_SGMLDECL;
2371
else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
2372
type = SGML_CATA_DOCUMENT;
2373
else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
2374
type = SGML_CATA_CATALOG;
2375
else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
2376
type = SGML_CATA_BASE;
2377
else if (xmlStrEqual(name, (const xmlChar *) "OVERRIDE")) {
2379
cur = xmlParseSGMLCatalogName(cur, &name);
2391
case SGML_CATA_ENTITY:
2393
type = SGML_CATA_PENTITY;
2394
case SGML_CATA_PENTITY:
2395
case SGML_CATA_DOCTYPE:
2396
case SGML_CATA_LINKTYPE:
2397
case SGML_CATA_NOTATION:
2398
cur = xmlParseSGMLCatalogName(cur, &name);
2403
if (!IS_BLANK_CH(*cur)) {
2408
cur = xmlParseSGMLCatalogPubid(cur, &sysid);
2414
case SGML_CATA_PUBLIC:
2415
case SGML_CATA_SYSTEM:
2416
case SGML_CATA_DELEGATE:
2417
cur = xmlParseSGMLCatalogPubid(cur, &name);
2422
if (type != SGML_CATA_SYSTEM) {
2425
normid = xmlCatalogNormalizePublic(name);
2426
if (normid != NULL) {
2437
if (!IS_BLANK_CH(*cur)) {
2442
cur = xmlParseSGMLCatalogPubid(cur, &sysid);
2448
case SGML_CATA_BASE:
2449
case SGML_CATA_CATALOG:
2450
case SGML_CATA_DOCUMENT:
2451
case SGML_CATA_SGMLDECL:
2452
cur = xmlParseSGMLCatalogPubid(cur, &sysid);
2467
} else if (type == SGML_CATA_BASE) {
2470
base = xmlStrdup(sysid);
2471
} else if ((type == SGML_CATA_PUBLIC) ||
2472
(type == SGML_CATA_SYSTEM)) {
2475
filename = xmlBuildURI(sysid, base);
2476
if (filename != NULL) {
2477
xmlCatalogEntryPtr entry;
2479
entry = xmlNewCatalogEntry(type, name, filename,
2480
NULL, XML_CATA_PREFER_NONE, NULL);
2481
res = xmlHashAddEntry(catal->sgml, name, entry);
2483
xmlFreeCatalogEntry(entry);
2488
} else if (type == SGML_CATA_CATALOG) {
2490
xmlCatalogEntryPtr entry;
2492
entry = xmlNewCatalogEntry(type, sysid, NULL, NULL,
2493
XML_CATA_PREFER_NONE, NULL);
2494
res = xmlHashAddEntry(catal->sgml, sysid, entry);
2496
xmlFreeCatalogEntry(entry);
2501
filename = xmlBuildURI(sysid, base);
2502
if (filename != NULL) {
2503
xmlExpandCatalog(catal, (const char *)filename);
2509
* drop anything else we won't handle it
2524
/************************************************************************
2526
* SGML Catalog handling *
2528
************************************************************************/
2531
* xmlCatalogGetSGMLPublic:
2532
* @catal: an SGML catalog hash
2533
* @pubID: the public ID string
2535
* Try to lookup the catalog local reference associated to a public ID
2537
* Returns the local resource if found or NULL otherwise.
2539
static const xmlChar *
2540
xmlCatalogGetSGMLPublic(xmlHashTablePtr catal, const xmlChar *pubID) {
2541
xmlCatalogEntryPtr entry;
2547
normid = xmlCatalogNormalizePublic(pubID);
2549
pubID = (*normid != 0 ? normid : NULL);
2551
entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, pubID);
2552
if (entry == NULL) {
2557
if (entry->type == SGML_CATA_PUBLIC) {
2568
* xmlCatalogGetSGMLSystem:
2569
* @catal: an SGML catalog hash
2570
* @sysID: the system ID string
2572
* Try to lookup the catalog local reference for a system ID
2574
* Returns the local resource if found or NULL otherwise.
2576
static const xmlChar *
2577
xmlCatalogGetSGMLSystem(xmlHashTablePtr catal, const xmlChar *sysID) {
2578
xmlCatalogEntryPtr entry;
2583
entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, sysID);
2586
if (entry->type == SGML_CATA_SYSTEM)
2592
* xmlCatalogSGMLResolve:
2593
* @catal: the SGML catalog
2594
* @pubID: the public ID string
2595
* @sysID: the system ID string
2597
* Do a complete resolution lookup of an External Identifier
2599
* Returns the URI of the resource or NULL if not found
2601
static const xmlChar *
2602
xmlCatalogSGMLResolve(xmlCatalogPtr catal, const xmlChar *pubID,
2603
const xmlChar *sysID) {
2604
const xmlChar *ret = NULL;
2606
if (catal->sgml == NULL)
2610
ret = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
2614
ret = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
2620
/************************************************************************
2622
* Specific Public interfaces *
2624
************************************************************************/
2627
* xmlLoadSGMLSuperCatalog:
2628
* @filename: a file path
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.
2634
* Returns the catalog parsed or NULL in case of error
2637
xmlLoadSGMLSuperCatalog(const char *filename)
2640
xmlCatalogPtr catal;
2643
content = xmlLoadFileContent(filename);
2644
if (content == NULL)
2647
catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
2648
if (catal == NULL) {
2653
ret = xmlParseSGMLCatalog(catal, content, filename, 1);
2656
xmlFreeCatalog(catal);
2664
* @filename: a file path
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.
2671
* Returns the catalog parsed or NULL in case of error
2674
xmlLoadACatalog(const char *filename)
2678
xmlCatalogPtr catal;
2681
content = xmlLoadFileContent(filename);
2682
if (content == NULL)
2688
while ((*first != 0) && (*first != '-') && (*first != '<') &&
2689
(!(((*first >= 'A') && (*first <= 'Z')) ||
2690
((*first >= 'a') && (*first <= 'z')))))
2693
if (*first != '<') {
2694
catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
2695
if (catal == NULL) {
2699
ret = xmlParseSGMLCatalog(catal, content, filename, 0);
2701
xmlFreeCatalog(catal);
2706
catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
2707
if (catal == NULL) {
2711
catal->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
2712
NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
2721
* @filename: a file path
2723
* Load the catalog and expand the existing catal structure.
2724
* This can be either an XML Catalog or an SGML Catalog
2726
* Returns 0 in case of success, -1 in case of error
2729
xmlExpandCatalog(xmlCatalogPtr catal, const char *filename)
2733
if ((catal == NULL) || (filename == NULL))
2737
if (catal->type == XML_SGML_CATALOG_TYPE) {
2740
content = xmlLoadFileContent(filename);
2741
if (content == NULL)
2744
ret = xmlParseSGMLCatalog(catal, content, filename, 0);
2751
xmlCatalogEntryPtr tmp, cur;
2752
tmp = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
2753
NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
2759
while (cur->next != NULL) cur = cur->next;
2767
* xmlACatalogResolveSystem:
2769
* @sysID: the system ID string
2771
* Try to lookup the catalog resource for a system ID
2773
* Returns the resource if found or NULL otherwise, the value returned
2774
* must be freed by the caller.
2777
xmlACatalogResolveSystem(xmlCatalogPtr catal, const xmlChar *sysID) {
2778
xmlChar *ret = NULL;
2780
if ((sysID == NULL) || (catal == NULL))
2783
if (xmlDebugCatalogs)
2784
xmlGenericError(xmlGenericErrorContext,
2785
"Resolve sysID %s\n", sysID);
2787
if (catal->type == XML_XML_CATALOG_TYPE) {
2788
ret = xmlCatalogListXMLResolve(catal->xml, NULL, sysID);
2789
if (ret == XML_CATAL_BREAK)
2792
const xmlChar *sgml;
2794
sgml = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
2796
ret = xmlStrdup(sgml);
2802
* xmlACatalogResolvePublic:
2804
* @pubID: the public ID string
2806
* Try to lookup the catalog local reference associated to a public ID in that catalog
2808
* Returns the local resource if found or NULL otherwise, the value returned
2809
* must be freed by the caller.
2812
xmlACatalogResolvePublic(xmlCatalogPtr catal, const xmlChar *pubID) {
2813
xmlChar *ret = NULL;
2815
if ((pubID == NULL) || (catal == NULL))
2818
if (xmlDebugCatalogs)
2819
xmlGenericError(xmlGenericErrorContext,
2820
"Resolve pubID %s\n", pubID);
2822
if (catal->type == XML_XML_CATALOG_TYPE) {
2823
ret = xmlCatalogListXMLResolve(catal->xml, pubID, NULL);
2824
if (ret == XML_CATAL_BREAK)
2827
const xmlChar *sgml;
2829
sgml = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
2831
ret = xmlStrdup(sgml);
2837
* xmlACatalogResolve:
2839
* @pubID: the public ID string
2840
* @sysID: the system ID string
2842
* Do a complete resolution lookup of an External Identifier
2844
* Returns the URI of the resource or NULL if not found, it must be freed
2848
xmlACatalogResolve(xmlCatalogPtr catal, const xmlChar * pubID,
2849
const xmlChar * sysID)
2851
xmlChar *ret = NULL;
2853
if (((pubID == NULL) && (sysID == NULL)) || (catal == NULL))
2856
if (xmlDebugCatalogs) {
2857
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);
2864
xmlGenericError(xmlGenericErrorContext,
2865
"Resolve: sysID %s\n", sysID);
2869
if (catal->type == XML_XML_CATALOG_TYPE) {
2870
ret = xmlCatalogListXMLResolve(catal->xml, pubID, sysID);
2871
if (ret == XML_CATAL_BREAK)
2874
const xmlChar *sgml;
2876
sgml = xmlCatalogSGMLResolve(catal, pubID, sysID);
2878
ret = xmlStrdup(sgml);
2884
* xmlACatalogResolveURI:
2888
* Do a complete resolution lookup of an URI
2890
* Returns the URI of the resource or NULL if not found, it must be freed
2894
xmlACatalogResolveURI(xmlCatalogPtr catal, const xmlChar *URI) {
2895
xmlChar *ret = NULL;
2897
if ((URI == NULL) || (catal == NULL))
2900
if (xmlDebugCatalogs)
2901
xmlGenericError(xmlGenericErrorContext,
2902
"Resolve URI %s\n", URI);
2904
if (catal->type == XML_XML_CATALOG_TYPE) {
2905
ret = xmlCatalogListXMLResolveURI(catal->xml, URI);
2906
if (ret == XML_CATAL_BREAK)
2909
const xmlChar *sgml;
2911
sgml = xmlCatalogSGMLResolve(catal, NULL, URI);
2913
ret = xmlStrdup(sgml);
2918
#ifdef LIBXML_OUTPUT_ENABLED
2924
* Dump the given catalog to the given file.
2927
xmlACatalogDump(xmlCatalogPtr catal, FILE *out) {
2928
if ((out == NULL) || (catal == NULL))
2931
if (catal->type == XML_XML_CATALOG_TYPE) {
2932
xmlDumpXMLCatalog(out, catal->xml);
2934
xmlHashScan(catal->sgml,
2935
(xmlHashScanner) xmlCatalogDumpEntry, out);
2938
#endif /* LIBXML_OUTPUT_ENABLED */
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
2947
* Add an entry in the catalog, it may overwrite existing but
2948
* different entries.
2950
* Returns 0 if successful, -1 otherwise
2953
xmlACatalogAdd(xmlCatalogPtr catal, const xmlChar * type,
2954
const xmlChar * orig, const xmlChar * replace)
2961
if (catal->type == XML_XML_CATALOG_TYPE) {
2962
res = xmlAddXMLCatalog(catal->xml, type, orig, replace);
2964
xmlCatalogEntryType cattype;
2966
cattype = xmlGetSGMLCatalogEntryType(type);
2967
if (cattype != XML_CATA_NONE) {
2968
xmlCatalogEntryPtr entry;
2970
entry = xmlNewCatalogEntry(cattype, orig, replace, NULL,
2971
XML_CATA_PREFER_NONE, NULL);
2972
if (catal->sgml == NULL)
2973
catal->sgml = xmlHashCreate(10);
2974
res = xmlHashAddEntry(catal->sgml, orig, entry);
2981
* xmlACatalogRemove:
2983
* @value: the value to remove
2985
* Remove an entry from the catalog
2987
* Returns the number of entries removed if successful, -1 otherwise
2990
xmlACatalogRemove(xmlCatalogPtr catal, const xmlChar *value) {
2993
if ((catal == NULL) || (value == NULL))
2996
if (catal->type == XML_XML_CATALOG_TYPE) {
2997
res = xmlDelXMLCatalog(catal->xml, value);
2999
res = xmlHashRemoveEntry(catal->sgml, value,
3000
(xmlHashDeallocator) xmlFreeCatalogEntry);
3009
* @sgml: should this create an SGML catalog
3011
* create a new Catalog.
3013
* Returns the xmlCatalogPtr or NULL in case of error
3016
xmlNewCatalog(int sgml) {
3017
xmlCatalogPtr catal = NULL;
3020
catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE,
3021
xmlCatalogDefaultPrefer);
3022
if ((catal != NULL) && (catal->sgml == NULL))
3023
catal->sgml = xmlHashCreate(10);
3025
catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3026
xmlCatalogDefaultPrefer);
3031
* xmlCatalogIsEmpty:
3032
* @catal: should this create an SGML catalog
3034
* Check is a catalog is empty
3036
* Returns 1 if the catalog is empty, 0 if not, amd -1 in case of error.
3039
xmlCatalogIsEmpty(xmlCatalogPtr catal) {
3043
if (catal->type == XML_XML_CATALOG_TYPE) {
3044
if (catal->xml == NULL)
3046
if ((catal->xml->type != XML_CATA_CATALOG) &&
3047
(catal->xml->type != XML_CATA_BROKEN_CATALOG))
3049
if (catal->xml->children == NULL)
3055
if (catal->sgml == NULL)
3057
res = xmlHashSize(catal->sgml);
3066
/************************************************************************
3068
* Public interfaces manipulating the global shared default catalog *
3070
************************************************************************/
3073
* xmlInitializeCatalogData:
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
3081
xmlInitializeCatalogData(void) {
3082
if (xmlCatalogInitialized != 0)
3085
if (getenv("XML_DEBUG_CATALOG"))
3086
xmlDebugCatalogs = 1;
3087
xmlCatalogMutex = xmlNewRMutex();
3089
xmlCatalogInitialized = 1;
3092
* xmlInitializeCatalog:
3094
* Do the catalog initialization.
3095
* this function is not thread safe, catalog initialization should
3096
* preferably be done once at startup
3099
xmlInitializeCatalog(void) {
3100
if (xmlCatalogInitialized != 0)
3103
xmlInitializeCatalogData();
3104
xmlRMutexLock(xmlCatalogMutex);
3106
if (getenv("XML_DEBUG_CATALOG"))
3107
xmlDebugCatalogs = 1;
3109
if (xmlDefaultCatalog == NULL) {
3110
const char *catalogs;
3112
const char *cur, *paths;
3113
xmlCatalogPtr catal;
3114
xmlCatalogEntryPtr *nextent;
3116
catalogs = (const char *) getenv("XML_CATALOG_FILES");
3117
if (catalogs == NULL)
3118
#if defined(_WIN32) && defined(_MSC_VER)
3121
hmodule = GetModuleHandleA("libxml2.dll");
3122
if (hmodule == NULL)
3123
hmodule = GetModuleHandleA(NULL);
3124
if (hmodule != NULL) {
3126
unsigned long len = GetModuleFileNameA(hmodule, buf, 255);
3128
char* p = &(buf[len]);
3129
while (*p != '\\' && p > buf)
3133
strncpy(p, "\\..\\etc\\catalog", 255 - (p - buf));
3134
uri = xmlCanonicPath((const xmlChar*)buf);
3136
strncpy(XML_XML_DEFAULT_CATALOG, uri, 255);
3142
catalogs = XML_XML_DEFAULT_CATALOG;
3145
catalogs = XML_XML_DEFAULT_CATALOG;
3148
catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3149
xmlCatalogDefaultPrefer);
3150
if (catal != NULL) {
3151
/* the XML_CATALOG_FILES envvar is allowed to contain a
3152
space-separated list of entries. */
3154
nextent = &catal->xml;
3155
while (*cur != '\0') {
3156
while (xmlIsBlank_ch(*cur))
3160
while ((*cur != 0) && (!xmlIsBlank_ch(*cur)))
3162
path = (char *) xmlStrndup((const xmlChar *)paths, cur - paths);
3164
*nextent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
3165
NULL, BAD_CAST path, xmlCatalogDefaultPrefer, NULL);
3166
if (*nextent != NULL)
3167
nextent = &((*nextent)->next);
3172
xmlDefaultCatalog = catal;
3176
xmlRMutexUnlock(xmlCatalogMutex);
3182
* @filename: a file path
3184
* Load the catalog and makes its definitions effective for the default
3185
* external entity loader. It will recurse in SGML CATALOG entries.
3186
* this function is not thread safe, catalog initialization should
3187
* preferably be done once at startup
3189
* Returns 0 in case of success -1 in case of error
3192
xmlLoadCatalog(const char *filename)
3195
xmlCatalogPtr catal;
3197
if (!xmlCatalogInitialized)
3198
xmlInitializeCatalogData();
3200
xmlRMutexLock(xmlCatalogMutex);
3202
if (xmlDefaultCatalog == NULL) {
3203
catal = xmlLoadACatalog(filename);
3204
if (catal == NULL) {
3205
xmlRMutexUnlock(xmlCatalogMutex);
3209
xmlDefaultCatalog = catal;
3210
xmlRMutexUnlock(xmlCatalogMutex);
3214
ret = xmlExpandCatalog(xmlDefaultCatalog, filename);
3215
xmlRMutexUnlock(xmlCatalogMutex);
3221
* @pathss: a list of directories separated by a colon or a space.
3223
* Load the catalogs and makes their definitions effective for the default
3224
* external entity loader.
3225
* this function is not thread safe, catalog initialization should
3226
* preferably be done once at startup
3229
xmlLoadCatalogs(const char *pathss) {
3242
while (xmlIsBlank_ch(*cur)) cur++;
3245
while ((*cur != 0) && (*cur != PATH_SEAPARATOR) && (!xmlIsBlank_ch(*cur)))
3247
path = xmlStrndup((const xmlChar *)paths, cur - paths);
3249
iLen = strlen((const char*)path);
3250
for(i = 0; i < iLen; i++) {
3251
if(path[i] == '\\') {
3257
xmlLoadCatalog((const char *) path);
3261
while (*cur == PATH_SEAPARATOR)
3267
* xmlCatalogCleanup:
3269
* Free up all the memory associated with catalogs
3272
xmlCatalogCleanup(void) {
3273
if (xmlCatalogInitialized == 0)
3276
xmlRMutexLock(xmlCatalogMutex);
3277
if (xmlDebugCatalogs)
3278
xmlGenericError(xmlGenericErrorContext,
3279
"Catalogs cleanup\n");
3280
if (xmlCatalogXMLFiles != NULL)
3281
xmlHashFree(xmlCatalogXMLFiles,
3282
(xmlHashDeallocator)xmlFreeCatalogHashEntryList);
3283
xmlCatalogXMLFiles = NULL;
3284
if (xmlDefaultCatalog != NULL)
3285
xmlFreeCatalog(xmlDefaultCatalog);
3286
xmlDefaultCatalog = NULL;
3287
xmlDebugCatalogs = 0;
3288
xmlCatalogInitialized = 0;
3289
xmlRMutexUnlock(xmlCatalogMutex);
3290
xmlFreeRMutex(xmlCatalogMutex);
3294
* xmlCatalogResolveSystem:
3295
* @sysID: the system ID string
3297
* Try to lookup the catalog resource for a system ID
3299
* Returns the resource if found or NULL otherwise, the value returned
3300
* must be freed by the caller.
3303
xmlCatalogResolveSystem(const xmlChar *sysID) {
3306
if (!xmlCatalogInitialized)
3307
xmlInitializeCatalog();
3309
ret = xmlACatalogResolveSystem(xmlDefaultCatalog, sysID);
3314
* xmlCatalogResolvePublic:
3315
* @pubID: the public ID string
3317
* Try to lookup the catalog reference associated to a public ID
3319
* Returns the resource if found or NULL otherwise, the value returned
3320
* must be freed by the caller.
3323
xmlCatalogResolvePublic(const xmlChar *pubID) {
3326
if (!xmlCatalogInitialized)
3327
xmlInitializeCatalog();
3329
ret = xmlACatalogResolvePublic(xmlDefaultCatalog, pubID);
3334
* xmlCatalogResolve:
3335
* @pubID: the public ID string
3336
* @sysID: the system ID string
3338
* Do a complete resolution lookup of an External Identifier
3340
* Returns the URI of the resource or NULL if not found, it must be freed
3344
xmlCatalogResolve(const xmlChar *pubID, const xmlChar *sysID) {
3347
if (!xmlCatalogInitialized)
3348
xmlInitializeCatalog();
3350
ret = xmlACatalogResolve(xmlDefaultCatalog, pubID, sysID);
3355
* xmlCatalogResolveURI:
3358
* Do a complete resolution lookup of an URI
3360
* Returns the URI of the resource or NULL if not found, it must be freed
3364
xmlCatalogResolveURI(const xmlChar *URI) {
3367
if (!xmlCatalogInitialized)
3368
xmlInitializeCatalog();
3370
ret = xmlACatalogResolveURI(xmlDefaultCatalog, URI);
3374
#ifdef LIBXML_OUTPUT_ENABLED
3379
* Dump all the global catalog content to the given file.
3382
xmlCatalogDump(FILE *out) {
3386
if (!xmlCatalogInitialized)
3387
xmlInitializeCatalog();
3389
xmlACatalogDump(xmlDefaultCatalog, out);
3391
#endif /* LIBXML_OUTPUT_ENABLED */
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
3399
* Add an entry in the catalog, it may overwrite existing but
3400
* different entries.
3401
* If called before any other catalog routine, allows to override the
3402
* default shared catalog put in place by xmlInitializeCatalog();
3404
* Returns 0 if successful, -1 otherwise
3407
xmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace) {
3410
if (!xmlCatalogInitialized)
3411
xmlInitializeCatalogData();
3413
xmlRMutexLock(xmlCatalogMutex);
3415
* Specific case where one want to override the default catalog
3416
* put in place by xmlInitializeCatalog();
3418
if ((xmlDefaultCatalog == NULL) &&
3419
(xmlStrEqual(type, BAD_CAST "catalog"))) {
3420
xmlDefaultCatalog = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3421
xmlCatalogDefaultPrefer);
3422
xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
3423
orig, NULL, xmlCatalogDefaultPrefer, NULL);
3425
xmlRMutexUnlock(xmlCatalogMutex);
3429
res = xmlACatalogAdd(xmlDefaultCatalog, type, orig, replace);
3430
xmlRMutexUnlock(xmlCatalogMutex);
3436
* @value: the value to remove
3438
* Remove an entry from the catalog
3440
* Returns the number of entries removed if successful, -1 otherwise
3443
xmlCatalogRemove(const xmlChar *value) {
3446
if (!xmlCatalogInitialized)
3447
xmlInitializeCatalog();
3449
xmlRMutexLock(xmlCatalogMutex);
3450
res = xmlACatalogRemove(xmlDefaultCatalog, value);
3451
xmlRMutexUnlock(xmlCatalogMutex);
3456
* xmlCatalogConvert:
3458
* Convert all the SGML catalog entries as XML ones
3460
* Returns the number of entries converted if successful, -1 otherwise
3463
xmlCatalogConvert(void) {
3466
if (!xmlCatalogInitialized)
3467
xmlInitializeCatalog();
3469
xmlRMutexLock(xmlCatalogMutex);
3470
res = xmlConvertSGMLCatalog(xmlDefaultCatalog);
3471
xmlRMutexUnlock(xmlCatalogMutex);
3475
/************************************************************************
3477
* Public interface manipulating the common preferences *
3479
************************************************************************/
3482
* xmlCatalogGetDefaults:
3484
* Used to get the user preference w.r.t. to what catalogs should
3487
* Returns the current xmlCatalogAllow value
3490
xmlCatalogGetDefaults(void) {
3491
return(xmlCatalogDefaultAllow);
3495
* xmlCatalogSetDefaults:
3496
* @allow: what catalogs should be accepted
3498
* Used to set the user preference w.r.t. to what catalogs should
3502
xmlCatalogSetDefaults(xmlCatalogAllow allow) {
3503
if (xmlDebugCatalogs) {
3505
case XML_CATA_ALLOW_NONE:
3506
xmlGenericError(xmlGenericErrorContext,
3507
"Disabling catalog usage\n");
3509
case XML_CATA_ALLOW_GLOBAL:
3510
xmlGenericError(xmlGenericErrorContext,
3511
"Allowing only global catalogs\n");
3513
case XML_CATA_ALLOW_DOCUMENT:
3514
xmlGenericError(xmlGenericErrorContext,
3515
"Allowing only catalogs from the document\n");
3517
case XML_CATA_ALLOW_ALL:
3518
xmlGenericError(xmlGenericErrorContext,
3519
"Allowing all catalogs\n");
3523
xmlCatalogDefaultAllow = allow;
3527
* xmlCatalogSetDefaultPrefer:
3528
* @prefer: the default preference for delegation
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
3532
* Values accepted are XML_CATA_PREFER_PUBLIC or XML_CATA_PREFER_SYSTEM
3534
* Returns the previous value of the default preference for delegation
3537
xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer) {
3538
xmlCatalogPrefer ret = xmlCatalogDefaultPrefer;
3540
if (prefer == XML_CATA_PREFER_NONE)
3543
if (xmlDebugCatalogs) {
3545
case XML_CATA_PREFER_PUBLIC:
3546
xmlGenericError(xmlGenericErrorContext,
3547
"Setting catalog preference to PUBLIC\n");
3549
case XML_CATA_PREFER_SYSTEM:
3550
xmlGenericError(xmlGenericErrorContext,
3551
"Setting catalog preference to SYSTEM\n");
3553
case XML_CATA_PREFER_NONE:
3557
xmlCatalogDefaultPrefer = prefer;
3562
* xmlCatalogSetDebug:
3563
* @level: the debug level of catalogs required
3565
* Used to set the debug level for catalog operation, 0 disable
3566
* debugging, 1 enable it
3568
* Returns the previous value of the catalog debugging level
3571
xmlCatalogSetDebug(int level) {
3572
int ret = xmlDebugCatalogs;
3575
xmlDebugCatalogs = 0;
3577
xmlDebugCatalogs = level;
3581
/************************************************************************
3583
* Minimal interfaces used for per-document catalogs by the parser *
3585
************************************************************************/
3588
* xmlCatalogFreeLocal:
3589
* @catalogs: a document's list of catalogs
3591
* Free up the memory associated to the catalog list
3594
xmlCatalogFreeLocal(void *catalogs) {
3595
xmlCatalogEntryPtr catal;
3597
if (!xmlCatalogInitialized)
3598
xmlInitializeCatalog();
3600
catal = (xmlCatalogEntryPtr) catalogs;
3602
xmlFreeCatalogEntryList(catal);
3607
* xmlCatalogAddLocal:
3608
* @catalogs: a document's list of catalogs
3609
* @URL: the URL to a new local catalog
3611
* Add the new entry to the catalog list
3613
* Returns the updated list
3616
xmlCatalogAddLocal(void *catalogs, const xmlChar *URL) {
3617
xmlCatalogEntryPtr catal, add;
3619
if (!xmlCatalogInitialized)
3620
xmlInitializeCatalog();
3625
if (xmlDebugCatalogs)
3626
xmlGenericError(xmlGenericErrorContext,
3627
"Adding document catalog %s\n", URL);
3629
add = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, URL, NULL,
3630
xmlCatalogDefaultPrefer, NULL);
3634
catal = (xmlCatalogEntryPtr) catalogs;
3636
return((void *) add);
3638
while (catal->next != NULL)
3639
catal = catal->next;
3645
* xmlCatalogLocalResolve:
3646
* @catalogs: a document's list of catalogs
3647
* @pubID: the public ID string
3648
* @sysID: the system ID string
3650
* Do a complete resolution lookup of an External Identifier using a
3651
* document's private catalog list
3653
* Returns the URI of the resource or NULL if not found, it must be freed
3657
xmlCatalogLocalResolve(void *catalogs, const xmlChar *pubID,
3658
const xmlChar *sysID) {
3659
xmlCatalogEntryPtr catal;
3662
if (!xmlCatalogInitialized)
3663
xmlInitializeCatalog();
3665
if ((pubID == NULL) && (sysID == NULL))
3668
if (xmlDebugCatalogs) {
3669
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);
3676
xmlGenericError(xmlGenericErrorContext,
3677
"Local Resolve: sysID %s\n", sysID);
3681
catal = (xmlCatalogEntryPtr) catalogs;
3684
ret = xmlCatalogListXMLResolve(catal, pubID, sysID);
3685
if ((ret != NULL) && (ret != XML_CATAL_BREAK))
3691
* xmlCatalogLocalResolveURI:
3692
* @catalogs: a document's list of catalogs
3695
* Do a complete resolution lookup of an URI using a
3696
* document's private catalog list
3698
* Returns the URI of the resource or NULL if not found, it must be freed
3702
xmlCatalogLocalResolveURI(void *catalogs, const xmlChar *URI) {
3703
xmlCatalogEntryPtr catal;
3706
if (!xmlCatalogInitialized)
3707
xmlInitializeCatalog();
3712
if (xmlDebugCatalogs)
3713
xmlGenericError(xmlGenericErrorContext,
3714
"Resolve URI %s\n", URI);
3716
catal = (xmlCatalogEntryPtr) catalogs;
3719
ret = xmlCatalogListXMLResolveURI(catal, URI);
3720
if ((ret != NULL) && (ret != XML_CATAL_BREAK))
3725
/************************************************************************
3727
* Deprecated interfaces *
3729
************************************************************************/
3731
* xmlCatalogGetSystem:
3732
* @sysID: the system ID string
3734
* Try to lookup the catalog reference associated to a system ID
3735
* DEPRECATED, use xmlCatalogResolveSystem()
3737
* Returns the resource if found or NULL otherwise.
3740
xmlCatalogGetSystem(const xmlChar *sysID) {
3742
static xmlChar result[1000];
3745
if (!xmlCatalogInitialized)
3746
xmlInitializeCatalog();
3749
xmlGenericError(xmlGenericErrorContext,
3750
"Use of deprecated xmlCatalogGetSystem() call\n");
3758
* Check first the XML catalogs
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;
3769
if (xmlDefaultCatalog != NULL)
3770
return(xmlCatalogGetSGMLSystem(xmlDefaultCatalog->sgml, sysID));
3775
* xmlCatalogGetPublic:
3776
* @pubID: the public ID string
3778
* Try to lookup the catalog reference associated to a public ID
3779
* DEPRECATED, use xmlCatalogResolvePublic()
3781
* Returns the resource if found or NULL otherwise.
3784
xmlCatalogGetPublic(const xmlChar *pubID) {
3786
static xmlChar result[1000];
3789
if (!xmlCatalogInitialized)
3790
xmlInitializeCatalog();
3793
xmlGenericError(xmlGenericErrorContext,
3794
"Use of deprecated xmlCatalogGetPublic() call\n");
3802
* Check first the XML catalogs
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;
3813
if (xmlDefaultCatalog != NULL)
3814
return(xmlCatalogGetSGMLPublic(xmlDefaultCatalog->sgml, pubID));
3818
#define bottom_catalog
3819
#include "elfgcchack.h"
3820
#endif /* LIBXML_CATALOG_ENABLED */