ReactOS 0.4.16-dev-2232-gc2aaa52
catalog.c
Go to the documentation of this file.
1
15#define IN_LIBXML
16#include "libxml.h"
17
18#ifdef LIBXML_CATALOG_ENABLED
19#include <stdlib.h>
20#include <string.h>
21#ifdef HAVE_SYS_STAT_H
22#include <sys/stat.h>
23#endif
24#ifdef HAVE_UNISTD_H
25#include <unistd.h>
26#elif defined (_WIN32)
27#include <io.h>
28#endif
29#ifdef HAVE_FCNTL_H
30#include <fcntl.h>
31#endif
32#include <libxml/xmlmemory.h>
33#include <libxml/hash.h>
34#include <libxml/uri.h>
36#include <libxml/catalog.h>
37#include <libxml/xmlerror.h>
38#include <libxml/threads.h>
39
40#include "private/buf.h"
41#include "private/error.h"
42
43#define MAX_DELEGATE 50
44#define MAX_CATAL_DEPTH 50
45
46#ifdef _WIN32
47# define PATH_SEPARATOR ';'
48#else
49# define PATH_SEPARATOR ':'
50#endif
51
62#define TODO \
63 xmlGenericError(xmlGenericErrorContext, \
64 "Unimplemented block at %s:%d\n", \
65 __FILE__, __LINE__);
66
67#define XML_URN_PUBID "urn:publicid:"
68#define XML_CATAL_BREAK ((xmlChar *) -1)
69#ifndef XML_XML_DEFAULT_CATALOG
70#define XML_XML_DEFAULT_CATALOG "file://" SYSCONFDIR "/xml/catalog"
71#endif
72#ifndef XML_SGML_DEFAULT_CATALOG
73#define XML_SGML_DEFAULT_CATALOG "file://" SYSCONFDIR "/sgml/catalog"
74#endif
75
76#if defined(_WIN32) && defined(_MSC_VER)
77#undef XML_XML_DEFAULT_CATALOG
78static char XML_XML_DEFAULT_CATALOG[256] = "file://" SYSCONFDIR "/xml/catalog";
79#if !defined(_WINDOWS_)
80void* __stdcall GetModuleHandleA(const char*);
81unsigned long __stdcall GetModuleFileNameA(void*, char*, unsigned long);
82#endif
83#endif
84
85static xmlChar *xmlCatalogNormalizePublic(const xmlChar *pubID);
86static int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename);
87
88/************************************************************************
89 * *
90 * Types, all private *
91 * *
92 ************************************************************************/
93
94typedef enum {
95 XML_CATA_REMOVED = -1,
96 XML_CATA_NONE = 0,
97 XML_CATA_CATALOG,
98 XML_CATA_BROKEN_CATALOG,
99 XML_CATA_NEXT_CATALOG,
100 XML_CATA_GROUP,
101 XML_CATA_PUBLIC,
102 XML_CATA_SYSTEM,
103 XML_CATA_REWRITE_SYSTEM,
104 XML_CATA_DELEGATE_PUBLIC,
105 XML_CATA_DELEGATE_SYSTEM,
106 XML_CATA_URI,
107 XML_CATA_REWRITE_URI,
108 XML_CATA_DELEGATE_URI,
109 SGML_CATA_SYSTEM,
110 SGML_CATA_PUBLIC,
111 SGML_CATA_ENTITY,
112 SGML_CATA_PENTITY,
113 SGML_CATA_DOCTYPE,
114 SGML_CATA_LINKTYPE,
115 SGML_CATA_NOTATION,
116 SGML_CATA_DELEGATE,
117 SGML_CATA_BASE,
118 SGML_CATA_CATALOG,
119 SGML_CATA_DOCUMENT,
120 SGML_CATA_SGMLDECL
121} xmlCatalogEntryType;
122
123typedef struct _xmlCatalogEntry xmlCatalogEntry;
124typedef xmlCatalogEntry *xmlCatalogEntryPtr;
125struct _xmlCatalogEntry {
126 struct _xmlCatalogEntry *next;
127 struct _xmlCatalogEntry *parent;
128 struct _xmlCatalogEntry *children;
129 xmlCatalogEntryType type;
130 xmlChar *name;
131 xmlChar *value;
132 xmlChar *URL; /* The expanded URL using the base */
133 xmlCatalogPrefer prefer;
134 int dealloc;
135 int depth;
136 struct _xmlCatalogEntry *group;
137};
138
139typedef enum {
140 XML_XML_CATALOG_TYPE = 1,
141 XML_SGML_CATALOG_TYPE
142} xmlCatalogType;
143
144#define XML_MAX_SGML_CATA_DEPTH 10
145struct _xmlCatalog {
146 xmlCatalogType type; /* either XML or SGML */
147
148 /*
149 * SGML Catalogs are stored as a simple hash table of catalog entries
150 * Catalog stack to check against overflows when building the
151 * SGML catalog
152 */
153 char *catalTab[XML_MAX_SGML_CATA_DEPTH]; /* stack of catals */
154 int catalNr; /* Number of current catal streams */
155 int catalMax; /* Max number of catal streams */
156 xmlHashTablePtr sgml;
157
158 /*
159 * XML Catalogs are stored as a tree of Catalog entries
160 */
161 xmlCatalogPrefer prefer;
162 xmlCatalogEntryPtr xml;
163};
164
165/************************************************************************
166 * *
167 * Global variables *
168 * *
169 ************************************************************************/
170
171/*
172 * Those are preferences
173 */
174static int xmlDebugCatalogs = 0; /* used for debugging */
175static xmlCatalogAllow xmlCatalogDefaultAllow = XML_CATA_ALLOW_ALL;
176static xmlCatalogPrefer xmlCatalogDefaultPrefer = XML_CATA_PREFER_PUBLIC;
177
178/*
179 * Hash table containing all the trees of XML catalogs parsed by
180 * the application.
181 */
182static xmlHashTablePtr xmlCatalogXMLFiles = NULL;
183
184/*
185 * The default catalog in use by the application
186 */
187static xmlCatalogPtr xmlDefaultCatalog = NULL;
188
189/*
190 * A mutex for modifying the shared global catalog(s)
191 * xmlDefaultCatalog tree.
192 * It also protects xmlCatalogXMLFiles
193 * The core of this readers/writer scheme is in xmlFetchXMLCatalogFile()
194 */
195static xmlRMutexPtr xmlCatalogMutex = NULL;
196
197/*
198 * Whether the catalog support was initialized.
199 */
200static int xmlCatalogInitialized = 0;
201
202/************************************************************************
203 * *
204 * Catalog error handlers *
205 * *
206 ************************************************************************/
207
214static void
215xmlCatalogErrMemory(const char *extra)
216{
219 extra, NULL, NULL, 0, 0,
220 "Memory allocation failed : %s\n", extra);
221}
222
232static void LIBXML_ATTR_FORMAT(4,0)
233xmlCatalogErr(xmlCatalogEntryPtr catal, xmlNodePtr node, int error,
235 const xmlChar *str3)
236{
239 (const char *) str1, (const char *) str2,
240 (const char *) str3, 0, 0,
241 msg, str1, str2, str3);
242}
243
244
245/************************************************************************
246 * *
247 * Allocation and Freeing *
248 * *
249 ************************************************************************/
250
264static xmlCatalogEntryPtr
265xmlNewCatalogEntry(xmlCatalogEntryType type, const xmlChar *name,
266 const xmlChar *value, const xmlChar *URL, xmlCatalogPrefer prefer,
267 xmlCatalogEntryPtr group) {
268 xmlCatalogEntryPtr ret;
269 xmlChar *normid = NULL;
270
271 ret = (xmlCatalogEntryPtr) xmlMalloc(sizeof(xmlCatalogEntry));
272 if (ret == NULL) {
273 xmlCatalogErrMemory("allocating catalog entry");
274 return(NULL);
275 }
276 ret->next = NULL;
277 ret->parent = NULL;
278 ret->children = NULL;
279 ret->type = type;
280 if (type == XML_CATA_PUBLIC || type == XML_CATA_DELEGATE_PUBLIC) {
281 normid = xmlCatalogNormalizePublic(name);
282 if (normid != NULL)
283 name = (*normid != 0 ? normid : NULL);
284 }
285 if (name != NULL)
286 ret->name = xmlStrdup(name);
287 else
288 ret->name = NULL;
289 if (normid != NULL)
290 xmlFree(normid);
291 if (value != NULL)
292 ret->value = xmlStrdup(value);
293 else
294 ret->value = NULL;
295 if (URL == NULL)
296 URL = value;
297 if (URL != NULL)
298 ret->URL = xmlStrdup(URL);
299 else
300 ret->URL = NULL;
301 ret->prefer = prefer;
302 ret->dealloc = 0;
303 ret->depth = 0;
304 ret->group = group;
305 return(ret);
306}
307
308static void
309xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret);
310
317static void
318xmlFreeCatalogEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
319 xmlCatalogEntryPtr ret = (xmlCatalogEntryPtr) payload;
320 if (ret == NULL)
321 return;
322 /*
323 * Entries stored in the file hash must be deallocated
324 * only by the file hash cleaner !
325 */
326 if (ret->dealloc == 1)
327 return;
328
329 if (xmlDebugCatalogs) {
330 if (ret->name != NULL)
332 "Free catalog entry %s\n", ret->name);
333 else if (ret->value != NULL)
335 "Free catalog entry %s\n", ret->value);
336 else
338 "Free catalog entry\n");
339 }
340
341 if (ret->name != NULL)
342 xmlFree(ret->name);
343 if (ret->value != NULL)
344 xmlFree(ret->value);
345 if (ret->URL != NULL)
346 xmlFree(ret->URL);
347 xmlFree(ret);
348}
349
356static void
357xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret) {
358 xmlCatalogEntryPtr next;
359
360 while (ret != NULL) {
361 next = ret->next;
362 xmlFreeCatalogEntry(ret, NULL);
363 ret = next;
364 }
365}
366
374static void
375xmlFreeCatalogHashEntryList(void *payload,
377 xmlCatalogEntryPtr catal = (xmlCatalogEntryPtr) payload;
378 xmlCatalogEntryPtr children, next;
379
380 if (catal == NULL)
381 return;
382
383 children = catal->children;
384 while (children != NULL) {
385 next = children->next;
386 children->dealloc = 0;
387 children->children = NULL;
388 xmlFreeCatalogEntry(children, NULL);
389 children = next;
390 }
391 catal->dealloc = 0;
392 xmlFreeCatalogEntry(catal, NULL);
393}
394
405static xmlCatalogPtr
406xmlCreateNewCatalog(xmlCatalogType type, xmlCatalogPrefer prefer) {
407 xmlCatalogPtr ret;
408
409 ret = (xmlCatalogPtr) xmlMalloc(sizeof(xmlCatalog));
410 if (ret == NULL) {
411 xmlCatalogErrMemory("allocating catalog");
412 return(NULL);
413 }
414 memset(ret, 0, sizeof(xmlCatalog));
415 ret->type = type;
416 ret->catalNr = 0;
417 ret->catalMax = XML_MAX_SGML_CATA_DEPTH;
418 ret->prefer = prefer;
419 if (ret->type == XML_SGML_CATALOG_TYPE)
420 ret->sgml = xmlHashCreate(10);
421 return(ret);
422}
423
430void
431xmlFreeCatalog(xmlCatalogPtr catal) {
432 if (catal == NULL)
433 return;
434 if (catal->xml != NULL)
435 xmlFreeCatalogEntryList(catal->xml);
436 if (catal->sgml != NULL)
437 xmlHashFree(catal->sgml, xmlFreeCatalogEntry);
438 xmlFree(catal);
439}
440
441/************************************************************************
442 * *
443 * Serializing Catalogs *
444 * *
445 ************************************************************************/
446
447#ifdef LIBXML_OUTPUT_ENABLED
455static void
456xmlCatalogDumpEntry(void *payload, void *data,
458 xmlCatalogEntryPtr entry = (xmlCatalogEntryPtr) payload;
459 FILE *out = (FILE *) data;
460 if ((entry == NULL) || (out == NULL))
461 return;
462 switch (entry->type) {
463 case SGML_CATA_ENTITY:
464 fprintf(out, "ENTITY "); break;
465 case SGML_CATA_PENTITY:
466 fprintf(out, "ENTITY %%"); break;
467 case SGML_CATA_DOCTYPE:
468 fprintf(out, "DOCTYPE "); break;
469 case SGML_CATA_LINKTYPE:
470 fprintf(out, "LINKTYPE "); break;
471 case SGML_CATA_NOTATION:
472 fprintf(out, "NOTATION "); break;
473 case SGML_CATA_PUBLIC:
474 fprintf(out, "PUBLIC "); break;
475 case SGML_CATA_SYSTEM:
476 fprintf(out, "SYSTEM "); break;
477 case SGML_CATA_DELEGATE:
478 fprintf(out, "DELEGATE "); break;
479 case SGML_CATA_BASE:
480 fprintf(out, "BASE "); break;
481 case SGML_CATA_CATALOG:
482 fprintf(out, "CATALOG "); break;
483 case SGML_CATA_DOCUMENT:
484 fprintf(out, "DOCUMENT "); break;
485 case SGML_CATA_SGMLDECL:
486 fprintf(out, "SGMLDECL "); break;
487 default:
488 return;
489 }
490 switch (entry->type) {
491 case SGML_CATA_ENTITY:
492 case SGML_CATA_PENTITY:
493 case SGML_CATA_DOCTYPE:
494 case SGML_CATA_LINKTYPE:
495 case SGML_CATA_NOTATION:
496 fprintf(out, "%s", (const char *) entry->name); break;
497 case SGML_CATA_PUBLIC:
498 case SGML_CATA_SYSTEM:
499 case SGML_CATA_SGMLDECL:
500 case SGML_CATA_DOCUMENT:
501 case SGML_CATA_CATALOG:
502 case SGML_CATA_BASE:
503 case SGML_CATA_DELEGATE:
504 fprintf(out, "\"%s\"", entry->name); break;
505 default:
506 break;
507 }
508 switch (entry->type) {
509 case SGML_CATA_ENTITY:
510 case SGML_CATA_PENTITY:
511 case SGML_CATA_DOCTYPE:
512 case SGML_CATA_LINKTYPE:
513 case SGML_CATA_NOTATION:
514 case SGML_CATA_PUBLIC:
515 case SGML_CATA_SYSTEM:
516 case SGML_CATA_DELEGATE:
517 fprintf(out, " \"%s\"", entry->value); break;
518 default:
519 break;
520 }
521 fprintf(out, "\n");
522}
523
535static void xmlDumpXMLCatalogNode(xmlCatalogEntryPtr catal, xmlNodePtr catalog,
536 xmlDocPtr doc, xmlNsPtr ns, xmlCatalogEntryPtr cgroup) {
537 xmlNodePtr node;
538 xmlCatalogEntryPtr cur;
539 /*
540 * add all the catalog entries
541 */
542 cur = catal;
543 while (cur != NULL) {
544 if (cur->group == cgroup) {
545 switch (cur->type) {
546 case XML_CATA_REMOVED:
547 break;
548 case XML_CATA_BROKEN_CATALOG:
549 case XML_CATA_CATALOG:
550 if (cur == catal) {
551 cur = cur->children;
552 continue;
553 }
554 break;
555 case XML_CATA_NEXT_CATALOG:
556 node = xmlNewDocNode(doc, ns, BAD_CAST "nextCatalog", NULL);
557 xmlSetProp(node, BAD_CAST "catalog", cur->value);
558 xmlAddChild(catalog, node);
559 break;
560 case XML_CATA_NONE:
561 break;
562 case XML_CATA_GROUP:
563 node = xmlNewDocNode(doc, ns, BAD_CAST "group", NULL);
564 xmlSetProp(node, BAD_CAST "id", cur->name);
565 if (cur->value != NULL) {
566 xmlNsPtr xns;
567 xns = xmlSearchNsByHref(doc, node, XML_XML_NAMESPACE);
568 if (xns != NULL)
569 xmlSetNsProp(node, xns, BAD_CAST "base",
570 cur->value);
571 }
572 switch (cur->prefer) {
573 case XML_CATA_PREFER_NONE:
574 break;
575 case XML_CATA_PREFER_PUBLIC:
576 xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "public");
577 break;
578 case XML_CATA_PREFER_SYSTEM:
579 xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "system");
580 break;
581 }
582 xmlDumpXMLCatalogNode(cur->next, node, doc, ns, cur);
583 xmlAddChild(catalog, node);
584 break;
585 case XML_CATA_PUBLIC:
586 node = xmlNewDocNode(doc, ns, BAD_CAST "public", NULL);
587 xmlSetProp(node, BAD_CAST "publicId", cur->name);
588 xmlSetProp(node, BAD_CAST "uri", cur->value);
589 xmlAddChild(catalog, node);
590 break;
591 case XML_CATA_SYSTEM:
592 node = xmlNewDocNode(doc, ns, BAD_CAST "system", NULL);
593 xmlSetProp(node, BAD_CAST "systemId", cur->name);
594 xmlSetProp(node, BAD_CAST "uri", cur->value);
595 xmlAddChild(catalog, node);
596 break;
597 case XML_CATA_REWRITE_SYSTEM:
598 node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteSystem", NULL);
599 xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
600 xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
601 xmlAddChild(catalog, node);
602 break;
603 case XML_CATA_DELEGATE_PUBLIC:
604 node = xmlNewDocNode(doc, ns, BAD_CAST "delegatePublic", NULL);
605 xmlSetProp(node, BAD_CAST "publicIdStartString", cur->name);
606 xmlSetProp(node, BAD_CAST "catalog", cur->value);
607 xmlAddChild(catalog, node);
608 break;
609 case XML_CATA_DELEGATE_SYSTEM:
610 node = xmlNewDocNode(doc, ns, BAD_CAST "delegateSystem", NULL);
611 xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name);
612 xmlSetProp(node, BAD_CAST "catalog", cur->value);
613 xmlAddChild(catalog, node);
614 break;
615 case XML_CATA_URI:
616 node = xmlNewDocNode(doc, ns, BAD_CAST "uri", NULL);
617 xmlSetProp(node, BAD_CAST "name", cur->name);
618 xmlSetProp(node, BAD_CAST "uri", cur->value);
619 xmlAddChild(catalog, node);
620 break;
621 case XML_CATA_REWRITE_URI:
622 node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteURI", NULL);
623 xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
624 xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value);
625 xmlAddChild(catalog, node);
626 break;
627 case XML_CATA_DELEGATE_URI:
628 node = xmlNewDocNode(doc, ns, BAD_CAST "delegateURI", NULL);
629 xmlSetProp(node, BAD_CAST "uriStartString", cur->name);
630 xmlSetProp(node, BAD_CAST "catalog", cur->value);
631 xmlAddChild(catalog, node);
632 break;
633 case SGML_CATA_SYSTEM:
634 case SGML_CATA_PUBLIC:
635 case SGML_CATA_ENTITY:
636 case SGML_CATA_PENTITY:
637 case SGML_CATA_DOCTYPE:
638 case SGML_CATA_LINKTYPE:
639 case SGML_CATA_NOTATION:
640 case SGML_CATA_DELEGATE:
641 case SGML_CATA_BASE:
642 case SGML_CATA_CATALOG:
643 case SGML_CATA_DOCUMENT:
644 case SGML_CATA_SGMLDECL:
645 break;
646 }
647 }
648 cur = cur->next;
649 }
650}
651
652static int
653xmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) {
654 int ret;
655 xmlDocPtr doc;
656 xmlNsPtr ns;
657 xmlDtdPtr dtd;
658 xmlNodePtr catalog;
659 xmlOutputBufferPtr buf;
660
661 /*
662 * Rebuild a catalog
663 */
664 doc = xmlNewDoc(NULL);
665 if (doc == NULL)
666 return(-1);
667 dtd = xmlNewDtd(doc, BAD_CAST "catalog",
668 BAD_CAST "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN",
669BAD_CAST "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd");
670
671 xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd);
672
673 ns = xmlNewNs(NULL, XML_CATALOGS_NAMESPACE, NULL);
674 if (ns == NULL) {
675 xmlFreeDoc(doc);
676 return(-1);
677 }
678 catalog = xmlNewDocNode(doc, ns, BAD_CAST "catalog", NULL);
679 if (catalog == NULL) {
680 xmlFreeNs(ns);
681 xmlFreeDoc(doc);
682 return(-1);
683 }
684 catalog->nsDef = ns;
685 xmlAddChild((xmlNodePtr) doc, catalog);
686
687 xmlDumpXMLCatalogNode(catal, catalog, doc, ns, NULL);
688
689 /*
690 * reserialize it
691 */
692 buf = xmlOutputBufferCreateFile(out, NULL);
693 if (buf == NULL) {
694 xmlFreeDoc(doc);
695 return(-1);
696 }
697 ret = xmlSaveFormatFileTo(buf, doc, NULL, 1);
698
699 /*
700 * Free it
701 */
702 xmlFreeDoc(doc);
703
704 return(ret);
705}
706#endif /* LIBXML_OUTPUT_ENABLED */
707
708/************************************************************************
709 * *
710 * Converting SGML Catalogs to XML *
711 * *
712 ************************************************************************/
713
721static void
722xmlCatalogConvertEntry(void *payload, void *data,
724 xmlCatalogEntryPtr entry = (xmlCatalogEntryPtr) payload;
725 xmlCatalogPtr catal = (xmlCatalogPtr) data;
726 if ((entry == NULL) || (catal == NULL) || (catal->sgml == NULL) ||
727 (catal->xml == NULL))
728 return;
729 switch (entry->type) {
730 case SGML_CATA_ENTITY:
731 entry->type = XML_CATA_PUBLIC;
732 break;
733 case SGML_CATA_PENTITY:
734 entry->type = XML_CATA_PUBLIC;
735 break;
736 case SGML_CATA_DOCTYPE:
737 entry->type = XML_CATA_PUBLIC;
738 break;
739 case SGML_CATA_LINKTYPE:
740 entry->type = XML_CATA_PUBLIC;
741 break;
742 case SGML_CATA_NOTATION:
743 entry->type = XML_CATA_PUBLIC;
744 break;
745 case SGML_CATA_PUBLIC:
746 entry->type = XML_CATA_PUBLIC;
747 break;
748 case SGML_CATA_SYSTEM:
749 entry->type = XML_CATA_SYSTEM;
750 break;
751 case SGML_CATA_DELEGATE:
752 entry->type = XML_CATA_DELEGATE_PUBLIC;
753 break;
754 case SGML_CATA_CATALOG:
755 entry->type = XML_CATA_CATALOG;
756 break;
757 default:
758 xmlHashRemoveEntry(catal->sgml, entry->name, xmlFreeCatalogEntry);
759 return;
760 }
761 /*
762 * Conversion successful, remove from the SGML catalog
763 * and add it to the default XML one
764 */
765 xmlHashRemoveEntry(catal->sgml, entry->name, NULL);
766 entry->parent = catal->xml;
767 entry->next = NULL;
768 if (catal->xml->children == NULL)
769 catal->xml->children = entry;
770 else {
771 xmlCatalogEntryPtr prev;
772
773 prev = catal->xml->children;
774 while (prev->next != NULL)
775 prev = prev->next;
776 prev->next = entry;
777 }
778}
779
788int
789xmlConvertSGMLCatalog(xmlCatalogPtr catal) {
790
791 if ((catal == NULL) || (catal->type != XML_SGML_CATALOG_TYPE))
792 return(-1);
793
794 if (xmlDebugCatalogs) {
796 "Converting SGML catalog to XML\n");
797 }
798 xmlHashScan(catal->sgml, xmlCatalogConvertEntry, &catal);
799 return(0);
800}
801
802/************************************************************************
803 * *
804 * Helper function *
805 * *
806 ************************************************************************/
807
817static xmlChar *
818xmlCatalogUnWrapURN(const xmlChar *urn) {
819 xmlChar result[2000];
820 unsigned int i = 0;
821
822 if (xmlStrncmp(urn, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1))
823 return(NULL);
824 urn += sizeof(XML_URN_PUBID) - 1;
825
826 while (*urn != 0) {
827 if (i > sizeof(result) - 4)
828 break;
829 if (*urn == '+') {
830 result[i++] = ' ';
831 urn++;
832 } else if (*urn == ':') {
833 result[i++] = '/';
834 result[i++] = '/';
835 urn++;
836 } else if (*urn == ';') {
837 result[i++] = ':';
838 result[i++] = ':';
839 urn++;
840 } else if (*urn == '%') {
841 if ((urn[1] == '2') && (urn[2] == 'B'))
842 result[i++] = '+';
843 else if ((urn[1] == '3') && (urn[2] == 'A'))
844 result[i++] = ':';
845 else if ((urn[1] == '2') && (urn[2] == 'F'))
846 result[i++] = '/';
847 else if ((urn[1] == '3') && (urn[2] == 'B'))
848 result[i++] = ';';
849 else if ((urn[1] == '2') && (urn[2] == '7'))
850 result[i++] = '\'';
851 else if ((urn[1] == '3') && (urn[2] == 'F'))
852 result[i++] = '?';
853 else if ((urn[1] == '2') && (urn[2] == '3'))
854 result[i++] = '#';
855 else if ((urn[1] == '2') && (urn[2] == '5'))
856 result[i++] = '%';
857 else {
858 result[i++] = *urn;
859 urn++;
860 continue;
861 }
862 urn += 3;
863 } else {
864 result[i++] = *urn;
865 urn++;
866 }
867 }
868 result[i] = 0;
869
870 return(xmlStrdup(result));
871}
872
883xmlDocPtr
884xmlParseCatalogFile(const char *filename) {
885 xmlDocPtr ret;
886 xmlParserCtxtPtr ctxt;
887 char *directory = NULL;
888 xmlParserInputPtr inputStream;
889 xmlParserInputBufferPtr buf;
890
891 ctxt = xmlNewParserCtxt();
892 if (ctxt == NULL) {
893 xmlCatalogErrMemory("allocating parser context");
894 return(NULL);
895 }
896
898 if (buf == NULL) {
899 xmlFreeParserCtxt(ctxt);
900 return(NULL);
901 }
902
903 inputStream = xmlNewInputStream(ctxt);
904 if (inputStream == NULL) {
906 xmlFreeParserCtxt(ctxt);
907 return(NULL);
908 }
909
910 inputStream->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
911 inputStream->buf = buf;
912 xmlBufResetInput(buf->buffer, inputStream);
913
914 inputPush(ctxt, inputStream);
915 if (ctxt->directory == NULL)
917 if ((ctxt->directory == NULL) && (directory != NULL))
918 ctxt->directory = directory;
919 ctxt->valid = 0;
920 ctxt->validate = 0;
921 ctxt->loadsubset = 0;
922 ctxt->pedantic = 0;
923 ctxt->dictNames = 1;
924
925 xmlParseDocument(ctxt);
926
927 if (ctxt->wellFormed)
928 ret = ctxt->myDoc;
929 else {
930 ret = NULL;
931 xmlFreeDoc(ctxt->myDoc);
932 ctxt->myDoc = NULL;
933 }
934 xmlFreeParserCtxt(ctxt);
935
936 return(ret);
937}
938
947static xmlChar *
948xmlLoadFileContent(const char *filename)
949{
950#ifdef HAVE_STAT
951 int fd;
952#else
953 FILE *fd;
954#endif
955 int len;
956 long size;
957
958#ifdef HAVE_STAT
959 struct stat info;
960#endif
962
963 if (filename == NULL)
964 return (NULL);
965
966#ifdef HAVE_STAT
967 if (stat(filename, &info) < 0)
968 return (NULL);
969#endif
970
971#ifdef HAVE_STAT
972 if ((fd = open(filename, O_RDONLY)) < 0)
973#else
974 if ((fd = fopen(filename, "rb")) == NULL)
975#endif
976 {
977 return (NULL);
978 }
979#ifdef HAVE_STAT
980 size = info.st_size;
981#else
982 if (fseek(fd, 0, SEEK_END) || (size = ftell(fd)) == EOF || fseek(fd, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */
983 fclose(fd);
984 return (NULL);
985 }
986#endif
988 if (content == NULL) {
989 xmlCatalogErrMemory("allocating catalog data");
990#ifdef HAVE_STAT
991 close(fd);
992#else
993 fclose(fd);
994#endif
995 return (NULL);
996 }
997#ifdef HAVE_STAT
998 len = read(fd, content, size);
999 close(fd);
1000#else
1001 len = fread(content, 1, size, fd);
1002 fclose(fd);
1003#endif
1004 if (len < 0) {
1006 return (NULL);
1007 }
1008 content[len] = 0;
1009
1010 return(content);
1011}
1012
1025static xmlChar *
1026xmlCatalogNormalizePublic(const xmlChar *pubID)
1027{
1028 int ok = 1;
1029 int white;
1030 const xmlChar *p;
1031 xmlChar *ret;
1032 xmlChar *q;
1033
1034 if (pubID == NULL)
1035 return(NULL);
1036
1037 white = 1;
1038 for (p = pubID;*p != 0 && ok;p++) {
1039 if (!xmlIsBlank_ch(*p))
1040 white = 0;
1041 else if (*p == 0x20 && !white)
1042 white = 1;
1043 else
1044 ok = 0;
1045 }
1046 if (ok && !white) /* is normalized */
1047 return(NULL);
1048
1049 ret = xmlStrdup(pubID);
1050 q = ret;
1051 white = 0;
1052 for (p = pubID;*p != 0;p++) {
1053 if (xmlIsBlank_ch(*p)) {
1054 if (q != ret)
1055 white = 1;
1056 } else {
1057 if (white) {
1058 *(q++) = 0x20;
1059 white = 0;
1060 }
1061 *(q++) = *p;
1062 }
1063 }
1064 *q = 0;
1065 return(ret);
1066}
1067
1068/************************************************************************
1069 * *
1070 * The XML Catalog parser *
1071 * *
1072 ************************************************************************/
1073
1074static xmlCatalogEntryPtr
1075xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename);
1076static void
1077xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
1078 xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup);
1079static xmlChar *
1080xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1081 const xmlChar *sysID);
1082static xmlChar *
1083xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI);
1084
1085
1094static xmlCatalogEntryType
1095xmlGetXMLCatalogEntryType(const xmlChar *name) {
1096 xmlCatalogEntryType type = XML_CATA_NONE;
1097 if (xmlStrEqual(name, (const xmlChar *) "system"))
1098 type = XML_CATA_SYSTEM;
1099 else if (xmlStrEqual(name, (const xmlChar *) "public"))
1100 type = XML_CATA_PUBLIC;
1101 else if (xmlStrEqual(name, (const xmlChar *) "rewriteSystem"))
1102 type = XML_CATA_REWRITE_SYSTEM;
1103 else if (xmlStrEqual(name, (const xmlChar *) "delegatePublic"))
1104 type = XML_CATA_DELEGATE_PUBLIC;
1105 else if (xmlStrEqual(name, (const xmlChar *) "delegateSystem"))
1106 type = XML_CATA_DELEGATE_SYSTEM;
1107 else if (xmlStrEqual(name, (const xmlChar *) "uri"))
1108 type = XML_CATA_URI;
1109 else if (xmlStrEqual(name, (const xmlChar *) "rewriteURI"))
1110 type = XML_CATA_REWRITE_URI;
1111 else if (xmlStrEqual(name, (const xmlChar *) "delegateURI"))
1112 type = XML_CATA_DELEGATE_URI;
1113 else if (xmlStrEqual(name, (const xmlChar *) "nextCatalog"))
1114 type = XML_CATA_NEXT_CATALOG;
1115 else if (xmlStrEqual(name, (const xmlChar *) "catalog"))
1116 type = XML_CATA_CATALOG;
1117 return(type);
1118}
1119
1135static xmlCatalogEntryPtr
1136xmlParseXMLCatalogOneNode(xmlNodePtr cur, xmlCatalogEntryType type,
1137 const xmlChar *name, const xmlChar *attrName,
1138 const xmlChar *uriAttrName, xmlCatalogPrefer prefer,
1139 xmlCatalogEntryPtr cgroup) {
1140 int ok = 1;
1141 xmlChar *uriValue;
1142 xmlChar *nameValue = NULL;
1143 xmlChar *base = NULL;
1144 xmlChar *URL = NULL;
1145 xmlCatalogEntryPtr ret = NULL;
1146
1147 if (attrName != NULL) {
1148 nameValue = xmlGetProp(cur, attrName);
1149 if (nameValue == NULL) {
1150 xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
1151 "%s entry lacks '%s'\n", name, attrName, NULL);
1152 ok = 0;
1153 }
1154 }
1155 uriValue = xmlGetProp(cur, uriAttrName);
1156 if (uriValue == NULL) {
1157 xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
1158 "%s entry lacks '%s'\n", name, uriAttrName, NULL);
1159 ok = 0;
1160 }
1161 if (!ok) {
1162 if (nameValue != NULL)
1163 xmlFree(nameValue);
1164 if (uriValue != NULL)
1165 xmlFree(uriValue);
1166 return(NULL);
1167 }
1168
1169 base = xmlNodeGetBase(cur->doc, cur);
1170 URL = xmlBuildURI(uriValue, base);
1171 if (URL != NULL) {
1172 if (xmlDebugCatalogs > 1) {
1173 if (nameValue != NULL)
1175 "Found %s: '%s' '%s'\n", name, nameValue, URL);
1176 else
1178 "Found %s: '%s'\n", name, URL);
1179 }
1180 ret = xmlNewCatalogEntry(type, nameValue, uriValue, URL, prefer, cgroup);
1181 } else {
1182 xmlCatalogErr(ret, cur, XML_CATALOG_ENTRY_BROKEN,
1183 "%s entry '%s' broken ?: %s\n", name, uriAttrName, uriValue);
1184 }
1185 if (nameValue != NULL)
1186 xmlFree(nameValue);
1187 if (uriValue != NULL)
1188 xmlFree(uriValue);
1189 if (base != NULL)
1190 xmlFree(base);
1191 if (URL != NULL)
1192 xmlFree(URL);
1193 return(ret);
1194}
1195
1207static void
1208xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer,
1209 xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup)
1210{
1211 xmlChar *base = NULL;
1212 xmlCatalogEntryPtr entry = NULL;
1213
1214 if (cur == NULL)
1215 return;
1216 if (xmlStrEqual(cur->name, BAD_CAST "group")) {
1217 xmlChar *prop;
1218 xmlCatalogPrefer pref = XML_CATA_PREFER_NONE;
1219
1220 prop = xmlGetProp(cur, BAD_CAST "prefer");
1221 if (prop != NULL) {
1222 if (xmlStrEqual(prop, BAD_CAST "system")) {
1223 prefer = XML_CATA_PREFER_SYSTEM;
1224 } else if (xmlStrEqual(prop, BAD_CAST "public")) {
1225 prefer = XML_CATA_PREFER_PUBLIC;
1226 } else {
1227 xmlCatalogErr(parent, cur, XML_CATALOG_PREFER_VALUE,
1228 "Invalid value for prefer: '%s'\n",
1229 prop, NULL, NULL);
1230 }
1231 xmlFree(prop);
1232 pref = prefer;
1233 }
1234 prop = xmlGetProp(cur, BAD_CAST "id");
1235 base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE);
1236 entry = xmlNewCatalogEntry(XML_CATA_GROUP, prop, base, NULL, pref, cgroup);
1237 xmlFree(prop);
1238 } else if (xmlStrEqual(cur->name, BAD_CAST "public")) {
1239 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_PUBLIC,
1240 BAD_CAST "public", BAD_CAST "publicId", BAD_CAST "uri", prefer, cgroup);
1241 } else if (xmlStrEqual(cur->name, BAD_CAST "system")) {
1242 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_SYSTEM,
1243 BAD_CAST "system", BAD_CAST "systemId", BAD_CAST "uri", prefer, cgroup);
1244 } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteSystem")) {
1245 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_SYSTEM,
1246 BAD_CAST "rewriteSystem", BAD_CAST "systemIdStartString",
1247 BAD_CAST "rewritePrefix", prefer, cgroup);
1248 } else if (xmlStrEqual(cur->name, BAD_CAST "delegatePublic")) {
1249 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_PUBLIC,
1250 BAD_CAST "delegatePublic", BAD_CAST "publicIdStartString",
1251 BAD_CAST "catalog", prefer, cgroup);
1252 } else if (xmlStrEqual(cur->name, BAD_CAST "delegateSystem")) {
1253 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_SYSTEM,
1254 BAD_CAST "delegateSystem", BAD_CAST "systemIdStartString",
1255 BAD_CAST "catalog", prefer, cgroup);
1256 } else if (xmlStrEqual(cur->name, BAD_CAST "uri")) {
1257 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_URI,
1258 BAD_CAST "uri", BAD_CAST "name",
1259 BAD_CAST "uri", prefer, cgroup);
1260 } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteURI")) {
1261 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_URI,
1262 BAD_CAST "rewriteURI", BAD_CAST "uriStartString",
1263 BAD_CAST "rewritePrefix", prefer, cgroup);
1264 } else if (xmlStrEqual(cur->name, BAD_CAST "delegateURI")) {
1265 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_URI,
1266 BAD_CAST "delegateURI", BAD_CAST "uriStartString",
1267 BAD_CAST "catalog", prefer, cgroup);
1268 } else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) {
1269 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG,
1270 BAD_CAST "nextCatalog", NULL,
1271 BAD_CAST "catalog", prefer, cgroup);
1272 }
1273 if (entry != NULL) {
1274 if (parent != NULL) {
1275 entry->parent = parent;
1276 if (parent->children == NULL)
1277 parent->children = entry;
1278 else {
1279 xmlCatalogEntryPtr prev;
1280
1281 prev = parent->children;
1282 while (prev->next != NULL)
1283 prev = prev->next;
1284 prev->next = entry;
1285 }
1286 }
1287 if (entry->type == XML_CATA_GROUP) {
1288 /*
1289 * Recurse to propagate prefer to the subtree
1290 * (xml:base handling is automated)
1291 */
1292 xmlParseXMLCatalogNodeList(cur->children, prefer, parent, entry);
1293 }
1294 }
1295 if (base != NULL)
1296 xmlFree(base);
1297}
1298
1310static void
1311xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
1312 xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup) {
1313 while (cur != NULL) {
1314 if ((cur->ns != NULL) && (cur->ns->href != NULL) &&
1315 (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) {
1316 xmlParseXMLCatalogNode(cur, prefer, parent, cgroup);
1317 }
1318 cur = cur->next;
1319 }
1320 /* TODO: sort the list according to REWRITE lengths and prefer value */
1321}
1322
1333static xmlCatalogEntryPtr
1334xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename) {
1335 xmlDocPtr doc;
1336 xmlNodePtr cur;
1337 xmlChar *prop;
1338 xmlCatalogEntryPtr parent = NULL;
1339
1340 if (filename == NULL)
1341 return(NULL);
1342
1343 doc = xmlParseCatalogFile((const char *) filename);
1344 if (doc == NULL) {
1345 if (xmlDebugCatalogs)
1347 "Failed to parse catalog %s\n", filename);
1348 return(NULL);
1349 }
1350
1351 if (xmlDebugCatalogs)
1353 "%d Parsing catalog %s\n", xmlGetThreadId(), filename);
1354
1355 cur = xmlDocGetRootElement(doc);
1356 if ((cur != NULL) && (xmlStrEqual(cur->name, BAD_CAST "catalog")) &&
1357 (cur->ns != NULL) && (cur->ns->href != NULL) &&
1358 (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) {
1359
1360 parent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
1361 (const xmlChar *)filename, NULL, prefer, NULL);
1362 if (parent == NULL) {
1363 xmlFreeDoc(doc);
1364 return(NULL);
1365 }
1366
1367 prop = xmlGetProp(cur, BAD_CAST "prefer");
1368 if (prop != NULL) {
1369 if (xmlStrEqual(prop, BAD_CAST "system")) {
1370 prefer = XML_CATA_PREFER_SYSTEM;
1371 } else if (xmlStrEqual(prop, BAD_CAST "public")) {
1372 prefer = XML_CATA_PREFER_PUBLIC;
1373 } else {
1374 xmlCatalogErr(NULL, cur, XML_CATALOG_PREFER_VALUE,
1375 "Invalid value for prefer: '%s'\n",
1376 prop, NULL, NULL);
1377 }
1378 xmlFree(prop);
1379 }
1380 cur = cur->children;
1381 xmlParseXMLCatalogNodeList(cur, prefer, parent, NULL);
1382 } else {
1383 xmlCatalogErr(NULL, (xmlNodePtr) doc, XML_CATALOG_NOT_CATALOG,
1384 "File %s is not an XML Catalog\n",
1385 filename, NULL, NULL);
1386 xmlFreeDoc(doc);
1387 return(NULL);
1388 }
1389 xmlFreeDoc(doc);
1390 return(parent);
1391}
1392
1401static int
1402xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) {
1403 xmlCatalogEntryPtr doc;
1404
1405 if (catal == NULL)
1406 return(-1);
1407 if (catal->URL == NULL)
1408 return(-1);
1409
1410 /*
1411 * lock the whole catalog for modification
1412 */
1413 xmlRMutexLock(xmlCatalogMutex);
1414 if (catal->children != NULL) {
1415 /* Okay someone else did it in the meantime */
1416 xmlRMutexUnlock(xmlCatalogMutex);
1417 return(0);
1418 }
1419
1420 if (xmlCatalogXMLFiles != NULL) {
1421 doc = (xmlCatalogEntryPtr)
1422 xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
1423 if (doc != NULL) {
1424 if (xmlDebugCatalogs)
1426 "Found %s in file hash\n", catal->URL);
1427
1428 if (catal->type == XML_CATA_CATALOG)
1429 catal->children = doc->children;
1430 else
1431 catal->children = doc;
1432 catal->dealloc = 0;
1433 xmlRMutexUnlock(xmlCatalogMutex);
1434 return(0);
1435 }
1436 if (xmlDebugCatalogs)
1438 "%s not found in file hash\n", catal->URL);
1439 }
1440
1441 /*
1442 * Fetch and parse. Note that xmlParseXMLCatalogFile does not
1443 * use the existing catalog, there is no recursion allowed at
1444 * that level.
1445 */
1446 doc = xmlParseXMLCatalogFile(catal->prefer, catal->URL);
1447 if (doc == NULL) {
1448 catal->type = XML_CATA_BROKEN_CATALOG;
1449 xmlRMutexUnlock(xmlCatalogMutex);
1450 return(-1);
1451 }
1452
1453 if (catal->type == XML_CATA_CATALOG)
1454 catal->children = doc->children;
1455 else
1456 catal->children = doc;
1457
1458 doc->dealloc = 1;
1459
1460 if (xmlCatalogXMLFiles == NULL)
1461 xmlCatalogXMLFiles = xmlHashCreate(10);
1462 if (xmlCatalogXMLFiles != NULL) {
1463 if (xmlDebugCatalogs)
1465 "%s added to file hash\n", catal->URL);
1466 xmlHashAddEntry(xmlCatalogXMLFiles, catal->URL, doc);
1467 }
1468 xmlRMutexUnlock(xmlCatalogMutex);
1469 return(0);
1470}
1471
1472/************************************************************************
1473 * *
1474 * XML Catalog handling *
1475 * *
1476 ************************************************************************/
1477
1490static int
1491xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type,
1492 const xmlChar *orig, const xmlChar *replace) {
1493 xmlCatalogEntryPtr cur;
1494 xmlCatalogEntryType typ;
1495 int doregister = 0;
1496
1497 if ((catal == NULL) ||
1498 ((catal->type != XML_CATA_CATALOG) &&
1499 (catal->type != XML_CATA_BROKEN_CATALOG)))
1500 return(-1);
1501 if (catal->children == NULL) {
1502 xmlFetchXMLCatalogFile(catal);
1503 }
1504 if (catal->children == NULL)
1505 doregister = 1;
1506
1507 typ = xmlGetXMLCatalogEntryType(type);
1508 if (typ == XML_CATA_NONE) {
1509 if (xmlDebugCatalogs)
1511 "Failed to add unknown element %s to catalog\n", type);
1512 return(-1);
1513 }
1514
1515 cur = catal->children;
1516 /*
1517 * Might be a simple "update in place"
1518 */
1519 if (cur != NULL) {
1520 while (cur != NULL) {
1521 if ((orig != NULL) && (cur->type == typ) &&
1522 (xmlStrEqual(orig, cur->name))) {
1523 if (xmlDebugCatalogs)
1525 "Updating element %s to catalog\n", type);
1526 if (cur->value != NULL)
1527 xmlFree(cur->value);
1528 if (cur->URL != NULL)
1529 xmlFree(cur->URL);
1530 cur->value = xmlStrdup(replace);
1531 cur->URL = xmlStrdup(replace);
1532 return(0);
1533 }
1534 if (cur->next == NULL)
1535 break;
1536 cur = cur->next;
1537 }
1538 }
1539 if (xmlDebugCatalogs)
1541 "Adding element %s to catalog\n", type);
1542 if (cur == NULL)
1543 catal->children = xmlNewCatalogEntry(typ, orig, replace,
1544 NULL, catal->prefer, NULL);
1545 else
1546 cur->next = xmlNewCatalogEntry(typ, orig, replace,
1547 NULL, catal->prefer, NULL);
1548 if (doregister) {
1549 catal->type = XML_CATA_CATALOG;
1550 cur = (xmlCatalogEntryPtr)xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
1551 if (cur != NULL)
1552 cur->children = catal->children;
1553 }
1554
1555 return(0);
1556}
1557
1568static int
1569xmlDelXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *value) {
1570 xmlCatalogEntryPtr cur;
1571 int ret = 0;
1572
1573 if ((catal == NULL) ||
1574 ((catal->type != XML_CATA_CATALOG) &&
1575 (catal->type != XML_CATA_BROKEN_CATALOG)))
1576 return(-1);
1577 if (value == NULL)
1578 return(-1);
1579 if (catal->children == NULL) {
1580 xmlFetchXMLCatalogFile(catal);
1581 }
1582
1583 /*
1584 * Scan the children
1585 */
1586 cur = catal->children;
1587 while (cur != NULL) {
1588 if (((cur->name != NULL) && (xmlStrEqual(value, cur->name))) ||
1589 (xmlStrEqual(value, cur->value))) {
1590 if (xmlDebugCatalogs) {
1591 if (cur->name != NULL)
1593 "Removing element %s from catalog\n", cur->name);
1594 else
1596 "Removing element %s from catalog\n", cur->value);
1597 }
1598 cur->type = XML_CATA_REMOVED;
1599 }
1600 cur = cur->next;
1601 }
1602 return(ret);
1603}
1604
1619static xmlChar *
1620xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1621 const xmlChar *sysID) {
1622 xmlChar *ret = NULL;
1623 xmlCatalogEntryPtr cur;
1624 int haveDelegate = 0;
1625 int haveNext = 0;
1626
1627 /*
1628 * protection against loops
1629 */
1630 if (catal->depth > MAX_CATAL_DEPTH) {
1631 xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
1632 "Detected recursion in catalog %s\n",
1633 catal->name, NULL, NULL);
1634 return(NULL);
1635 }
1636 catal->depth++;
1637
1638 /*
1639 * First tries steps 2/ 3/ 4/ if a system ID is provided.
1640 */
1641 if (sysID != NULL) {
1642 xmlCatalogEntryPtr rewrite = NULL;
1643 int lenrewrite = 0, len;
1644 cur = catal;
1645 haveDelegate = 0;
1646 while (cur != NULL) {
1647 switch (cur->type) {
1648 case XML_CATA_SYSTEM:
1649 if (xmlStrEqual(sysID, cur->name)) {
1650 if (xmlDebugCatalogs)
1652 "Found system match %s, using %s\n",
1653 cur->name, cur->URL);
1654 catal->depth--;
1655 return(xmlStrdup(cur->URL));
1656 }
1657 break;
1658 case XML_CATA_REWRITE_SYSTEM:
1659 len = xmlStrlen(cur->name);
1660 if ((len > lenrewrite) &&
1661 (!xmlStrncmp(sysID, cur->name, len))) {
1662 lenrewrite = len;
1663 rewrite = cur;
1664 }
1665 break;
1666 case XML_CATA_DELEGATE_SYSTEM:
1667 if (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))
1668 haveDelegate++;
1669 break;
1670 case XML_CATA_NEXT_CATALOG:
1671 haveNext++;
1672 break;
1673 default:
1674 break;
1675 }
1676 cur = cur->next;
1677 }
1678 if (rewrite != NULL) {
1679 if (xmlDebugCatalogs)
1681 "Using rewriting rule %s\n", rewrite->name);
1682 ret = xmlStrdup(rewrite->URL);
1683 if (ret != NULL)
1684 ret = xmlStrcat(ret, &sysID[lenrewrite]);
1685 catal->depth--;
1686 return(ret);
1687 }
1688 if (haveDelegate) {
1689 const xmlChar *delegates[MAX_DELEGATE];
1690 int nbList = 0, i;
1691
1692 /*
1693 * Assume the entries have been sorted by decreasing substring
1694 * matches when the list was produced.
1695 */
1696 cur = catal;
1697 while (cur != NULL) {
1698 if ((cur->type == XML_CATA_DELEGATE_SYSTEM) &&
1699 (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))) {
1700 for (i = 0;i < nbList;i++)
1701 if (xmlStrEqual(cur->URL, delegates[i]))
1702 break;
1703 if (i < nbList) {
1704 cur = cur->next;
1705 continue;
1706 }
1707 if (nbList < MAX_DELEGATE)
1708 delegates[nbList++] = cur->URL;
1709
1710 if (cur->children == NULL) {
1711 xmlFetchXMLCatalogFile(cur);
1712 }
1713 if (cur->children != NULL) {
1714 if (xmlDebugCatalogs)
1716 "Trying system delegate %s\n", cur->URL);
1717 ret = xmlCatalogListXMLResolve(
1718 cur->children, NULL, sysID);
1719 if (ret != NULL) {
1720 catal->depth--;
1721 return(ret);
1722 }
1723 }
1724 }
1725 cur = cur->next;
1726 }
1727 /*
1728 * Apply the cut algorithm explained in 4/
1729 */
1730 catal->depth--;
1731 return(XML_CATAL_BREAK);
1732 }
1733 }
1734 /*
1735 * Then tries 5/ 6/ if a public ID is provided
1736 */
1737 if (pubID != NULL) {
1738 cur = catal;
1739 haveDelegate = 0;
1740 while (cur != NULL) {
1741 switch (cur->type) {
1742 case XML_CATA_PUBLIC:
1743 if (xmlStrEqual(pubID, cur->name)) {
1744 if (xmlDebugCatalogs)
1746 "Found public match %s\n", cur->name);
1747 catal->depth--;
1748 return(xmlStrdup(cur->URL));
1749 }
1750 break;
1751 case XML_CATA_DELEGATE_PUBLIC:
1752 if (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)) &&
1753 (cur->prefer == XML_CATA_PREFER_PUBLIC))
1754 haveDelegate++;
1755 break;
1756 case XML_CATA_NEXT_CATALOG:
1757 if (sysID == NULL)
1758 haveNext++;
1759 break;
1760 default:
1761 break;
1762 }
1763 cur = cur->next;
1764 }
1765 if (haveDelegate) {
1766 const xmlChar *delegates[MAX_DELEGATE];
1767 int nbList = 0, i;
1768
1769 /*
1770 * Assume the entries have been sorted by decreasing substring
1771 * matches when the list was produced.
1772 */
1773 cur = catal;
1774 while (cur != NULL) {
1775 if ((cur->type == XML_CATA_DELEGATE_PUBLIC) &&
1776 (cur->prefer == XML_CATA_PREFER_PUBLIC) &&
1777 (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)))) {
1778
1779 for (i = 0;i < nbList;i++)
1780 if (xmlStrEqual(cur->URL, delegates[i]))
1781 break;
1782 if (i < nbList) {
1783 cur = cur->next;
1784 continue;
1785 }
1786 if (nbList < MAX_DELEGATE)
1787 delegates[nbList++] = cur->URL;
1788
1789 if (cur->children == NULL) {
1790 xmlFetchXMLCatalogFile(cur);
1791 }
1792 if (cur->children != NULL) {
1793 if (xmlDebugCatalogs)
1795 "Trying public delegate %s\n", cur->URL);
1796 ret = xmlCatalogListXMLResolve(
1797 cur->children, pubID, NULL);
1798 if (ret != NULL) {
1799 catal->depth--;
1800 return(ret);
1801 }
1802 }
1803 }
1804 cur = cur->next;
1805 }
1806 /*
1807 * Apply the cut algorithm explained in 4/
1808 */
1809 catal->depth--;
1810 return(XML_CATAL_BREAK);
1811 }
1812 }
1813 if (haveNext) {
1814 cur = catal;
1815 while (cur != NULL) {
1816 if (cur->type == XML_CATA_NEXT_CATALOG) {
1817 if (cur->children == NULL) {
1818 xmlFetchXMLCatalogFile(cur);
1819 }
1820 if (cur->children != NULL) {
1821 ret = xmlCatalogListXMLResolve(cur->children, pubID, sysID);
1822 if (ret != NULL) {
1823 catal->depth--;
1824 return(ret);
1825 } else if (catal->depth > MAX_CATAL_DEPTH) {
1826 return(NULL);
1827 }
1828 }
1829 }
1830 cur = cur->next;
1831 }
1832 }
1833
1834 catal->depth--;
1835 return(NULL);
1836}
1837
1852static xmlChar *
1853xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
1854 xmlChar *ret = NULL;
1855 xmlCatalogEntryPtr cur;
1856 int haveDelegate = 0;
1857 int haveNext = 0;
1858 xmlCatalogEntryPtr rewrite = NULL;
1859 int lenrewrite = 0, len;
1860
1861 if (catal == NULL)
1862 return(NULL);
1863
1864 if (URI == NULL)
1865 return(NULL);
1866
1867 if (catal->depth > MAX_CATAL_DEPTH) {
1868 xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
1869 "Detected recursion in catalog %s\n",
1870 catal->name, NULL, NULL);
1871 return(NULL);
1872 }
1873
1874 /*
1875 * First tries steps 2/ 3/ 4/ if a system ID is provided.
1876 */
1877 cur = catal;
1878 haveDelegate = 0;
1879 while (cur != NULL) {
1880 switch (cur->type) {
1881 case XML_CATA_URI:
1882 if (xmlStrEqual(URI, cur->name)) {
1883 if (xmlDebugCatalogs)
1885 "Found URI match %s\n", cur->name);
1886 return(xmlStrdup(cur->URL));
1887 }
1888 break;
1889 case XML_CATA_REWRITE_URI:
1890 len = xmlStrlen(cur->name);
1891 if ((len > lenrewrite) &&
1892 (!xmlStrncmp(URI, cur->name, len))) {
1893 lenrewrite = len;
1894 rewrite = cur;
1895 }
1896 break;
1897 case XML_CATA_DELEGATE_URI:
1898 if (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))
1899 haveDelegate++;
1900 break;
1901 case XML_CATA_NEXT_CATALOG:
1902 haveNext++;
1903 break;
1904 default:
1905 break;
1906 }
1907 cur = cur->next;
1908 }
1909 if (rewrite != NULL) {
1910 if (xmlDebugCatalogs)
1912 "Using rewriting rule %s\n", rewrite->name);
1913 ret = xmlStrdup(rewrite->URL);
1914 if (ret != NULL)
1915 ret = xmlStrcat(ret, &URI[lenrewrite]);
1916 return(ret);
1917 }
1918 if (haveDelegate) {
1919 const xmlChar *delegates[MAX_DELEGATE];
1920 int nbList = 0, i;
1921
1922 /*
1923 * Assume the entries have been sorted by decreasing substring
1924 * matches when the list was produced.
1925 */
1926 cur = catal;
1927 while (cur != NULL) {
1928 if (((cur->type == XML_CATA_DELEGATE_SYSTEM) ||
1929 (cur->type == XML_CATA_DELEGATE_URI)) &&
1930 (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))) {
1931 for (i = 0;i < nbList;i++)
1932 if (xmlStrEqual(cur->URL, delegates[i]))
1933 break;
1934 if (i < nbList) {
1935 cur = cur->next;
1936 continue;
1937 }
1938 if (nbList < MAX_DELEGATE)
1939 delegates[nbList++] = cur->URL;
1940
1941 if (cur->children == NULL) {
1942 xmlFetchXMLCatalogFile(cur);
1943 }
1944 if (cur->children != NULL) {
1945 if (xmlDebugCatalogs)
1947 "Trying URI delegate %s\n", cur->URL);
1948 ret = xmlCatalogListXMLResolveURI(
1949 cur->children, URI);
1950 if (ret != NULL)
1951 return(ret);
1952 }
1953 }
1954 cur = cur->next;
1955 }
1956 /*
1957 * Apply the cut algorithm explained in 4/
1958 */
1959 return(XML_CATAL_BREAK);
1960 }
1961 if (haveNext) {
1962 cur = catal;
1963 while (cur != NULL) {
1964 if (cur->type == XML_CATA_NEXT_CATALOG) {
1965 if (cur->children == NULL) {
1966 xmlFetchXMLCatalogFile(cur);
1967 }
1968 if (cur->children != NULL) {
1969 ret = xmlCatalogListXMLResolveURI(cur->children, URI);
1970 if (ret != NULL)
1971 return(ret);
1972 }
1973 }
1974 cur = cur->next;
1975 }
1976 }
1977
1978 return(NULL);
1979}
1980
1995static xmlChar *
1996xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
1997 const xmlChar *sysID) {
1998 xmlChar *ret = NULL;
1999 xmlChar *urnID = NULL;
2000 xmlChar *normid;
2001
2002 if (catal == NULL)
2003 return(NULL);
2004 if ((pubID == NULL) && (sysID == NULL))
2005 return(NULL);
2006
2007 normid = xmlCatalogNormalizePublic(pubID);
2008 if (normid != NULL)
2009 pubID = (*normid != 0 ? normid : NULL);
2010
2011 if (!xmlStrncmp(pubID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2012 urnID = xmlCatalogUnWrapURN(pubID);
2013 if (xmlDebugCatalogs) {
2014 if (urnID == NULL)
2016 "Public URN ID %s expanded to NULL\n", pubID);
2017 else
2019 "Public URN ID expanded to %s\n", urnID);
2020 }
2021 ret = xmlCatalogListXMLResolve(catal, urnID, sysID);
2022 if (urnID != NULL)
2023 xmlFree(urnID);
2024 if (normid != NULL)
2025 xmlFree(normid);
2026 return(ret);
2027 }
2028 if (!xmlStrncmp(sysID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2029 urnID = xmlCatalogUnWrapURN(sysID);
2030 if (xmlDebugCatalogs) {
2031 if (urnID == NULL)
2033 "System URN ID %s expanded to NULL\n", sysID);
2034 else
2036 "System URN ID expanded to %s\n", urnID);
2037 }
2038 if (pubID == NULL)
2039 ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
2040 else if (xmlStrEqual(pubID, urnID))
2041 ret = xmlCatalogListXMLResolve(catal, pubID, NULL);
2042 else {
2043 ret = xmlCatalogListXMLResolve(catal, pubID, urnID);
2044 }
2045 if (urnID != NULL)
2046 xmlFree(urnID);
2047 if (normid != NULL)
2048 xmlFree(normid);
2049 return(ret);
2050 }
2051 while (catal != NULL) {
2052 if (catal->type == XML_CATA_CATALOG) {
2053 if (catal->children == NULL) {
2054 xmlFetchXMLCatalogFile(catal);
2055 }
2056 if (catal->children != NULL) {
2057 ret = xmlCatalogXMLResolve(catal->children, pubID, sysID);
2058 if (ret != NULL) {
2059 break;
2060 } else if (catal->children->depth > MAX_CATAL_DEPTH) {
2061 ret = NULL;
2062 break;
2063 }
2064 }
2065 }
2066 catal = catal->next;
2067 }
2068 if (normid != NULL)
2069 xmlFree(normid);
2070 return(ret);
2071}
2072
2085static xmlChar *
2086xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
2087 xmlChar *ret = NULL;
2088 xmlChar *urnID = NULL;
2089
2090 if (catal == NULL)
2091 return(NULL);
2092 if (URI == NULL)
2093 return(NULL);
2094
2095 if (!xmlStrncmp(URI, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
2096 urnID = xmlCatalogUnWrapURN(URI);
2097 if (xmlDebugCatalogs) {
2098 if (urnID == NULL)
2100 "URN ID %s expanded to NULL\n", URI);
2101 else
2103 "URN ID expanded to %s\n", urnID);
2104 }
2105 ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
2106 if (urnID != NULL)
2107 xmlFree(urnID);
2108 return(ret);
2109 }
2110 while (catal != NULL) {
2111 if (catal->type == XML_CATA_CATALOG) {
2112 if (catal->children == NULL) {
2113 xmlFetchXMLCatalogFile(catal);
2114 }
2115 if (catal->children != NULL) {
2116 ret = xmlCatalogXMLResolveURI(catal->children, URI);
2117 if (ret != NULL)
2118 return(ret);
2119 }
2120 }
2121 catal = catal->next;
2122 }
2123 return(ret);
2124}
2125
2126/************************************************************************
2127 * *
2128 * The SGML Catalog parser *
2129 * *
2130 ************************************************************************/
2131
2132
2133#define RAW *cur
2134#define NEXT cur++;
2135#define SKIP(x) cur += x;
2136
2137#define SKIP_BLANKS while (IS_BLANK_CH(*cur)) NEXT;
2138
2147static const xmlChar *
2148xmlParseSGMLCatalogComment(const xmlChar *cur) {
2149 if ((cur[0] != '-') || (cur[1] != '-'))
2150 return(cur);
2151 SKIP(2);
2152 while ((cur[0] != 0) && ((cur[0] != '-') || ((cur[1] != '-'))))
2153 NEXT;
2154 if (cur[0] == 0) {
2155 return(NULL);
2156 }
2157 return(cur + 2);
2158}
2159
2169static const xmlChar *
2170xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) {
2171 xmlChar *buf = NULL, *tmp;
2172 int len = 0;
2173 int size = 50;
2174 xmlChar stop;
2175
2176 *id = NULL;
2177
2178 if (RAW == '"') {
2179 NEXT;
2180 stop = '"';
2181 } else if (RAW == '\'') {
2182 NEXT;
2183 stop = '\'';
2184 } else {
2185 stop = ' ';
2186 }
2188 if (buf == NULL) {
2189 xmlCatalogErrMemory("allocating public ID");
2190 return(NULL);
2191 }
2192 while (IS_PUBIDCHAR_CH(*cur) || (*cur == '?')) {
2193 if ((*cur == stop) && (stop != ' '))
2194 break;
2195 if ((stop == ' ') && (IS_BLANK_CH(*cur)))
2196 break;
2197 if (len + 1 >= size) {
2198 size *= 2;
2199 tmp = (xmlChar *) xmlRealloc(buf, size);
2200 if (tmp == NULL) {
2201 xmlCatalogErrMemory("allocating public ID");
2202 xmlFree(buf);
2203 return(NULL);
2204 }
2205 buf = tmp;
2206 }
2207 buf[len++] = *cur;
2208 NEXT;
2209 }
2210 buf[len] = 0;
2211 if (stop == ' ') {
2212 if (!IS_BLANK_CH(*cur)) {
2213 xmlFree(buf);
2214 return(NULL);
2215 }
2216 } else {
2217 if (*cur != stop) {
2218 xmlFree(buf);
2219 return(NULL);
2220 }
2221 NEXT;
2222 }
2223 *id = buf;
2224 return(cur);
2225}
2226
2236static const xmlChar *
2237xmlParseSGMLCatalogName(const xmlChar *cur, xmlChar **name) {
2239 int len = 0;
2240 int c;
2241
2242 *name = NULL;
2243
2244 /*
2245 * Handler for more complex cases
2246 */
2247 c = *cur;
2248 if ((!IS_LETTER(c) && (c != '_') && (c != ':'))) {
2249 return(NULL);
2250 }
2251
2252 while (((IS_LETTER(c)) || (IS_DIGIT(c)) ||
2253 (c == '.') || (c == '-') ||
2254 (c == '_') || (c == ':'))) {
2255 buf[len++] = c;
2256 cur++;
2257 c = *cur;
2258 if (len >= XML_MAX_NAMELEN)
2259 return(NULL);
2260 }
2261 *name = xmlStrndup(buf, len);
2262 return(cur);
2263}
2264
2273static xmlCatalogEntryType
2274xmlGetSGMLCatalogEntryType(const xmlChar *name) {
2275 xmlCatalogEntryType type = XML_CATA_NONE;
2276 if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
2277 type = SGML_CATA_SYSTEM;
2278 else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
2279 type = SGML_CATA_PUBLIC;
2280 else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
2281 type = SGML_CATA_DELEGATE;
2282 else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
2283 type = SGML_CATA_ENTITY;
2284 else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
2285 type = SGML_CATA_DOCTYPE;
2286 else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
2287 type = SGML_CATA_LINKTYPE;
2288 else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
2289 type = SGML_CATA_NOTATION;
2290 else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
2291 type = SGML_CATA_SGMLDECL;
2292 else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
2293 type = SGML_CATA_DOCUMENT;
2294 else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
2295 type = SGML_CATA_CATALOG;
2296 else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
2297 type = SGML_CATA_BASE;
2298 return(type);
2299}
2300
2314static int
2315xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value,
2316 const char *file, int super) {
2317 const xmlChar *cur = value;
2318 xmlChar *base = NULL;
2319 int res;
2320
2321 if ((cur == NULL) || (file == NULL))
2322 return(-1);
2323 base = xmlStrdup((const xmlChar *) file);
2324
2325 while ((cur != NULL) && (cur[0] != 0)) {
2327 if (cur[0] == 0)
2328 break;
2329 if ((cur[0] == '-') && (cur[1] == '-')) {
2330 cur = xmlParseSGMLCatalogComment(cur);
2331 if (cur == NULL) {
2332 /* error */
2333 break;
2334 }
2335 } else {
2336 xmlChar *sysid = NULL;
2337 xmlChar *name = NULL;
2338 xmlCatalogEntryType type = XML_CATA_NONE;
2339
2340 cur = xmlParseSGMLCatalogName(cur, &name);
2341 if (cur == NULL || name == NULL) {
2342 /* error */
2343 break;
2344 }
2345 if (!IS_BLANK_CH(*cur)) {
2346 /* error */
2347 xmlFree(name);
2348 break;
2349 }
2351 if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
2352 type = SGML_CATA_SYSTEM;
2353 else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
2354 type = SGML_CATA_PUBLIC;
2355 else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
2356 type = SGML_CATA_DELEGATE;
2357 else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
2358 type = SGML_CATA_ENTITY;
2359 else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
2360 type = SGML_CATA_DOCTYPE;
2361 else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
2362 type = SGML_CATA_LINKTYPE;
2363 else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
2364 type = SGML_CATA_NOTATION;
2365 else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
2366 type = SGML_CATA_SGMLDECL;
2367 else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
2368 type = SGML_CATA_DOCUMENT;
2369 else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
2370 type = SGML_CATA_CATALOG;
2371 else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
2372 type = SGML_CATA_BASE;
2373 else if (xmlStrEqual(name, (const xmlChar *) "OVERRIDE")) {
2374 xmlFree(name);
2375 cur = xmlParseSGMLCatalogName(cur, &name);
2376 if (name == NULL) {
2377 /* error */
2378 break;
2379 }
2380 xmlFree(name);
2381 continue;
2382 }
2383 xmlFree(name);
2384 name = NULL;
2385
2386 switch(type) {
2387 case SGML_CATA_ENTITY:
2388 if (*cur == '%')
2389 type = SGML_CATA_PENTITY;
2390 /* Falls through. */
2391 case SGML_CATA_PENTITY:
2392 case SGML_CATA_DOCTYPE:
2393 case SGML_CATA_LINKTYPE:
2394 case SGML_CATA_NOTATION:
2395 cur = xmlParseSGMLCatalogName(cur, &name);
2396 if (cur == NULL) {
2397 /* error */
2398 break;
2399 }
2400 if (!IS_BLANK_CH(*cur)) {
2401 /* error */
2402 break;
2403 }
2405 cur = xmlParseSGMLCatalogPubid(cur, &sysid);
2406 if (cur == NULL) {
2407 /* error */
2408 break;
2409 }
2410 break;
2411 case SGML_CATA_PUBLIC:
2412 case SGML_CATA_SYSTEM:
2413 case SGML_CATA_DELEGATE:
2414 cur = xmlParseSGMLCatalogPubid(cur, &name);
2415 if (cur == NULL) {
2416 /* error */
2417 break;
2418 }
2419 if (type != SGML_CATA_SYSTEM) {
2420 xmlChar *normid;
2421
2422 normid = xmlCatalogNormalizePublic(name);
2423 if (normid != NULL) {
2424 if (name != NULL)
2425 xmlFree(name);
2426 if (*normid != 0)
2427 name = normid;
2428 else {
2429 xmlFree(normid);
2430 name = NULL;
2431 }
2432 }
2433 }
2434 if (!IS_BLANK_CH(*cur)) {
2435 /* error */
2436 break;
2437 }
2439 cur = xmlParseSGMLCatalogPubid(cur, &sysid);
2440 if (cur == NULL) {
2441 /* error */
2442 break;
2443 }
2444 break;
2445 case SGML_CATA_BASE:
2446 case SGML_CATA_CATALOG:
2447 case SGML_CATA_DOCUMENT:
2448 case SGML_CATA_SGMLDECL:
2449 cur = xmlParseSGMLCatalogPubid(cur, &sysid);
2450 if (cur == NULL) {
2451 /* error */
2452 break;
2453 }
2454 break;
2455 default:
2456 break;
2457 }
2458 if (cur == NULL) {
2459 if (name != NULL)
2460 xmlFree(name);
2461 if (sysid != NULL)
2462 xmlFree(sysid);
2463 break;
2464 } else if (type == SGML_CATA_BASE) {
2465 if (base != NULL)
2466 xmlFree(base);
2467 base = xmlStrdup(sysid);
2468 } else if ((type == SGML_CATA_PUBLIC) ||
2469 (type == SGML_CATA_SYSTEM)) {
2471
2472 filename = xmlBuildURI(sysid, base);
2473 if (filename != NULL) {
2474 xmlCatalogEntryPtr entry;
2475
2476 entry = xmlNewCatalogEntry(type, name, filename,
2477 NULL, XML_CATA_PREFER_NONE, NULL);
2478 res = xmlHashAddEntry(catal->sgml, name, entry);
2479 if (res < 0) {
2480 xmlFreeCatalogEntry(entry, NULL);
2481 }
2483 }
2484
2485 } else if (type == SGML_CATA_CATALOG) {
2486 if (super) {
2487 xmlCatalogEntryPtr entry;
2488
2489 entry = xmlNewCatalogEntry(type, sysid, NULL, NULL,
2490 XML_CATA_PREFER_NONE, NULL);
2491 res = xmlHashAddEntry(catal->sgml, sysid, entry);
2492 if (res < 0) {
2493 xmlFreeCatalogEntry(entry, NULL);
2494 }
2495 } else {
2497
2498 filename = xmlBuildURI(sysid, base);
2499 if (filename != NULL) {
2500 xmlExpandCatalog(catal, (const char *)filename);
2502 }
2503 }
2504 }
2505 /*
2506 * drop anything else we won't handle it
2507 */
2508 if (name != NULL)
2509 xmlFree(name);
2510 if (sysid != NULL)
2511 xmlFree(sysid);
2512 }
2513 }
2514 if (base != NULL)
2515 xmlFree(base);
2516 if (cur == NULL)
2517 return(-1);
2518 return(0);
2519}
2520
2521/************************************************************************
2522 * *
2523 * SGML Catalog handling *
2524 * *
2525 ************************************************************************/
2526
2536static const xmlChar *
2537xmlCatalogGetSGMLPublic(xmlHashTablePtr catal, const xmlChar *pubID) {
2538 xmlCatalogEntryPtr entry;
2539 xmlChar *normid;
2540
2541 if (catal == NULL)
2542 return(NULL);
2543
2544 normid = xmlCatalogNormalizePublic(pubID);
2545 if (normid != NULL)
2546 pubID = (*normid != 0 ? normid : NULL);
2547
2548 entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, pubID);
2549 if (entry == NULL) {
2550 if (normid != NULL)
2551 xmlFree(normid);
2552 return(NULL);
2553 }
2554 if (entry->type == SGML_CATA_PUBLIC) {
2555 if (normid != NULL)
2556 xmlFree(normid);
2557 return(entry->URL);
2558 }
2559 if (normid != NULL)
2560 xmlFree(normid);
2561 return(NULL);
2562}
2563
2573static const xmlChar *
2574xmlCatalogGetSGMLSystem(xmlHashTablePtr catal, const xmlChar *sysID) {
2575 xmlCatalogEntryPtr entry;
2576
2577 if (catal == NULL)
2578 return(NULL);
2579
2580 entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, sysID);
2581 if (entry == NULL)
2582 return(NULL);
2583 if (entry->type == SGML_CATA_SYSTEM)
2584 return(entry->URL);
2585 return(NULL);
2586}
2587
2598static const xmlChar *
2599xmlCatalogSGMLResolve(xmlCatalogPtr catal, const xmlChar *pubID,
2600 const xmlChar *sysID) {
2601 const xmlChar *ret = NULL;
2602
2603 if (catal->sgml == NULL)
2604 return(NULL);
2605
2606 if (pubID != NULL)
2607 ret = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
2608 if (ret != NULL)
2609 return(ret);
2610 if (sysID != NULL)
2611 ret = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
2612 if (ret != NULL)
2613 return(ret);
2614 return(NULL);
2615}
2616
2617/************************************************************************
2618 * *
2619 * Specific Public interfaces *
2620 * *
2621 ************************************************************************/
2622
2633xmlCatalogPtr
2634xmlLoadSGMLSuperCatalog(const char *filename)
2635{
2637 xmlCatalogPtr catal;
2638 int ret;
2639
2640 content = xmlLoadFileContent(filename);
2641 if (content == NULL)
2642 return(NULL);
2643
2644 catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
2645 if (catal == NULL) {
2647 return(NULL);
2648 }
2649
2650 ret = xmlParseSGMLCatalog(catal, content, filename, 1);
2652 if (ret < 0) {
2653 xmlFreeCatalog(catal);
2654 return(NULL);
2655 }
2656 return (catal);
2657}
2658
2670xmlCatalogPtr
2671xmlLoadACatalog(const char *filename)
2672{
2674 xmlChar *first;
2675 xmlCatalogPtr catal;
2676 int ret;
2677
2678 content = xmlLoadFileContent(filename);
2679 if (content == NULL)
2680 return(NULL);
2681
2682
2683 first = content;
2684
2685 while ((*first != 0) && (*first != '-') && (*first != '<') &&
2686 (!(((*first >= 'A') && (*first <= 'Z')) ||
2687 ((*first >= 'a') && (*first <= 'z')))))
2688 first++;
2689
2690 if (*first != '<') {
2691 catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
2692 if (catal == NULL) {
2694 return(NULL);
2695 }
2696 ret = xmlParseSGMLCatalog(catal, content, filename, 0);
2697 if (ret < 0) {
2698 xmlFreeCatalog(catal);
2700 return(NULL);
2701 }
2702 } else {
2703 catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
2704 if (catal == NULL) {
2706 return(NULL);
2707 }
2708 catal->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
2709 NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
2710 }
2712 return (catal);
2713}
2714
2725static int
2726xmlExpandCatalog(xmlCatalogPtr catal, const char *filename)
2727{
2728 int ret;
2729
2730 if ((catal == NULL) || (filename == NULL))
2731 return(-1);
2732
2733
2734 if (catal->type == XML_SGML_CATALOG_TYPE) {
2736
2737 content = xmlLoadFileContent(filename);
2738 if (content == NULL)
2739 return(-1);
2740
2741 ret = xmlParseSGMLCatalog(catal, content, filename, 0);
2742 if (ret < 0) {
2744 return(-1);
2745 }
2747 } else {
2748 xmlCatalogEntryPtr tmp, cur;
2749 tmp = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
2750 NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
2751
2752 cur = catal->xml;
2753 if (cur == NULL) {
2754 catal->xml = tmp;
2755 } else {
2756 while (cur->next != NULL) cur = cur->next;
2757 cur->next = tmp;
2758 }
2759 }
2760 return (0);
2761}
2762
2773xmlChar *
2774xmlACatalogResolveSystem(xmlCatalogPtr catal, const xmlChar *sysID) {
2775 xmlChar *ret = NULL;
2776
2777 if ((sysID == NULL) || (catal == NULL))
2778 return(NULL);
2779
2780 if (xmlDebugCatalogs)
2782 "Resolve sysID %s\n", sysID);
2783
2784 if (catal->type == XML_XML_CATALOG_TYPE) {
2785 ret = xmlCatalogListXMLResolve(catal->xml, NULL, sysID);
2786 if (ret == XML_CATAL_BREAK)
2787 ret = NULL;
2788 } else {
2789 const xmlChar *sgml;
2790
2791 sgml = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
2792 if (sgml != NULL)
2793 ret = xmlStrdup(sgml);
2794 }
2795 return(ret);
2796}
2797
2808xmlChar *
2809xmlACatalogResolvePublic(xmlCatalogPtr catal, const xmlChar *pubID) {
2810 xmlChar *ret = NULL;
2811
2812 if ((pubID == NULL) || (catal == NULL))
2813 return(NULL);
2814
2815 if (xmlDebugCatalogs)
2817 "Resolve pubID %s\n", pubID);
2818
2819 if (catal->type == XML_XML_CATALOG_TYPE) {
2820 ret = xmlCatalogListXMLResolve(catal->xml, pubID, NULL);
2821 if (ret == XML_CATAL_BREAK)
2822 ret = NULL;
2823 } else {
2824 const xmlChar *sgml;
2825
2826 sgml = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
2827 if (sgml != NULL)
2828 ret = xmlStrdup(sgml);
2829 }
2830 return(ret);
2831}
2832
2844xmlChar *
2845xmlACatalogResolve(xmlCatalogPtr catal, const xmlChar * pubID,
2846 const xmlChar * sysID)
2847{
2848 xmlChar *ret = NULL;
2849
2850 if (((pubID == NULL) && (sysID == NULL)) || (catal == NULL))
2851 return (NULL);
2852
2853 if (xmlDebugCatalogs) {
2854 if ((pubID != NULL) && (sysID != NULL)) {
2856 "Resolve: pubID %s sysID %s\n", pubID, sysID);
2857 } else if (pubID != NULL) {
2859 "Resolve: pubID %s\n", pubID);
2860 } else {
2862 "Resolve: sysID %s\n", sysID);
2863 }
2864 }
2865
2866 if (catal->type == XML_XML_CATALOG_TYPE) {
2867 ret = xmlCatalogListXMLResolve(catal->xml, pubID, sysID);
2868 if (ret == XML_CATAL_BREAK)
2869 ret = NULL;
2870 } else {
2871 const xmlChar *sgml;
2872
2873 sgml = xmlCatalogSGMLResolve(catal, pubID, sysID);
2874 if (sgml != NULL)
2875 ret = xmlStrdup(sgml);
2876 }
2877 return (ret);
2878}
2879
2890xmlChar *
2891xmlACatalogResolveURI(xmlCatalogPtr catal, const xmlChar *URI) {
2892 xmlChar *ret = NULL;
2893
2894 if ((URI == NULL) || (catal == NULL))
2895 return(NULL);
2896
2897 if (xmlDebugCatalogs)
2899 "Resolve URI %s\n", URI);
2900
2901 if (catal->type == XML_XML_CATALOG_TYPE) {
2902 ret = xmlCatalogListXMLResolveURI(catal->xml, URI);
2903 if (ret == XML_CATAL_BREAK)
2904 ret = NULL;
2905 } else {
2906 const xmlChar *sgml;
2907
2908 sgml = xmlCatalogSGMLResolve(catal, NULL, URI);
2909 if (sgml != NULL)
2910 ret = xmlStrdup(sgml);
2911 }
2912 return(ret);
2913}
2914
2915#ifdef LIBXML_OUTPUT_ENABLED
2923void
2924xmlACatalogDump(xmlCatalogPtr catal, FILE *out) {
2925 if ((out == NULL) || (catal == NULL))
2926 return;
2927
2928 if (catal->type == XML_XML_CATALOG_TYPE) {
2929 xmlDumpXMLCatalog(out, catal->xml);
2930 } else {
2931 xmlHashScan(catal->sgml, xmlCatalogDumpEntry, out);
2932 }
2933}
2934#endif /* LIBXML_OUTPUT_ENABLED */
2935
2948int
2949xmlACatalogAdd(xmlCatalogPtr catal, const xmlChar * type,
2950 const xmlChar * orig, const xmlChar * replace)
2951{
2952 int res = -1;
2953
2954 if (catal == NULL)
2955 return(-1);
2956
2957 if (catal->type == XML_XML_CATALOG_TYPE) {
2958 res = xmlAddXMLCatalog(catal->xml, type, orig, replace);
2959 } else {
2960 xmlCatalogEntryType cattype;
2961
2962 cattype = xmlGetSGMLCatalogEntryType(type);
2963 if (cattype != XML_CATA_NONE) {
2964 xmlCatalogEntryPtr entry;
2965
2966 entry = xmlNewCatalogEntry(cattype, orig, replace, NULL,
2967 XML_CATA_PREFER_NONE, NULL);
2968 if (catal->sgml == NULL)
2969 catal->sgml = xmlHashCreate(10);
2970 res = xmlHashAddEntry(catal->sgml, orig, entry);
2971 if (res < 0)
2972 xmlFreeCatalogEntry(entry, NULL);
2973 }
2974 }
2975 return (res);
2976}
2977
2987int
2988xmlACatalogRemove(xmlCatalogPtr catal, const xmlChar *value) {
2989 int res = -1;
2990
2991 if ((catal == NULL) || (value == NULL))
2992 return(-1);
2993
2994 if (catal->type == XML_XML_CATALOG_TYPE) {
2995 res = xmlDelXMLCatalog(catal->xml, value);
2996 } else {
2997 res = xmlHashRemoveEntry(catal->sgml, value, xmlFreeCatalogEntry);
2998 if (res == 0)
2999 res = 1;
3000 }
3001 return(res);
3002}
3003
3012xmlCatalogPtr
3013xmlNewCatalog(int sgml) {
3014 xmlCatalogPtr catal = NULL;
3015
3016 if (sgml) {
3017 catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE,
3018 xmlCatalogDefaultPrefer);
3019 if ((catal != NULL) && (catal->sgml == NULL))
3020 catal->sgml = xmlHashCreate(10);
3021 } else
3022 catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3023 xmlCatalogDefaultPrefer);
3024 return(catal);
3025}
3026
3035int
3036xmlCatalogIsEmpty(xmlCatalogPtr catal) {
3037 if (catal == NULL)
3038 return(-1);
3039
3040 if (catal->type == XML_XML_CATALOG_TYPE) {
3041 if (catal->xml == NULL)
3042 return(1);
3043 if ((catal->xml->type != XML_CATA_CATALOG) &&
3044 (catal->xml->type != XML_CATA_BROKEN_CATALOG))
3045 return(-1);
3046 if (catal->xml->children == NULL)
3047 return(1);
3048 return(0);
3049 } else {
3050 int res;
3051
3052 if (catal->sgml == NULL)
3053 return(1);
3054 res = xmlHashSize(catal->sgml);
3055 if (res == 0)
3056 return(1);
3057 if (res < 0)
3058 return(-1);
3059 }
3060 return(0);
3061}
3062
3063/************************************************************************
3064 * *
3065 * Public interfaces manipulating the global shared default catalog *
3066 * *
3067 ************************************************************************/
3068
3077static void
3078xmlInitializeCatalogData(void) {
3079 if (xmlCatalogInitialized != 0)
3080 return;
3081
3082 if (getenv("XML_DEBUG_CATALOG"))
3083 xmlDebugCatalogs = 1;
3084 xmlCatalogMutex = xmlNewRMutex();
3085
3086 xmlCatalogInitialized = 1;
3087}
3095void
3096xmlInitializeCatalog(void) {
3097 if (xmlCatalogInitialized != 0)
3098 return;
3099
3100 xmlInitializeCatalogData();
3101 xmlRMutexLock(xmlCatalogMutex);
3102
3103 if (getenv("XML_DEBUG_CATALOG"))
3104 xmlDebugCatalogs = 1;
3105
3106 if (xmlDefaultCatalog == NULL) {
3107 const char *catalogs;
3108 char *path;
3109 const char *cur, *paths;
3110 xmlCatalogPtr catal;
3111 xmlCatalogEntryPtr *nextent;
3112
3113 catalogs = (const char *) getenv("XML_CATALOG_FILES");
3114 if (catalogs == NULL)
3115#if defined(_WIN32) && defined(_MSC_VER)
3116 {
3117 void* hmodule;
3118 hmodule = GetModuleHandleA("libxml2.dll");
3119 if (hmodule == NULL)
3121 if (hmodule != NULL) {
3122 char buf[256];
3123 unsigned long len = GetModuleFileNameA(hmodule, buf, 255);
3124 if (len != 0) {
3125 char* p = &(buf[len]);
3126 while (*p != '\\' && p > buf)
3127 p--;
3128 if (p != buf) {
3129 xmlChar* uri;
3130 strncpy(p, "\\..\\etc\\catalog", 255 - (p - buf));
3131 uri = xmlCanonicPath((const xmlChar*)buf);
3132 if (uri != NULL) {
3133 strncpy(XML_XML_DEFAULT_CATALOG, (char* )uri, 255);
3134 xmlFree(uri);
3135 }
3136 }
3137 }
3138 }
3139 catalogs = XML_XML_DEFAULT_CATALOG;
3140 }
3141#else
3142 catalogs = XML_XML_DEFAULT_CATALOG;
3143#endif
3144
3145 catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3146 xmlCatalogDefaultPrefer);
3147 if (catal != NULL) {
3148 /* the XML_CATALOG_FILES envvar is allowed to contain a
3149 space-separated list of entries. */
3150 cur = catalogs;
3151 nextent = &catal->xml;
3152 while (*cur != '\0') {
3153 while (xmlIsBlank_ch(*cur))
3154 cur++;
3155 if (*cur != 0) {
3156 paths = cur;
3157 while ((*cur != 0) && (!xmlIsBlank_ch(*cur)))
3158 cur++;
3159 path = (char *) xmlStrndup((const xmlChar *)paths, cur - paths);
3160 if (path != NULL) {
3161 *nextent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
3162 NULL, BAD_CAST path, xmlCatalogDefaultPrefer, NULL);
3163 if (*nextent != NULL)
3164 nextent = &((*nextent)->next);
3165 xmlFree(path);
3166 }
3167 }
3168 }
3169 xmlDefaultCatalog = catal;
3170 }
3171 }
3172
3173 xmlRMutexUnlock(xmlCatalogMutex);
3174}
3175
3176
3188int
3189xmlLoadCatalog(const char *filename)
3190{
3191 int ret;
3192 xmlCatalogPtr catal;
3193
3194 if (!xmlCatalogInitialized)
3195 xmlInitializeCatalogData();
3196
3197 xmlRMutexLock(xmlCatalogMutex);
3198
3199 if (xmlDefaultCatalog == NULL) {
3200 catal = xmlLoadACatalog(filename);
3201 if (catal == NULL) {
3202 xmlRMutexUnlock(xmlCatalogMutex);
3203 return(-1);
3204 }
3205
3206 xmlDefaultCatalog = catal;
3207 xmlRMutexUnlock(xmlCatalogMutex);
3208 return(0);
3209 }
3210
3211 ret = xmlExpandCatalog(xmlDefaultCatalog, filename);
3212 xmlRMutexUnlock(xmlCatalogMutex);
3213 return(ret);
3214}
3215
3225void
3226xmlLoadCatalogs(const char *pathss) {
3227 const char *cur;
3228 const char *paths;
3229 xmlChar *path;
3230#ifdef _WIN32
3231 int i, iLen;
3232#endif
3233
3234 if (pathss == NULL)
3235 return;
3236
3237 cur = pathss;
3238 while (*cur != 0) {
3239 while (xmlIsBlank_ch(*cur)) cur++;
3240 if (*cur != 0) {
3241 paths = cur;
3242 while ((*cur != 0) && (*cur != PATH_SEPARATOR) && (!xmlIsBlank_ch(*cur)))
3243 cur++;
3244 path = xmlStrndup((const xmlChar *)paths, cur - paths);
3245 if (path != NULL) {
3246#ifdef _WIN32
3247 iLen = strlen((const char*)path);
3248 for(i = 0; i < iLen; i++) {
3249 if(path[i] == '\\') {
3250 path[i] = '/';
3251 }
3252 }
3253#endif
3254 xmlLoadCatalog((const char *) path);
3255 xmlFree(path);
3256 }
3257 }
3258 while (*cur == PATH_SEPARATOR)
3259 cur++;
3260 }
3261}
3262
3268void
3269xmlCatalogCleanup(void) {
3270 if (xmlCatalogInitialized == 0)
3271 return;
3272
3273 xmlRMutexLock(xmlCatalogMutex);
3274 if (xmlDebugCatalogs)
3276 "Catalogs cleanup\n");
3277 if (xmlCatalogXMLFiles != NULL)
3278 xmlHashFree(xmlCatalogXMLFiles, xmlFreeCatalogHashEntryList);
3279 xmlCatalogXMLFiles = NULL;
3280 if (xmlDefaultCatalog != NULL)
3281 xmlFreeCatalog(xmlDefaultCatalog);
3282 xmlDefaultCatalog = NULL;
3283 xmlDebugCatalogs = 0;
3284 xmlCatalogInitialized = 0;
3285 xmlRMutexUnlock(xmlCatalogMutex);
3286 xmlFreeRMutex(xmlCatalogMutex);
3287}
3288
3298xmlChar *
3299xmlCatalogResolveSystem(const xmlChar *sysID) {
3300 xmlChar *ret;
3301
3302 if (!xmlCatalogInitialized)
3303 xmlInitializeCatalog();
3304
3305 ret = xmlACatalogResolveSystem(xmlDefaultCatalog, sysID);
3306 return(ret);
3307}
3308
3318xmlChar *
3319xmlCatalogResolvePublic(const xmlChar *pubID) {
3320 xmlChar *ret;
3321
3322 if (!xmlCatalogInitialized)
3323 xmlInitializeCatalog();
3324
3325 ret = xmlACatalogResolvePublic(xmlDefaultCatalog, pubID);
3326 return(ret);
3327}
3328
3339xmlChar *
3340xmlCatalogResolve(const xmlChar *pubID, const xmlChar *sysID) {
3341 xmlChar *ret;
3342
3343 if (!xmlCatalogInitialized)
3344 xmlInitializeCatalog();
3345
3346 ret = xmlACatalogResolve(xmlDefaultCatalog, pubID, sysID);
3347 return(ret);
3348}
3349
3359xmlChar *
3360xmlCatalogResolveURI(const xmlChar *URI) {
3361 xmlChar *ret;
3362
3363 if (!xmlCatalogInitialized)
3364 xmlInitializeCatalog();
3365
3366 ret = xmlACatalogResolveURI(xmlDefaultCatalog, URI);
3367 return(ret);
3368}
3369
3370#ifdef LIBXML_OUTPUT_ENABLED
3377void
3378xmlCatalogDump(FILE *out) {
3379 if (out == NULL)
3380 return;
3381
3382 if (!xmlCatalogInitialized)
3383 xmlInitializeCatalog();
3384
3385 xmlACatalogDump(xmlDefaultCatalog, out);
3386}
3387#endif /* LIBXML_OUTPUT_ENABLED */
3388
3402int
3403xmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace) {
3404 int res = -1;
3405
3406 if (!xmlCatalogInitialized)
3407 xmlInitializeCatalogData();
3408
3409 xmlRMutexLock(xmlCatalogMutex);
3410 /*
3411 * Specific case where one want to override the default catalog
3412 * put in place by xmlInitializeCatalog();
3413 */
3414 if ((xmlDefaultCatalog == NULL) &&
3415 (xmlStrEqual(type, BAD_CAST "catalog"))) {
3416 xmlDefaultCatalog = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
3417 xmlCatalogDefaultPrefer);
3418 if (xmlDefaultCatalog != NULL) {
3419 xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
3420 orig, NULL, xmlCatalogDefaultPrefer, NULL);
3421 }
3422 xmlRMutexUnlock(xmlCatalogMutex);
3423 return(0);
3424 }
3425
3426 res = xmlACatalogAdd(xmlDefaultCatalog, type, orig, replace);
3427 xmlRMutexUnlock(xmlCatalogMutex);
3428 return(res);
3429}
3430
3439int
3440xmlCatalogRemove(const xmlChar *value) {
3441 int res;
3442
3443 if (!xmlCatalogInitialized)
3444 xmlInitializeCatalog();
3445
3446 xmlRMutexLock(xmlCatalogMutex);
3447 res = xmlACatalogRemove(xmlDefaultCatalog, value);
3448 xmlRMutexUnlock(xmlCatalogMutex);
3449 return(res);
3450}
3451
3459int
3460xmlCatalogConvert(void) {
3461 int res = -1;
3462
3463 if (!xmlCatalogInitialized)
3464 xmlInitializeCatalog();
3465
3466 xmlRMutexLock(xmlCatalogMutex);
3467 res = xmlConvertSGMLCatalog(xmlDefaultCatalog);
3468 xmlRMutexUnlock(xmlCatalogMutex);
3469 return(res);
3470}
3471
3472/************************************************************************
3473 * *
3474 * Public interface manipulating the common preferences *
3475 * *
3476 ************************************************************************/
3477
3486xmlCatalogAllow
3487xmlCatalogGetDefaults(void) {
3488 return(xmlCatalogDefaultAllow);
3489}
3490
3498void
3499xmlCatalogSetDefaults(xmlCatalogAllow allow) {
3500 if (xmlDebugCatalogs) {
3501 switch (allow) {
3502 case XML_CATA_ALLOW_NONE:
3504 "Disabling catalog usage\n");
3505 break;
3506 case XML_CATA_ALLOW_GLOBAL:
3508 "Allowing only global catalogs\n");
3509 break;
3510 case XML_CATA_ALLOW_DOCUMENT:
3512 "Allowing only catalogs from the document\n");
3513 break;
3514 case XML_CATA_ALLOW_ALL:
3516 "Allowing all catalogs\n");
3517 break;
3518 }
3519 }
3520 xmlCatalogDefaultAllow = allow;
3521}
3522
3533xmlCatalogPrefer
3534xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer) {
3535 xmlCatalogPrefer ret = xmlCatalogDefaultPrefer;
3536
3537 if (prefer == XML_CATA_PREFER_NONE)
3538 return(ret);
3539
3540 if (xmlDebugCatalogs) {
3541 switch (prefer) {
3542 case XML_CATA_PREFER_PUBLIC:
3544 "Setting catalog preference to PUBLIC\n");
3545 break;
3546 case XML_CATA_PREFER_SYSTEM:
3548 "Setting catalog preference to SYSTEM\n");
3549 break;
3550 default:
3551 return(ret);
3552 }
3553 }
3554 xmlCatalogDefaultPrefer = prefer;
3555 return(ret);
3556}
3557
3567int
3568xmlCatalogSetDebug(int level) {
3569 int ret = xmlDebugCatalogs;
3570
3571 if (level <= 0)
3572 xmlDebugCatalogs = 0;
3573 else
3574 xmlDebugCatalogs = level;
3575 return(ret);
3576}
3577
3578/************************************************************************
3579 * *
3580 * Minimal interfaces used for per-document catalogs by the parser *
3581 * *
3582 ************************************************************************/
3583
3590void
3591xmlCatalogFreeLocal(void *catalogs) {
3592 xmlCatalogEntryPtr catal;
3593
3594 if (!xmlCatalogInitialized)
3595 xmlInitializeCatalog();
3596
3597 catal = (xmlCatalogEntryPtr) catalogs;
3598 if (catal != NULL)
3599 xmlFreeCatalogEntryList(catal);
3600}
3601
3602
3612void *
3613xmlCatalogAddLocal(void *catalogs, const xmlChar *URL) {
3614 xmlCatalogEntryPtr catal, add;
3615
3616 if (!xmlCatalogInitialized)
3617 xmlInitializeCatalog();
3618
3619 if (URL == NULL)
3620 return(catalogs);
3621
3622 if (xmlDebugCatalogs)
3624 "Adding document catalog %s\n", URL);
3625
3626 add = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, URL, NULL,
3627 xmlCatalogDefaultPrefer, NULL);
3628 if (add == NULL)
3629 return(catalogs);
3630
3631 catal = (xmlCatalogEntryPtr) catalogs;
3632 if (catal == NULL)
3633 return((void *) add);
3634
3635 while (catal->next != NULL)
3636 catal = catal->next;
3637 catal->next = add;
3638 return(catalogs);
3639}
3640
3653xmlChar *
3654xmlCatalogLocalResolve(void *catalogs, const xmlChar *pubID,
3655 const xmlChar *sysID) {
3656 xmlCatalogEntryPtr catal;
3657 xmlChar *ret;
3658
3659 if (!xmlCatalogInitialized)
3660 xmlInitializeCatalog();
3661
3662 if ((pubID == NULL) && (sysID == NULL))
3663 return(NULL);
3664
3665 if (xmlDebugCatalogs) {
3666 if ((pubID != NULL) && (sysID != NULL)) {
3668 "Local Resolve: pubID %s sysID %s\n", pubID, sysID);
3669 } else if (pubID != NULL) {
3671 "Local Resolve: pubID %s\n", pubID);
3672 } else {
3674 "Local Resolve: sysID %s\n", sysID);
3675 }
3676 }
3677
3678 catal = (xmlCatalogEntryPtr) catalogs;
3679 if (catal == NULL)
3680 return(NULL);
3681 ret = xmlCatalogListXMLResolve(catal, pubID, sysID);
3682 if ((ret != NULL) && (ret != XML_CATAL_BREAK))
3683 return(ret);
3684 return(NULL);
3685}
3686
3698xmlChar *
3699xmlCatalogLocalResolveURI(void *catalogs, const xmlChar *URI) {
3700 xmlCatalogEntryPtr catal;
3701 xmlChar *ret;
3702
3703 if (!xmlCatalogInitialized)
3704 xmlInitializeCatalog();
3705
3706 if (URI == NULL)
3707 return(NULL);
3708
3709 if (xmlDebugCatalogs)
3711 "Resolve URI %s\n", URI);
3712
3713 catal = (xmlCatalogEntryPtr) catalogs;
3714 if (catal == NULL)
3715 return(NULL);
3716 ret = xmlCatalogListXMLResolveURI(catal, URI);
3717 if ((ret != NULL) && (ret != XML_CATAL_BREAK))
3718 return(ret);
3719 return(NULL);
3720}
3721
3722/************************************************************************
3723 * *
3724 * Deprecated interfaces *
3725 * *
3726 ************************************************************************/
3736const xmlChar *
3737xmlCatalogGetSystem(const xmlChar *sysID) {
3738 xmlChar *ret;
3739 static xmlChar result[1000];
3740 static int msg = 0;
3741
3742 if (!xmlCatalogInitialized)
3743 xmlInitializeCatalog();
3744
3745 if (msg == 0) {
3747 "Use of deprecated xmlCatalogGetSystem() call\n");
3748 msg++;
3749 }
3750
3751 if (sysID == NULL)
3752 return(NULL);
3753
3754 /*
3755 * Check first the XML catalogs
3756 */
3757 if (xmlDefaultCatalog != NULL) {
3758 ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, NULL, sysID);
3759 if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
3760 snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
3761 result[sizeof(result) - 1] = 0;
3762 return(result);
3763 }
3764 }
3765
3766 if (xmlDefaultCatalog != NULL)
3767 return(xmlCatalogGetSGMLSystem(xmlDefaultCatalog->sgml, sysID));
3768 return(NULL);
3769}
3770
3780const xmlChar *
3781xmlCatalogGetPublic(const xmlChar *pubID) {
3782 xmlChar *ret;
3783 static xmlChar result[1000];
3784 static int msg = 0;
3785
3786 if (!xmlCatalogInitialized)
3787 xmlInitializeCatalog();
3788
3789 if (msg == 0) {
3791 "Use of deprecated xmlCatalogGetPublic() call\n");
3792 msg++;
3793 }
3794
3795 if (pubID == NULL)
3796 return(NULL);
3797
3798 /*
3799 * Check first the XML catalogs
3800 */
3801 if (xmlDefaultCatalog != NULL) {
3802 ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, pubID, NULL);
3803 if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
3804 snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
3805 result[sizeof(result) - 1] = 0;
3806 return(result);
3807 }
3808 }
3809
3810 if (xmlDefaultCatalog != NULL)
3811 return(xmlCatalogGetSGMLPublic(xmlDefaultCatalog->sgml, pubID));
3812 return(NULL);
3813}
3814
3815#endif /* LIBXML_CATALOG_ENABLED */
#define stat
Definition: acwin.h:99
#define read
Definition: acwin.h:96
#define close
Definition: acwin.h:98
#define ok(value,...)
Definition: atltest.h:57
#define msg(x)
Definition: auth_time.c:54
int xmlBufResetInput(xmlBufPtr buf, xmlParserInputPtr input)
Definition: buf.c:1019
#define SEEK_END
Definition: cabinet.c:29
#define xmlIsBlank_ch(c)
Definition: chvalid.h:88
#define NULL
Definition: types.h:112
#define SKIP_BLANKS
Definition: pattern.c:1186
#define SKIP(val)
Definition: pattern.c:1182
content
Definition: atl_ax.c:994
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:539
char *CDECL getenv(const char *name)
Definition: environ.c:227
__msvcrt_long CDECL ftell(FILE *file)
Definition: file.c:4740
int CDECL fclose(FILE *file)
Definition: file.c:3757
int CDECL fseek(FILE *file, __msvcrt_long offset, int whence)
Definition: file.c:1610
int WINAPIV fprintf(FILE *file, const char *format,...)
Definition: file.c:5549
size_t CDECL fread(void *ptr, size_t size, size_t nmemb, FILE *file)
Definition: file.c:4406
FILE *CDECL fopen(const char *path, const char *mode)
Definition: file.c:4310
#define __stdcall
Definition: corecrt.h:120
#define O_RDONLY
Definition: fcntl.h:34
#define open
Definition: io.h:44
#define EOF
Definition: stdio.h:33
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
return ret
Definition: mutex.c:146
r parent
Definition: btrfs.c:3010
void dealloc(int i, int no_throw)
Definition: ehthrow.cxx:33
@ XML_CHAR_ENCODING_NONE
Definition: encoding.h:67
#define NEXT(n, i)
FxCollectionEntry * cur
#define RAW(x)
Definition: genincdata.c:42
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLint level
Definition: gl.h:1546
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLuint res
Definition: glext.h:9613
GLsizeiptr size
Definition: glext.h:5919
const GLubyte * c
Definition: glext.h:8905
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLboolean GLuint group
Definition: glext.h:11120
const GLint * first
Definition: glext.h:5794
GLuint64EXT * result
Definition: glext.h:11304
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLsizei const GLuint * paths
Definition: glext.h:11717
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ATTRIBUTE_UNUSED
Definition: i386-dis.c:36
@ extra
Definition: id3.c:95
const char * filename
Definition: ioapi.h:137
uint32_t entry
Definition: isohybrid.c:63
#define SEEK_SET
Definition: jmemansi.c:26
#define c
Definition: ke_i.h:80
XMLPUBFUN void xmlFreeRMutex(xmlRMutexPtr tok)
Definition: threads.c:275
XML_DEPRECATED XMLPUBFUN int xmlGetThreadId(void)
Definition: threads.c:372
XMLPUBFUN void xmlRMutexLock(xmlRMutexPtr tok)
Definition: threads.c:297
XMLPUBFUN xmlRMutexPtr xmlNewRMutex(void)
Definition: threads.c:248
XMLPUBFUN void xmlRMutexUnlock(xmlRMutexPtr tok)
Definition: threads.c:333
#define SYSCONFDIR
Definition: libxml.h:38
#define error(str)
Definition: mkdosfs.c:1605
#define PATH_SEPARATOR
Definition: mkisofs.h:786
static HMODULE hmodule
Definition: rasapi.c:29
const char * uri
Definition: sec_mgr.c:1588
__forceinline bool __cdecl add(big_integer &x, uint32_t const value)
#define XML_MAX_NAMELEN
#define IS_DIGIT(c)
#define IS_PUBIDCHAR_CH(c)
#define IS_LETTER(c)
XMLPUBFUN xmlParserInputPtr xmlNewInputStream(xmlParserCtxtPtr ctxt)
XMLPUBFUN int inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
Definition: parser.c:1897
#define IS_BLANK_CH(c)
static unsigned __int64 next
Definition: rand_nt.c:6
INT replace(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], DWORD dwFlags, BOOL *doMore)
Definition: replace.c:38
strncpy
Definition: string.h:335
void * xmlGenericErrorContext
Definition: globals.c:410
xmlReallocFunc xmlRealloc
Definition: globals.c:214
xmlFreeFunc xmlFree
Definition: globals.c:184
xmlGenericErrorFunc xmlGenericError
Definition: globals.c:396
xmlMallocFunc xmlMalloc
Definition: globals.c:193
xmlMallocFunc xmlMallocAtomic
Definition: globals.c:204
void xmlHashScan(xmlHashTablePtr hash, xmlHashScanner scan, void *data)
Definition: hash.c:898
void xmlHashFree(xmlHashTablePtr hash, xmlHashDeallocator dealloc)
Definition: hash.c:229
void * xmlHashLookup(xmlHashTablePtr hash, const xmlChar *key)
Definition: hash.c:739
int xmlHashRemoveEntry(xmlHashTablePtr hash, const xmlChar *key, xmlHashDeallocator dealloc)
Definition: hash.c:1102
int xmlHashSize(xmlHashTablePtr hash)
Definition: hash.c:1085
int xmlHashAddEntry(xmlHashTablePtr hash, const xmlChar *key, void *payload)
Definition: hash.c:621
xmlHashTablePtr xmlHashCreate(int size)
Definition: hash.c:160
XMLPUBFUN int xmlParseDocument(xmlParserCtxtPtr ctxt)
Definition: parser.c:11009
XMLPUBFUN void xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
XMLPUBFUN xmlParserCtxtPtr xmlNewParserCtxt(void)
XML_HIDDEN void __xmlRaiseError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel, void *data, void *ctx, void *nod, int domain, int code, xmlErrorLevel level, const char *file, int line, const char *str1, const char *str2, const char *str3, int int1, int col, const char *msg,...) LIBXML_ATTR_FORMAT(16
XML_HIDDEN void xmlParserErrors const char const xmlChar const xmlChar * str2
Definition: parser.h:35
XML_HIDDEN void xmlParserErrors const char const xmlChar * str1
Definition: parser.h:35
static int fd
Definition: io.c:51
#define memset(x, y, z)
Definition: compat.h:39
struct define * next
Definition: compiler.c:65
Definition: fci.c:127
Definition: name.c:39
Definition: mxnamespace.c:38
Definition: stat.h:66
Definition: dlist.c:348
Definition: pdh_main.c:96
XMLPUBFUN xmlChar * xmlBuildURI(const xmlChar *URI, const xmlChar *base)
Definition: uri.c:1902
XMLPUBFUN xmlChar * xmlCanonicPath(const xmlChar *path)
Definition: uri.c:2394
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
#define snprintf
Definition: wintirpc.h:48
XMLPUBFUN void xmlFreeParserInputBuffer(xmlParserInputBufferPtr in)
XMLPUBFUN char * xmlParserGetDirectory(const char *filename)
XMLPUBFUN xmlParserInputBufferPtr xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc)
@ XML_ERR_ERROR
Definition: xmlerror.h:27
@ XML_FROM_CATALOG
Definition: xmlerror.h:57
@ XML_CATALOG_RECURSION
Definition: xmlerror.h:499
@ XML_CATALOG_PREFER_VALUE
Definition: xmlerror.h:497
@ XML_CATALOG_ENTRY_BROKEN
Definition: xmlerror.h:496
@ XML_CATALOG_NOT_CATALOG
Definition: xmlerror.h:498
@ XML_CATALOG_MISSING_ATTR
Definition: xmlerror.h:495
@ XML_ERR_NO_MEMORY
Definition: xmlerror.h:102
XMLPUBFUN xmlChar * xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:45
XMLPUBFUN int xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:428
XMLPUBFUN int xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len)
Definition: xmlstring.c:215
XMLPUBFUN xmlChar * xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:524
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:162
unsigned char xmlChar
Definition: xmlstring.h:28
XMLPUBFUN xmlChar * xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:69
#define LIBXML_ATTR_FORMAT(fmt, args)
Definition: xmlversion.h:472
#define const
Definition: zconf.h:233