Annotation of embedaddon/libxml2/catalog.c, revision 1.1
1.1 ! misho 1: /**
! 2: * catalog.c: set of generic Catalog related routines
! 3: *
! 4: * Reference: SGML Open Technical Resolution TR9401:1997.
! 5: * http://www.jclark.com/sp/catalog.htm
! 6: *
! 7: * XML Catalogs Working Draft 06 August 2001
! 8: * http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
! 9: *
! 10: * See Copyright for the status of this software.
! 11: *
! 12: * Daniel.Veillard@imag.fr
! 13: */
! 14:
! 15: #define IN_LIBXML
! 16: #include "libxml.h"
! 17:
! 18: #ifdef LIBXML_CATALOG_ENABLED
! 19: #ifdef HAVE_SYS_TYPES_H
! 20: #include <sys/types.h>
! 21: #endif
! 22: #ifdef HAVE_SYS_STAT_H
! 23: #include <sys/stat.h>
! 24: #endif
! 25: #ifdef HAVE_UNISTD_H
! 26: #include <unistd.h>
! 27: #endif
! 28: #ifdef HAVE_FCNTL_H
! 29: #include <fcntl.h>
! 30: #endif
! 31: #ifdef HAVE_STDLIB_H
! 32: #include <stdlib.h>
! 33: #endif
! 34: #include <string.h>
! 35: #include <libxml/xmlmemory.h>
! 36: #include <libxml/hash.h>
! 37: #include <libxml/uri.h>
! 38: #include <libxml/parserInternals.h>
! 39: #include <libxml/catalog.h>
! 40: #include <libxml/xmlerror.h>
! 41: #include <libxml/threads.h>
! 42: #include <libxml/globals.h>
! 43:
! 44: #define MAX_DELEGATE 50
! 45: #define MAX_CATAL_DEPTH 50
! 46:
! 47: #ifdef _WIN32
! 48: # define PATH_SEAPARATOR ';'
! 49: #else
! 50: # define PATH_SEAPARATOR ':'
! 51: #endif
! 52:
! 53: /**
! 54: * TODO:
! 55: *
! 56: * macro to flag unimplemented blocks
! 57: * XML_CATALOG_PREFER user env to select between system/public prefered
! 58: * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk>
! 59: *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
! 60: *> values "system" and "public". I have made the default be "system" to
! 61: *> match yours.
! 62: */
! 63: #define TODO \
! 64: xmlGenericError(xmlGenericErrorContext, \
! 65: "Unimplemented block at %s:%d\n", \
! 66: __FILE__, __LINE__);
! 67:
! 68: #define XML_URN_PUBID "urn:publicid:"
! 69: #define XML_CATAL_BREAK ((xmlChar *) -1)
! 70: #ifndef XML_XML_DEFAULT_CATALOG
! 71: #define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog"
! 72: #endif
! 73: #ifndef XML_SGML_DEFAULT_CATALOG
! 74: #define XML_SGML_DEFAULT_CATALOG "file:///etc/sgml/catalog"
! 75: #endif
! 76:
! 77: #if defined(_WIN32) && defined(_MSC_VER)
! 78: #undef XML_XML_DEFAULT_CATALOG
! 79: static char XML_XML_DEFAULT_CATALOG[256] = "file:///etc/xml/catalog";
! 80: #if defined(_WIN32_WCE)
! 81: /* Windows CE don't have a A variant */
! 82: #define GetModuleHandleA GetModuleHandle
! 83: #define GetModuleFileNameA GetModuleFileName
! 84: #else
! 85: void* __stdcall GetModuleHandleA(const char*);
! 86: unsigned long __stdcall GetModuleFileNameA(void*, char*, unsigned long);
! 87: #endif
! 88: #endif
! 89:
! 90: static xmlChar *xmlCatalogNormalizePublic(const xmlChar *pubID);
! 91: static int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename);
! 92:
! 93: /************************************************************************
! 94: * *
! 95: * Types, all private *
! 96: * *
! 97: ************************************************************************/
! 98:
! 99: typedef enum {
! 100: XML_CATA_REMOVED = -1,
! 101: XML_CATA_NONE = 0,
! 102: XML_CATA_CATALOG,
! 103: XML_CATA_BROKEN_CATALOG,
! 104: XML_CATA_NEXT_CATALOG,
! 105: XML_CATA_GROUP,
! 106: XML_CATA_PUBLIC,
! 107: XML_CATA_SYSTEM,
! 108: XML_CATA_REWRITE_SYSTEM,
! 109: XML_CATA_DELEGATE_PUBLIC,
! 110: XML_CATA_DELEGATE_SYSTEM,
! 111: XML_CATA_URI,
! 112: XML_CATA_REWRITE_URI,
! 113: XML_CATA_DELEGATE_URI,
! 114: SGML_CATA_SYSTEM,
! 115: SGML_CATA_PUBLIC,
! 116: SGML_CATA_ENTITY,
! 117: SGML_CATA_PENTITY,
! 118: SGML_CATA_DOCTYPE,
! 119: SGML_CATA_LINKTYPE,
! 120: SGML_CATA_NOTATION,
! 121: SGML_CATA_DELEGATE,
! 122: SGML_CATA_BASE,
! 123: SGML_CATA_CATALOG,
! 124: SGML_CATA_DOCUMENT,
! 125: SGML_CATA_SGMLDECL
! 126: } xmlCatalogEntryType;
! 127:
! 128: typedef struct _xmlCatalogEntry xmlCatalogEntry;
! 129: typedef xmlCatalogEntry *xmlCatalogEntryPtr;
! 130: struct _xmlCatalogEntry {
! 131: struct _xmlCatalogEntry *next;
! 132: struct _xmlCatalogEntry *parent;
! 133: struct _xmlCatalogEntry *children;
! 134: xmlCatalogEntryType type;
! 135: xmlChar *name;
! 136: xmlChar *value;
! 137: xmlChar *URL; /* The expanded URL using the base */
! 138: xmlCatalogPrefer prefer;
! 139: int dealloc;
! 140: int depth;
! 141: struct _xmlCatalogEntry *group;
! 142: };
! 143:
! 144: typedef enum {
! 145: XML_XML_CATALOG_TYPE = 1,
! 146: XML_SGML_CATALOG_TYPE
! 147: } xmlCatalogType;
! 148:
! 149: #define XML_MAX_SGML_CATA_DEPTH 10
! 150: struct _xmlCatalog {
! 151: xmlCatalogType type; /* either XML or SGML */
! 152:
! 153: /*
! 154: * SGML Catalogs are stored as a simple hash table of catalog entries
! 155: * Catalog stack to check against overflows when building the
! 156: * SGML catalog
! 157: */
! 158: char *catalTab[XML_MAX_SGML_CATA_DEPTH]; /* stack of catals */
! 159: int catalNr; /* Number of current catal streams */
! 160: int catalMax; /* Max number of catal streams */
! 161: xmlHashTablePtr sgml;
! 162:
! 163: /*
! 164: * XML Catalogs are stored as a tree of Catalog entries
! 165: */
! 166: xmlCatalogPrefer prefer;
! 167: xmlCatalogEntryPtr xml;
! 168: };
! 169:
! 170: /************************************************************************
! 171: * *
! 172: * Global variables *
! 173: * *
! 174: ************************************************************************/
! 175:
! 176: /*
! 177: * Those are preferences
! 178: */
! 179: static int xmlDebugCatalogs = 0; /* used for debugging */
! 180: static xmlCatalogAllow xmlCatalogDefaultAllow = XML_CATA_ALLOW_ALL;
! 181: static xmlCatalogPrefer xmlCatalogDefaultPrefer = XML_CATA_PREFER_PUBLIC;
! 182:
! 183: /*
! 184: * Hash table containing all the trees of XML catalogs parsed by
! 185: * the application.
! 186: */
! 187: static xmlHashTablePtr xmlCatalogXMLFiles = NULL;
! 188:
! 189: /*
! 190: * The default catalog in use by the application
! 191: */
! 192: static xmlCatalogPtr xmlDefaultCatalog = NULL;
! 193:
! 194: /*
! 195: * A mutex for modifying the shared global catalog(s)
! 196: * xmlDefaultCatalog tree.
! 197: * It also protects xmlCatalogXMLFiles
! 198: * The core of this readers/writer scheme is in xmlFetchXMLCatalogFile()
! 199: */
! 200: static xmlRMutexPtr xmlCatalogMutex = NULL;
! 201:
! 202: /*
! 203: * Whether the catalog support was initialized.
! 204: */
! 205: static int xmlCatalogInitialized = 0;
! 206:
! 207: /************************************************************************
! 208: * *
! 209: * Catalog error handlers *
! 210: * *
! 211: ************************************************************************/
! 212:
! 213: /**
! 214: * xmlCatalogErrMemory:
! 215: * @extra: extra informations
! 216: *
! 217: * Handle an out of memory condition
! 218: */
! 219: static void
! 220: xmlCatalogErrMemory(const char *extra)
! 221: {
! 222: __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_CATALOG,
! 223: XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0,
! 224: extra, NULL, NULL, 0, 0,
! 225: "Memory allocation failed : %s\n", extra);
! 226: }
! 227:
! 228: /**
! 229: * xmlCatalogErr:
! 230: * @catal: the Catalog entry
! 231: * @node: the context node
! 232: * @msg: the error message
! 233: * @extra: extra informations
! 234: *
! 235: * Handle a catalog error
! 236: */
! 237: static void
! 238: xmlCatalogErr(xmlCatalogEntryPtr catal, xmlNodePtr node, int error,
! 239: const char *msg, const xmlChar *str1, const xmlChar *str2,
! 240: const xmlChar *str3)
! 241: {
! 242: __xmlRaiseError(NULL, NULL, NULL, catal, node, XML_FROM_CATALOG,
! 243: error, XML_ERR_ERROR, NULL, 0,
! 244: (const char *) str1, (const char *) str2,
! 245: (const char *) str3, 0, 0,
! 246: msg, str1, str2, str3);
! 247: }
! 248:
! 249:
! 250: /************************************************************************
! 251: * *
! 252: * Allocation and Freeing *
! 253: * *
! 254: ************************************************************************/
! 255:
! 256: /**
! 257: * xmlNewCatalogEntry:
! 258: * @type: type of entry
! 259: * @name: name of the entry
! 260: * @value: value of the entry
! 261: * @prefer: the PUBLIC vs. SYSTEM current preference value
! 262: * @group: for members of a group, the group entry
! 263: *
! 264: * create a new Catalog entry, this type is shared both by XML and
! 265: * SGML catalogs, but the acceptable types values differs.
! 266: *
! 267: * Returns the xmlCatalogEntryPtr or NULL in case of error
! 268: */
! 269: static xmlCatalogEntryPtr
! 270: xmlNewCatalogEntry(xmlCatalogEntryType type, const xmlChar *name,
! 271: const xmlChar *value, const xmlChar *URL, xmlCatalogPrefer prefer,
! 272: xmlCatalogEntryPtr group) {
! 273: xmlCatalogEntryPtr ret;
! 274: xmlChar *normid = NULL;
! 275:
! 276: ret = (xmlCatalogEntryPtr) xmlMalloc(sizeof(xmlCatalogEntry));
! 277: if (ret == NULL) {
! 278: xmlCatalogErrMemory("allocating catalog entry");
! 279: return(NULL);
! 280: }
! 281: ret->next = NULL;
! 282: ret->parent = NULL;
! 283: ret->children = NULL;
! 284: ret->type = type;
! 285: if (type == XML_CATA_PUBLIC || type == XML_CATA_DELEGATE_PUBLIC) {
! 286: normid = xmlCatalogNormalizePublic(name);
! 287: if (normid != NULL)
! 288: name = (*normid != 0 ? normid : NULL);
! 289: }
! 290: if (name != NULL)
! 291: ret->name = xmlStrdup(name);
! 292: else
! 293: ret->name = NULL;
! 294: if (normid != NULL)
! 295: xmlFree(normid);
! 296: if (value != NULL)
! 297: ret->value = xmlStrdup(value);
! 298: else
! 299: ret->value = NULL;
! 300: if (URL == NULL)
! 301: URL = value;
! 302: if (URL != NULL)
! 303: ret->URL = xmlStrdup(URL);
! 304: else
! 305: ret->URL = NULL;
! 306: ret->prefer = prefer;
! 307: ret->dealloc = 0;
! 308: ret->depth = 0;
! 309: ret->group = group;
! 310: return(ret);
! 311: }
! 312:
! 313: static void
! 314: xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret);
! 315:
! 316: /**
! 317: * xmlFreeCatalogEntry:
! 318: * @ret: a Catalog entry
! 319: *
! 320: * Free the memory allocated to a Catalog entry
! 321: */
! 322: static void
! 323: xmlFreeCatalogEntry(xmlCatalogEntryPtr ret) {
! 324: if (ret == NULL)
! 325: return;
! 326: /*
! 327: * Entries stored in the file hash must be deallocated
! 328: * only by the file hash cleaner !
! 329: */
! 330: if (ret->dealloc == 1)
! 331: return;
! 332:
! 333: if (xmlDebugCatalogs) {
! 334: if (ret->name != NULL)
! 335: xmlGenericError(xmlGenericErrorContext,
! 336: "Free catalog entry %s\n", ret->name);
! 337: else if (ret->value != NULL)
! 338: xmlGenericError(xmlGenericErrorContext,
! 339: "Free catalog entry %s\n", ret->value);
! 340: else
! 341: xmlGenericError(xmlGenericErrorContext,
! 342: "Free catalog entry\n");
! 343: }
! 344:
! 345: if (ret->name != NULL)
! 346: xmlFree(ret->name);
! 347: if (ret->value != NULL)
! 348: xmlFree(ret->value);
! 349: if (ret->URL != NULL)
! 350: xmlFree(ret->URL);
! 351: xmlFree(ret);
! 352: }
! 353:
! 354: /**
! 355: * xmlFreeCatalogEntryList:
! 356: * @ret: a Catalog entry list
! 357: *
! 358: * Free the memory allocated to a full chained list of Catalog entries
! 359: */
! 360: static void
! 361: xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret) {
! 362: xmlCatalogEntryPtr next;
! 363:
! 364: while (ret != NULL) {
! 365: next = ret->next;
! 366: xmlFreeCatalogEntry(ret);
! 367: ret = next;
! 368: }
! 369: }
! 370:
! 371: /**
! 372: * xmlFreeCatalogHashEntryList:
! 373: * @ret: a Catalog entry list
! 374: *
! 375: * Free the memory allocated to list of Catalog entries from the
! 376: * catalog file hash.
! 377: */
! 378: static void
! 379: xmlFreeCatalogHashEntryList(xmlCatalogEntryPtr catal) {
! 380: xmlCatalogEntryPtr children, next;
! 381:
! 382: if (catal == NULL)
! 383: return;
! 384:
! 385: children = catal->children;
! 386: while (children != NULL) {
! 387: next = children->next;
! 388: children->dealloc = 0;
! 389: children->children = NULL;
! 390: xmlFreeCatalogEntry(children);
! 391: children = next;
! 392: }
! 393: catal->dealloc = 0;
! 394: xmlFreeCatalogEntry(catal);
! 395: }
! 396:
! 397: /**
! 398: * xmlCreateNewCatalog:
! 399: * @type: type of catalog
! 400: * @prefer: the PUBLIC vs. SYSTEM current preference value
! 401: *
! 402: * create a new Catalog, this type is shared both by XML and
! 403: * SGML catalogs, but the acceptable types values differs.
! 404: *
! 405: * Returns the xmlCatalogPtr or NULL in case of error
! 406: */
! 407: static xmlCatalogPtr
! 408: xmlCreateNewCatalog(xmlCatalogType type, xmlCatalogPrefer prefer) {
! 409: xmlCatalogPtr ret;
! 410:
! 411: ret = (xmlCatalogPtr) xmlMalloc(sizeof(xmlCatalog));
! 412: if (ret == NULL) {
! 413: xmlCatalogErrMemory("allocating catalog");
! 414: return(NULL);
! 415: }
! 416: memset(ret, 0, sizeof(xmlCatalog));
! 417: ret->type = type;
! 418: ret->catalNr = 0;
! 419: ret->catalMax = XML_MAX_SGML_CATA_DEPTH;
! 420: ret->prefer = prefer;
! 421: if (ret->type == XML_SGML_CATALOG_TYPE)
! 422: ret->sgml = xmlHashCreate(10);
! 423: return(ret);
! 424: }
! 425:
! 426: /**
! 427: * xmlFreeCatalog:
! 428: * @catal: a Catalog
! 429: *
! 430: * Free the memory allocated to a Catalog
! 431: */
! 432: void
! 433: xmlFreeCatalog(xmlCatalogPtr catal) {
! 434: if (catal == NULL)
! 435: return;
! 436: if (catal->xml != NULL)
! 437: xmlFreeCatalogEntryList(catal->xml);
! 438: if (catal->sgml != NULL)
! 439: xmlHashFree(catal->sgml,
! 440: (xmlHashDeallocator) xmlFreeCatalogEntry);
! 441: xmlFree(catal);
! 442: }
! 443:
! 444: /************************************************************************
! 445: * *
! 446: * Serializing Catalogs *
! 447: * *
! 448: ************************************************************************/
! 449:
! 450: #ifdef LIBXML_OUTPUT_ENABLED
! 451: /**
! 452: * xmlCatalogDumpEntry:
! 453: * @entry: the catalog entry
! 454: * @out: the file.
! 455: *
! 456: * Serialize an SGML Catalog entry
! 457: */
! 458: static void
! 459: xmlCatalogDumpEntry(xmlCatalogEntryPtr entry, FILE *out) {
! 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:
! 524: /**
! 525: * xmlDumpXMLCatalogNode:
! 526: * @catal: top catalog entry
! 527: * @catalog: pointer to the xml tree
! 528: * @doc: the containing document
! 529: * @ns: the current namespace
! 530: * @cgroup: group node for group members
! 531: *
! 532: * Serializes a Catalog entry, called by xmlDumpXMLCatalog and recursively
! 533: * for group entries
! 534: */
! 535: static 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:
! 652: static int
! 653: xmlDumpXMLCatalog(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",
! 669: BAD_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:
! 714: /**
! 715: * xmlCatalogConvertEntry:
! 716: * @entry: the entry
! 717: * @catal: pointer to the catalog being converted
! 718: *
! 719: * Convert one entry from the catalog
! 720: */
! 721: static void
! 722: xmlCatalogConvertEntry(xmlCatalogEntryPtr entry, xmlCatalogPtr catal) {
! 723: if ((entry == NULL) || (catal == NULL) || (catal->sgml == NULL) ||
! 724: (catal->xml == NULL))
! 725: return;
! 726: switch (entry->type) {
! 727: case SGML_CATA_ENTITY:
! 728: entry->type = XML_CATA_PUBLIC;
! 729: break;
! 730: case SGML_CATA_PENTITY:
! 731: entry->type = XML_CATA_PUBLIC;
! 732: break;
! 733: case SGML_CATA_DOCTYPE:
! 734: entry->type = XML_CATA_PUBLIC;
! 735: break;
! 736: case SGML_CATA_LINKTYPE:
! 737: entry->type = XML_CATA_PUBLIC;
! 738: break;
! 739: case SGML_CATA_NOTATION:
! 740: entry->type = XML_CATA_PUBLIC;
! 741: break;
! 742: case SGML_CATA_PUBLIC:
! 743: entry->type = XML_CATA_PUBLIC;
! 744: break;
! 745: case SGML_CATA_SYSTEM:
! 746: entry->type = XML_CATA_SYSTEM;
! 747: break;
! 748: case SGML_CATA_DELEGATE:
! 749: entry->type = XML_CATA_DELEGATE_PUBLIC;
! 750: break;
! 751: case SGML_CATA_CATALOG:
! 752: entry->type = XML_CATA_CATALOG;
! 753: break;
! 754: default:
! 755: xmlHashRemoveEntry(catal->sgml, entry->name,
! 756: (xmlHashDeallocator) xmlFreeCatalogEntry);
! 757: return;
! 758: }
! 759: /*
! 760: * Conversion successful, remove from the SGML catalog
! 761: * and add it to the default XML one
! 762: */
! 763: xmlHashRemoveEntry(catal->sgml, entry->name, NULL);
! 764: entry->parent = catal->xml;
! 765: entry->next = NULL;
! 766: if (catal->xml->children == NULL)
! 767: catal->xml->children = entry;
! 768: else {
! 769: xmlCatalogEntryPtr prev;
! 770:
! 771: prev = catal->xml->children;
! 772: while (prev->next != NULL)
! 773: prev = prev->next;
! 774: prev->next = entry;
! 775: }
! 776: }
! 777:
! 778: /**
! 779: * xmlConvertSGMLCatalog:
! 780: * @catal: the catalog
! 781: *
! 782: * Convert all the SGML catalog entries as XML ones
! 783: *
! 784: * Returns the number of entries converted if successful, -1 otherwise
! 785: */
! 786: int
! 787: xmlConvertSGMLCatalog(xmlCatalogPtr catal) {
! 788:
! 789: if ((catal == NULL) || (catal->type != XML_SGML_CATALOG_TYPE))
! 790: return(-1);
! 791:
! 792: if (xmlDebugCatalogs) {
! 793: xmlGenericError(xmlGenericErrorContext,
! 794: "Converting SGML catalog to XML\n");
! 795: }
! 796: xmlHashScan(catal->sgml,
! 797: (xmlHashScanner) xmlCatalogConvertEntry,
! 798: &catal);
! 799: return(0);
! 800: }
! 801:
! 802: /************************************************************************
! 803: * *
! 804: * Helper function *
! 805: * *
! 806: ************************************************************************/
! 807:
! 808: /**
! 809: * xmlCatalogUnWrapURN:
! 810: * @urn: an "urn:publicid:" to unwrap
! 811: *
! 812: * Expand the URN into the equivalent Public Identifier
! 813: *
! 814: * Returns the new identifier or NULL, the string must be deallocated
! 815: * by the caller.
! 816: */
! 817: static xmlChar *
! 818: xmlCatalogUnWrapURN(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:
! 873: /**
! 874: * xmlParseCatalogFile:
! 875: * @filename: the filename
! 876: *
! 877: * parse an XML file and build a tree. It's like xmlParseFile()
! 878: * except it bypass all catalog lookups.
! 879: *
! 880: * Returns the resulting document tree or NULL in case of error
! 881: */
! 882:
! 883: xmlDocPtr
! 884: xmlParseCatalogFile(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: #ifdef LIBXML_SAX1_ENABLED
! 894: if (xmlDefaultSAXHandler.error != NULL) {
! 895: xmlDefaultSAXHandler.error(NULL, "out of memory\n");
! 896: }
! 897: #endif
! 898: return(NULL);
! 899: }
! 900:
! 901: buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
! 902: if (buf == NULL) {
! 903: xmlFreeParserCtxt(ctxt);
! 904: return(NULL);
! 905: }
! 906:
! 907: inputStream = xmlNewInputStream(ctxt);
! 908: if (inputStream == NULL) {
! 909: xmlFreeParserCtxt(ctxt);
! 910: return(NULL);
! 911: }
! 912:
! 913: inputStream->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
! 914: inputStream->buf = buf;
! 915: inputStream->base = inputStream->buf->buffer->content;
! 916: inputStream->cur = inputStream->buf->buffer->content;
! 917: inputStream->end =
! 918: &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
! 919:
! 920: inputPush(ctxt, inputStream);
! 921: if ((ctxt->directory == NULL) && (directory == NULL))
! 922: directory = xmlParserGetDirectory(filename);
! 923: if ((ctxt->directory == NULL) && (directory != NULL))
! 924: ctxt->directory = directory;
! 925: ctxt->valid = 0;
! 926: ctxt->validate = 0;
! 927: ctxt->loadsubset = 0;
! 928: ctxt->pedantic = 0;
! 929: ctxt->dictNames = 1;
! 930:
! 931: xmlParseDocument(ctxt);
! 932:
! 933: if (ctxt->wellFormed)
! 934: ret = ctxt->myDoc;
! 935: else {
! 936: ret = NULL;
! 937: xmlFreeDoc(ctxt->myDoc);
! 938: ctxt->myDoc = NULL;
! 939: }
! 940: xmlFreeParserCtxt(ctxt);
! 941:
! 942: return(ret);
! 943: }
! 944:
! 945: /**
! 946: * xmlLoadFileContent:
! 947: * @filename: a file path
! 948: *
! 949: * Load a file content into memory.
! 950: *
! 951: * Returns a pointer to the 0 terminated string or NULL in case of error
! 952: */
! 953: static xmlChar *
! 954: xmlLoadFileContent(const char *filename)
! 955: {
! 956: #ifdef HAVE_STAT
! 957: int fd;
! 958: #else
! 959: FILE *fd;
! 960: #endif
! 961: int len;
! 962: long size;
! 963:
! 964: #ifdef HAVE_STAT
! 965: struct stat info;
! 966: #endif
! 967: xmlChar *content;
! 968:
! 969: if (filename == NULL)
! 970: return (NULL);
! 971:
! 972: #ifdef HAVE_STAT
! 973: if (stat(filename, &info) < 0)
! 974: return (NULL);
! 975: #endif
! 976:
! 977: #ifdef HAVE_STAT
! 978: if ((fd = open(filename, O_RDONLY)) < 0)
! 979: #else
! 980: if ((fd = fopen(filename, "rb")) == NULL)
! 981: #endif
! 982: {
! 983: return (NULL);
! 984: }
! 985: #ifdef HAVE_STAT
! 986: size = info.st_size;
! 987: #else
! 988: if (fseek(fd, 0, SEEK_END) || (size = ftell(fd)) == EOF || fseek(fd, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */
! 989: fclose(fd);
! 990: return (NULL);
! 991: }
! 992: #endif
! 993: content = xmlMallocAtomic(size + 10);
! 994: if (content == NULL) {
! 995: xmlCatalogErrMemory("allocating catalog data");
! 996: return (NULL);
! 997: }
! 998: #ifdef HAVE_STAT
! 999: len = read(fd, content, size);
! 1000: close(fd);
! 1001: #else
! 1002: len = fread(content, 1, size, fd);
! 1003: fclose(fd);
! 1004: #endif
! 1005: if (len < 0) {
! 1006: xmlFree(content);
! 1007: return (NULL);
! 1008: }
! 1009: content[len] = 0;
! 1010:
! 1011: return(content);
! 1012: }
! 1013:
! 1014: /**
! 1015: * xmlCatalogNormalizePublic:
! 1016: * @pubID: the public ID string
! 1017: *
! 1018: * Normalizes the Public Identifier
! 1019: *
! 1020: * Implements 6.2. Public Identifier Normalization
! 1021: * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
! 1022: *
! 1023: * Returns the new string or NULL, the string must be deallocated
! 1024: * by the caller.
! 1025: */
! 1026: static xmlChar *
! 1027: xmlCatalogNormalizePublic(const xmlChar *pubID)
! 1028: {
! 1029: int ok = 1;
! 1030: int white;
! 1031: const xmlChar *p;
! 1032: xmlChar *ret;
! 1033: xmlChar *q;
! 1034:
! 1035: if (pubID == NULL)
! 1036: return(NULL);
! 1037:
! 1038: white = 1;
! 1039: for (p = pubID;*p != 0 && ok;p++) {
! 1040: if (!xmlIsBlank_ch(*p))
! 1041: white = 0;
! 1042: else if (*p == 0x20 && !white)
! 1043: white = 1;
! 1044: else
! 1045: ok = 0;
! 1046: }
! 1047: if (ok && !white) /* is normalized */
! 1048: return(NULL);
! 1049:
! 1050: ret = xmlStrdup(pubID);
! 1051: q = ret;
! 1052: white = 0;
! 1053: for (p = pubID;*p != 0;p++) {
! 1054: if (xmlIsBlank_ch(*p)) {
! 1055: if (q != ret)
! 1056: white = 1;
! 1057: } else {
! 1058: if (white) {
! 1059: *(q++) = 0x20;
! 1060: white = 0;
! 1061: }
! 1062: *(q++) = *p;
! 1063: }
! 1064: }
! 1065: *q = 0;
! 1066: return(ret);
! 1067: }
! 1068:
! 1069: /************************************************************************
! 1070: * *
! 1071: * The XML Catalog parser *
! 1072: * *
! 1073: ************************************************************************/
! 1074:
! 1075: static xmlCatalogEntryPtr
! 1076: xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename);
! 1077: static void
! 1078: xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
! 1079: xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup);
! 1080: static xmlChar *
! 1081: xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
! 1082: const xmlChar *sysID);
! 1083: static xmlChar *
! 1084: xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI);
! 1085:
! 1086:
! 1087: /**
! 1088: * xmlGetXMLCatalogEntryType:
! 1089: * @name: the name
! 1090: *
! 1091: * lookup the internal type associated to an XML catalog entry name
! 1092: *
! 1093: * Returns the type associated with that name
! 1094: */
! 1095: static xmlCatalogEntryType
! 1096: xmlGetXMLCatalogEntryType(const xmlChar *name) {
! 1097: xmlCatalogEntryType type = XML_CATA_NONE;
! 1098: if (xmlStrEqual(name, (const xmlChar *) "system"))
! 1099: type = XML_CATA_SYSTEM;
! 1100: else if (xmlStrEqual(name, (const xmlChar *) "public"))
! 1101: type = XML_CATA_PUBLIC;
! 1102: else if (xmlStrEqual(name, (const xmlChar *) "rewriteSystem"))
! 1103: type = XML_CATA_REWRITE_SYSTEM;
! 1104: else if (xmlStrEqual(name, (const xmlChar *) "delegatePublic"))
! 1105: type = XML_CATA_DELEGATE_PUBLIC;
! 1106: else if (xmlStrEqual(name, (const xmlChar *) "delegateSystem"))
! 1107: type = XML_CATA_DELEGATE_SYSTEM;
! 1108: else if (xmlStrEqual(name, (const xmlChar *) "uri"))
! 1109: type = XML_CATA_URI;
! 1110: else if (xmlStrEqual(name, (const xmlChar *) "rewriteURI"))
! 1111: type = XML_CATA_REWRITE_URI;
! 1112: else if (xmlStrEqual(name, (const xmlChar *) "delegateURI"))
! 1113: type = XML_CATA_DELEGATE_URI;
! 1114: else if (xmlStrEqual(name, (const xmlChar *) "nextCatalog"))
! 1115: type = XML_CATA_NEXT_CATALOG;
! 1116: else if (xmlStrEqual(name, (const xmlChar *) "catalog"))
! 1117: type = XML_CATA_CATALOG;
! 1118: return(type);
! 1119: }
! 1120:
! 1121: /**
! 1122: * xmlParseXMLCatalogOneNode:
! 1123: * @cur: the XML node
! 1124: * @type: the type of Catalog entry
! 1125: * @name: the name of the node
! 1126: * @attrName: the attribute holding the value
! 1127: * @uriAttrName: the attribute holding the URI-Reference
! 1128: * @prefer: the PUBLIC vs. SYSTEM current preference value
! 1129: * @cgroup: the group which includes this node
! 1130: *
! 1131: * Finishes the examination of an XML tree node of a catalog and build
! 1132: * a Catalog entry from it.
! 1133: *
! 1134: * Returns the new Catalog entry node or NULL in case of error.
! 1135: */
! 1136: static xmlCatalogEntryPtr
! 1137: xmlParseXMLCatalogOneNode(xmlNodePtr cur, xmlCatalogEntryType type,
! 1138: const xmlChar *name, const xmlChar *attrName,
! 1139: const xmlChar *uriAttrName, xmlCatalogPrefer prefer,
! 1140: xmlCatalogEntryPtr cgroup) {
! 1141: int ok = 1;
! 1142: xmlChar *uriValue;
! 1143: xmlChar *nameValue = NULL;
! 1144: xmlChar *base = NULL;
! 1145: xmlChar *URL = NULL;
! 1146: xmlCatalogEntryPtr ret = NULL;
! 1147:
! 1148: if (attrName != NULL) {
! 1149: nameValue = xmlGetProp(cur, attrName);
! 1150: if (nameValue == NULL) {
! 1151: xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
! 1152: "%s entry lacks '%s'\n", name, attrName, NULL);
! 1153: ok = 0;
! 1154: }
! 1155: }
! 1156: uriValue = xmlGetProp(cur, uriAttrName);
! 1157: if (uriValue == NULL) {
! 1158: xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR,
! 1159: "%s entry lacks '%s'\n", name, uriAttrName, NULL);
! 1160: ok = 0;
! 1161: }
! 1162: if (!ok) {
! 1163: if (nameValue != NULL)
! 1164: xmlFree(nameValue);
! 1165: if (uriValue != NULL)
! 1166: xmlFree(uriValue);
! 1167: return(NULL);
! 1168: }
! 1169:
! 1170: base = xmlNodeGetBase(cur->doc, cur);
! 1171: URL = xmlBuildURI(uriValue, base);
! 1172: if (URL != NULL) {
! 1173: if (xmlDebugCatalogs > 1) {
! 1174: if (nameValue != NULL)
! 1175: xmlGenericError(xmlGenericErrorContext,
! 1176: "Found %s: '%s' '%s'\n", name, nameValue, URL);
! 1177: else
! 1178: xmlGenericError(xmlGenericErrorContext,
! 1179: "Found %s: '%s'\n", name, URL);
! 1180: }
! 1181: ret = xmlNewCatalogEntry(type, nameValue, uriValue, URL, prefer, cgroup);
! 1182: } else {
! 1183: xmlCatalogErr(ret, cur, XML_CATALOG_ENTRY_BROKEN,
! 1184: "%s entry '%s' broken ?: %s\n", name, uriAttrName, uriValue);
! 1185: }
! 1186: if (nameValue != NULL)
! 1187: xmlFree(nameValue);
! 1188: if (uriValue != NULL)
! 1189: xmlFree(uriValue);
! 1190: if (base != NULL)
! 1191: xmlFree(base);
! 1192: if (URL != NULL)
! 1193: xmlFree(URL);
! 1194: return(ret);
! 1195: }
! 1196:
! 1197: /**
! 1198: * xmlParseXMLCatalogNode:
! 1199: * @cur: the XML node
! 1200: * @prefer: the PUBLIC vs. SYSTEM current preference value
! 1201: * @parent: the parent Catalog entry
! 1202: * @cgroup: the group which includes this node
! 1203: *
! 1204: * Examines an XML tree node of a catalog and build
! 1205: * a Catalog entry from it adding it to its parent. The examination can
! 1206: * be recursive.
! 1207: */
! 1208: static void
! 1209: xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer,
! 1210: xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup)
! 1211: {
! 1212: xmlChar *base = NULL;
! 1213: xmlCatalogEntryPtr entry = NULL;
! 1214:
! 1215: if (cur == NULL)
! 1216: return;
! 1217: if (xmlStrEqual(cur->name, BAD_CAST "group")) {
! 1218: xmlChar *prop;
! 1219: xmlCatalogPrefer pref = XML_CATA_PREFER_NONE;
! 1220:
! 1221: prop = xmlGetProp(cur, BAD_CAST "prefer");
! 1222: if (prop != NULL) {
! 1223: if (xmlStrEqual(prop, BAD_CAST "system")) {
! 1224: prefer = XML_CATA_PREFER_SYSTEM;
! 1225: } else if (xmlStrEqual(prop, BAD_CAST "public")) {
! 1226: prefer = XML_CATA_PREFER_PUBLIC;
! 1227: } else {
! 1228: xmlCatalogErr(parent, cur, XML_CATALOG_PREFER_VALUE,
! 1229: "Invalid value for prefer: '%s'\n",
! 1230: prop, NULL, NULL);
! 1231: }
! 1232: xmlFree(prop);
! 1233: pref = prefer;
! 1234: }
! 1235: prop = xmlGetProp(cur, BAD_CAST "id");
! 1236: base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE);
! 1237: entry = xmlNewCatalogEntry(XML_CATA_GROUP, prop, base, NULL, pref, cgroup);
! 1238: xmlFree(prop);
! 1239: } else if (xmlStrEqual(cur->name, BAD_CAST "public")) {
! 1240: entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_PUBLIC,
! 1241: BAD_CAST "public", BAD_CAST "publicId", BAD_CAST "uri", prefer, cgroup);
! 1242: } else if (xmlStrEqual(cur->name, BAD_CAST "system")) {
! 1243: entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_SYSTEM,
! 1244: BAD_CAST "system", BAD_CAST "systemId", BAD_CAST "uri", prefer, cgroup);
! 1245: } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteSystem")) {
! 1246: entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_SYSTEM,
! 1247: BAD_CAST "rewriteSystem", BAD_CAST "systemIdStartString",
! 1248: BAD_CAST "rewritePrefix", prefer, cgroup);
! 1249: } else if (xmlStrEqual(cur->name, BAD_CAST "delegatePublic")) {
! 1250: entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_PUBLIC,
! 1251: BAD_CAST "delegatePublic", BAD_CAST "publicIdStartString",
! 1252: BAD_CAST "catalog", prefer, cgroup);
! 1253: } else if (xmlStrEqual(cur->name, BAD_CAST "delegateSystem")) {
! 1254: entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_SYSTEM,
! 1255: BAD_CAST "delegateSystem", BAD_CAST "systemIdStartString",
! 1256: BAD_CAST "catalog", prefer, cgroup);
! 1257: } else if (xmlStrEqual(cur->name, BAD_CAST "uri")) {
! 1258: entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_URI,
! 1259: BAD_CAST "uri", BAD_CAST "name",
! 1260: BAD_CAST "uri", prefer, cgroup);
! 1261: } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteURI")) {
! 1262: entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_URI,
! 1263: BAD_CAST "rewriteURI", BAD_CAST "uriStartString",
! 1264: BAD_CAST "rewritePrefix", prefer, cgroup);
! 1265: } else if (xmlStrEqual(cur->name, BAD_CAST "delegateURI")) {
! 1266: entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_URI,
! 1267: BAD_CAST "delegateURI", BAD_CAST "uriStartString",
! 1268: BAD_CAST "catalog", prefer, cgroup);
! 1269: } else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) {
! 1270: entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG,
! 1271: BAD_CAST "nextCatalog", NULL,
! 1272: BAD_CAST "catalog", prefer, cgroup);
! 1273: }
! 1274: if (entry != NULL) {
! 1275: if (parent != NULL) {
! 1276: entry->parent = parent;
! 1277: if (parent->children == NULL)
! 1278: parent->children = entry;
! 1279: else {
! 1280: xmlCatalogEntryPtr prev;
! 1281:
! 1282: prev = parent->children;
! 1283: while (prev->next != NULL)
! 1284: prev = prev->next;
! 1285: prev->next = entry;
! 1286: }
! 1287: }
! 1288: if (entry->type == XML_CATA_GROUP) {
! 1289: /*
! 1290: * Recurse to propagate prefer to the subtree
! 1291: * (xml:base handling is automated)
! 1292: */
! 1293: xmlParseXMLCatalogNodeList(cur->children, prefer, parent, entry);
! 1294: }
! 1295: }
! 1296: if (base != NULL)
! 1297: xmlFree(base);
! 1298: }
! 1299:
! 1300: /**
! 1301: * xmlParseXMLCatalogNodeList:
! 1302: * @cur: the XML node list of siblings
! 1303: * @prefer: the PUBLIC vs. SYSTEM current preference value
! 1304: * @parent: the parent Catalog entry
! 1305: * @cgroup: the group which includes this list
! 1306: *
! 1307: * Examines a list of XML sibling nodes of a catalog and build
! 1308: * a list of Catalog entry from it adding it to the parent.
! 1309: * The examination will recurse to examine node subtrees.
! 1310: */
! 1311: static void
! 1312: xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer,
! 1313: xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup) {
! 1314: while (cur != NULL) {
! 1315: if ((cur->ns != NULL) && (cur->ns->href != NULL) &&
! 1316: (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) {
! 1317: xmlParseXMLCatalogNode(cur, prefer, parent, cgroup);
! 1318: }
! 1319: cur = cur->next;
! 1320: }
! 1321: /* TODO: sort the list according to REWRITE lengths and prefer value */
! 1322: }
! 1323:
! 1324: /**
! 1325: * xmlParseXMLCatalogFile:
! 1326: * @prefer: the PUBLIC vs. SYSTEM current preference value
! 1327: * @filename: the filename for the catalog
! 1328: *
! 1329: * Parses the catalog file to extract the XML tree and then analyze the
! 1330: * tree to build a list of Catalog entries corresponding to this catalog
! 1331: *
! 1332: * Returns the resulting Catalog entries list
! 1333: */
! 1334: static xmlCatalogEntryPtr
! 1335: xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename) {
! 1336: xmlDocPtr doc;
! 1337: xmlNodePtr cur;
! 1338: xmlChar *prop;
! 1339: xmlCatalogEntryPtr parent = NULL;
! 1340:
! 1341: if (filename == NULL)
! 1342: return(NULL);
! 1343:
! 1344: doc = xmlParseCatalogFile((const char *) filename);
! 1345: if (doc == NULL) {
! 1346: if (xmlDebugCatalogs)
! 1347: xmlGenericError(xmlGenericErrorContext,
! 1348: "Failed to parse catalog %s\n", filename);
! 1349: return(NULL);
! 1350: }
! 1351:
! 1352: if (xmlDebugCatalogs)
! 1353: xmlGenericError(xmlGenericErrorContext,
! 1354: "%d Parsing catalog %s\n", xmlGetThreadId(), filename);
! 1355:
! 1356: cur = xmlDocGetRootElement(doc);
! 1357: if ((cur != NULL) && (xmlStrEqual(cur->name, BAD_CAST "catalog")) &&
! 1358: (cur->ns != NULL) && (cur->ns->href != NULL) &&
! 1359: (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) {
! 1360:
! 1361: parent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
! 1362: (const xmlChar *)filename, NULL, prefer, NULL);
! 1363: if (parent == NULL) {
! 1364: xmlFreeDoc(doc);
! 1365: return(NULL);
! 1366: }
! 1367:
! 1368: prop = xmlGetProp(cur, BAD_CAST "prefer");
! 1369: if (prop != NULL) {
! 1370: if (xmlStrEqual(prop, BAD_CAST "system")) {
! 1371: prefer = XML_CATA_PREFER_SYSTEM;
! 1372: } else if (xmlStrEqual(prop, BAD_CAST "public")) {
! 1373: prefer = XML_CATA_PREFER_PUBLIC;
! 1374: } else {
! 1375: xmlCatalogErr(NULL, cur, XML_CATALOG_PREFER_VALUE,
! 1376: "Invalid value for prefer: '%s'\n",
! 1377: prop, NULL, NULL);
! 1378: }
! 1379: xmlFree(prop);
! 1380: }
! 1381: cur = cur->children;
! 1382: xmlParseXMLCatalogNodeList(cur, prefer, parent, NULL);
! 1383: } else {
! 1384: xmlCatalogErr(NULL, (xmlNodePtr) doc, XML_CATALOG_NOT_CATALOG,
! 1385: "File %s is not an XML Catalog\n",
! 1386: filename, NULL, NULL);
! 1387: xmlFreeDoc(doc);
! 1388: return(NULL);
! 1389: }
! 1390: xmlFreeDoc(doc);
! 1391: return(parent);
! 1392: }
! 1393:
! 1394: /**
! 1395: * xmlFetchXMLCatalogFile:
! 1396: * @catal: an existing but incomplete catalog entry
! 1397: *
! 1398: * Fetch and parse the subcatalog referenced by an entry
! 1399: *
! 1400: * Returns 0 in case of success, -1 otherwise
! 1401: */
! 1402: static int
! 1403: xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) {
! 1404: xmlCatalogEntryPtr doc;
! 1405:
! 1406: if (catal == NULL)
! 1407: return(-1);
! 1408: if (catal->URL == NULL)
! 1409: return(-1);
! 1410: if (catal->children != NULL)
! 1411: return(-1);
! 1412:
! 1413: /*
! 1414: * lock the whole catalog for modification
! 1415: */
! 1416: xmlRMutexLock(xmlCatalogMutex);
! 1417: if (catal->children != NULL) {
! 1418: /* Okay someone else did it in the meantime */
! 1419: xmlRMutexUnlock(xmlCatalogMutex);
! 1420: return(0);
! 1421: }
! 1422:
! 1423: if (xmlCatalogXMLFiles != NULL) {
! 1424: doc = (xmlCatalogEntryPtr)
! 1425: xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
! 1426: if (doc != NULL) {
! 1427: if (xmlDebugCatalogs)
! 1428: xmlGenericError(xmlGenericErrorContext,
! 1429: "Found %s in file hash\n", catal->URL);
! 1430:
! 1431: if (catal->type == XML_CATA_CATALOG)
! 1432: catal->children = doc->children;
! 1433: else
! 1434: catal->children = doc;
! 1435: catal->dealloc = 0;
! 1436: xmlRMutexUnlock(xmlCatalogMutex);
! 1437: return(0);
! 1438: }
! 1439: if (xmlDebugCatalogs)
! 1440: xmlGenericError(xmlGenericErrorContext,
! 1441: "%s not found in file hash\n", catal->URL);
! 1442: }
! 1443:
! 1444: /*
! 1445: * Fetch and parse. Note that xmlParseXMLCatalogFile does not
! 1446: * use the existing catalog, there is no recursion allowed at
! 1447: * that level.
! 1448: */
! 1449: doc = xmlParseXMLCatalogFile(catal->prefer, catal->URL);
! 1450: if (doc == NULL) {
! 1451: catal->type = XML_CATA_BROKEN_CATALOG;
! 1452: xmlRMutexUnlock(xmlCatalogMutex);
! 1453: return(-1);
! 1454: }
! 1455:
! 1456: if (catal->type == XML_CATA_CATALOG)
! 1457: catal->children = doc->children;
! 1458: else
! 1459: catal->children = doc;
! 1460:
! 1461: doc->dealloc = 1;
! 1462:
! 1463: if (xmlCatalogXMLFiles == NULL)
! 1464: xmlCatalogXMLFiles = xmlHashCreate(10);
! 1465: if (xmlCatalogXMLFiles != NULL) {
! 1466: if (xmlDebugCatalogs)
! 1467: xmlGenericError(xmlGenericErrorContext,
! 1468: "%s added to file hash\n", catal->URL);
! 1469: xmlHashAddEntry(xmlCatalogXMLFiles, catal->URL, doc);
! 1470: }
! 1471: xmlRMutexUnlock(xmlCatalogMutex);
! 1472: return(0);
! 1473: }
! 1474:
! 1475: /************************************************************************
! 1476: * *
! 1477: * XML Catalog handling *
! 1478: * *
! 1479: ************************************************************************/
! 1480:
! 1481: /**
! 1482: * xmlAddXMLCatalog:
! 1483: * @catal: top of an XML catalog
! 1484: * @type: the type of record to add to the catalog
! 1485: * @orig: the system, public or prefix to match (or NULL)
! 1486: * @replace: the replacement value for the match
! 1487: *
! 1488: * Add an entry in the XML catalog, it may overwrite existing but
! 1489: * different entries.
! 1490: *
! 1491: * Returns 0 if successful, -1 otherwise
! 1492: */
! 1493: static int
! 1494: xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type,
! 1495: const xmlChar *orig, const xmlChar *replace) {
! 1496: xmlCatalogEntryPtr cur;
! 1497: xmlCatalogEntryType typ;
! 1498: int doregister = 0;
! 1499:
! 1500: if ((catal == NULL) ||
! 1501: ((catal->type != XML_CATA_CATALOG) &&
! 1502: (catal->type != XML_CATA_BROKEN_CATALOG)))
! 1503: return(-1);
! 1504: if (catal->children == NULL) {
! 1505: xmlFetchXMLCatalogFile(catal);
! 1506: }
! 1507: if (catal->children == NULL)
! 1508: doregister = 1;
! 1509:
! 1510: typ = xmlGetXMLCatalogEntryType(type);
! 1511: if (typ == XML_CATA_NONE) {
! 1512: if (xmlDebugCatalogs)
! 1513: xmlGenericError(xmlGenericErrorContext,
! 1514: "Failed to add unknown element %s to catalog\n", type);
! 1515: return(-1);
! 1516: }
! 1517:
! 1518: cur = catal->children;
! 1519: /*
! 1520: * Might be a simple "update in place"
! 1521: */
! 1522: if (cur != NULL) {
! 1523: while (cur != NULL) {
! 1524: if ((orig != NULL) && (cur->type == typ) &&
! 1525: (xmlStrEqual(orig, cur->name))) {
! 1526: if (xmlDebugCatalogs)
! 1527: xmlGenericError(xmlGenericErrorContext,
! 1528: "Updating element %s to catalog\n", type);
! 1529: if (cur->value != NULL)
! 1530: xmlFree(cur->value);
! 1531: if (cur->URL != NULL)
! 1532: xmlFree(cur->URL);
! 1533: cur->value = xmlStrdup(replace);
! 1534: cur->URL = xmlStrdup(replace);
! 1535: return(0);
! 1536: }
! 1537: if (cur->next == NULL)
! 1538: break;
! 1539: cur = cur->next;
! 1540: }
! 1541: }
! 1542: if (xmlDebugCatalogs)
! 1543: xmlGenericError(xmlGenericErrorContext,
! 1544: "Adding element %s to catalog\n", type);
! 1545: if (cur == NULL)
! 1546: catal->children = xmlNewCatalogEntry(typ, orig, replace,
! 1547: NULL, catal->prefer, NULL);
! 1548: else
! 1549: cur->next = xmlNewCatalogEntry(typ, orig, replace,
! 1550: NULL, catal->prefer, NULL);
! 1551: if (doregister) {
! 1552: catal->type = XML_CATA_CATALOG;
! 1553: cur = xmlHashLookup(xmlCatalogXMLFiles, catal->URL);
! 1554: if (cur != NULL)
! 1555: cur->children = catal->children;
! 1556: }
! 1557:
! 1558: return(0);
! 1559: }
! 1560:
! 1561: /**
! 1562: * xmlDelXMLCatalog:
! 1563: * @catal: top of an XML catalog
! 1564: * @value: the value to remove from the catalog
! 1565: *
! 1566: * Remove entries in the XML catalog where the value or the URI
! 1567: * is equal to @value
! 1568: *
! 1569: * Returns the number of entries removed if successful, -1 otherwise
! 1570: */
! 1571: static int
! 1572: xmlDelXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *value) {
! 1573: xmlCatalogEntryPtr cur;
! 1574: int ret = 0;
! 1575:
! 1576: if ((catal == NULL) ||
! 1577: ((catal->type != XML_CATA_CATALOG) &&
! 1578: (catal->type != XML_CATA_BROKEN_CATALOG)))
! 1579: return(-1);
! 1580: if (value == NULL)
! 1581: return(-1);
! 1582: if (catal->children == NULL) {
! 1583: xmlFetchXMLCatalogFile(catal);
! 1584: }
! 1585:
! 1586: /*
! 1587: * Scan the children
! 1588: */
! 1589: cur = catal->children;
! 1590: while (cur != NULL) {
! 1591: if (((cur->name != NULL) && (xmlStrEqual(value, cur->name))) ||
! 1592: (xmlStrEqual(value, cur->value))) {
! 1593: if (xmlDebugCatalogs) {
! 1594: if (cur->name != NULL)
! 1595: xmlGenericError(xmlGenericErrorContext,
! 1596: "Removing element %s from catalog\n", cur->name);
! 1597: else
! 1598: xmlGenericError(xmlGenericErrorContext,
! 1599: "Removing element %s from catalog\n", cur->value);
! 1600: }
! 1601: cur->type = XML_CATA_REMOVED;
! 1602: }
! 1603: cur = cur->next;
! 1604: }
! 1605: return(ret);
! 1606: }
! 1607:
! 1608: /**
! 1609: * xmlCatalogXMLResolve:
! 1610: * @catal: a catalog list
! 1611: * @pubID: the public ID string
! 1612: * @sysID: the system ID string
! 1613: *
! 1614: * Do a complete resolution lookup of an External Identifier for a
! 1615: * list of catalog entries.
! 1616: *
! 1617: * Implements (or tries to) 7.1. External Identifier Resolution
! 1618: * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
! 1619: *
! 1620: * Returns the URI of the resource or NULL if not found
! 1621: */
! 1622: static xmlChar *
! 1623: xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
! 1624: const xmlChar *sysID) {
! 1625: xmlChar *ret = NULL;
! 1626: xmlCatalogEntryPtr cur;
! 1627: int haveDelegate = 0;
! 1628: int haveNext = 0;
! 1629:
! 1630: /*
! 1631: * protection against loops
! 1632: */
! 1633: if (catal->depth > MAX_CATAL_DEPTH) {
! 1634: xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
! 1635: "Detected recursion in catalog %s\n",
! 1636: catal->name, NULL, NULL);
! 1637: return(NULL);
! 1638: }
! 1639: catal->depth++;
! 1640:
! 1641: /*
! 1642: * First tries steps 2/ 3/ 4/ if a system ID is provided.
! 1643: */
! 1644: if (sysID != NULL) {
! 1645: xmlCatalogEntryPtr rewrite = NULL;
! 1646: int lenrewrite = 0, len;
! 1647: cur = catal;
! 1648: haveDelegate = 0;
! 1649: while (cur != NULL) {
! 1650: switch (cur->type) {
! 1651: case XML_CATA_SYSTEM:
! 1652: if (xmlStrEqual(sysID, cur->name)) {
! 1653: if (xmlDebugCatalogs)
! 1654: xmlGenericError(xmlGenericErrorContext,
! 1655: "Found system match %s, using %s\n",
! 1656: cur->name, cur->URL);
! 1657: catal->depth--;
! 1658: return(xmlStrdup(cur->URL));
! 1659: }
! 1660: break;
! 1661: case XML_CATA_REWRITE_SYSTEM:
! 1662: len = xmlStrlen(cur->name);
! 1663: if ((len > lenrewrite) &&
! 1664: (!xmlStrncmp(sysID, cur->name, len))) {
! 1665: lenrewrite = len;
! 1666: rewrite = cur;
! 1667: }
! 1668: break;
! 1669: case XML_CATA_DELEGATE_SYSTEM:
! 1670: if (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))
! 1671: haveDelegate++;
! 1672: break;
! 1673: case XML_CATA_NEXT_CATALOG:
! 1674: haveNext++;
! 1675: break;
! 1676: default:
! 1677: break;
! 1678: }
! 1679: cur = cur->next;
! 1680: }
! 1681: if (rewrite != NULL) {
! 1682: if (xmlDebugCatalogs)
! 1683: xmlGenericError(xmlGenericErrorContext,
! 1684: "Using rewriting rule %s\n", rewrite->name);
! 1685: ret = xmlStrdup(rewrite->URL);
! 1686: if (ret != NULL)
! 1687: ret = xmlStrcat(ret, &sysID[lenrewrite]);
! 1688: catal->depth--;
! 1689: return(ret);
! 1690: }
! 1691: if (haveDelegate) {
! 1692: const xmlChar *delegates[MAX_DELEGATE];
! 1693: int nbList = 0, i;
! 1694:
! 1695: /*
! 1696: * Assume the entries have been sorted by decreasing substring
! 1697: * matches when the list was produced.
! 1698: */
! 1699: cur = catal;
! 1700: while (cur != NULL) {
! 1701: if ((cur->type == XML_CATA_DELEGATE_SYSTEM) &&
! 1702: (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))) {
! 1703: for (i = 0;i < nbList;i++)
! 1704: if (xmlStrEqual(cur->URL, delegates[i]))
! 1705: break;
! 1706: if (i < nbList) {
! 1707: cur = cur->next;
! 1708: continue;
! 1709: }
! 1710: if (nbList < MAX_DELEGATE)
! 1711: delegates[nbList++] = cur->URL;
! 1712:
! 1713: if (cur->children == NULL) {
! 1714: xmlFetchXMLCatalogFile(cur);
! 1715: }
! 1716: if (cur->children != NULL) {
! 1717: if (xmlDebugCatalogs)
! 1718: xmlGenericError(xmlGenericErrorContext,
! 1719: "Trying system delegate %s\n", cur->URL);
! 1720: ret = xmlCatalogListXMLResolve(
! 1721: cur->children, NULL, sysID);
! 1722: if (ret != NULL) {
! 1723: catal->depth--;
! 1724: return(ret);
! 1725: }
! 1726: }
! 1727: }
! 1728: cur = cur->next;
! 1729: }
! 1730: /*
! 1731: * Apply the cut algorithm explained in 4/
! 1732: */
! 1733: catal->depth--;
! 1734: return(XML_CATAL_BREAK);
! 1735: }
! 1736: }
! 1737: /*
! 1738: * Then tries 5/ 6/ if a public ID is provided
! 1739: */
! 1740: if (pubID != NULL) {
! 1741: cur = catal;
! 1742: haveDelegate = 0;
! 1743: while (cur != NULL) {
! 1744: switch (cur->type) {
! 1745: case XML_CATA_PUBLIC:
! 1746: if (xmlStrEqual(pubID, cur->name)) {
! 1747: if (xmlDebugCatalogs)
! 1748: xmlGenericError(xmlGenericErrorContext,
! 1749: "Found public match %s\n", cur->name);
! 1750: catal->depth--;
! 1751: return(xmlStrdup(cur->URL));
! 1752: }
! 1753: break;
! 1754: case XML_CATA_DELEGATE_PUBLIC:
! 1755: if (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)) &&
! 1756: (cur->prefer == XML_CATA_PREFER_PUBLIC))
! 1757: haveDelegate++;
! 1758: break;
! 1759: case XML_CATA_NEXT_CATALOG:
! 1760: if (sysID == NULL)
! 1761: haveNext++;
! 1762: break;
! 1763: default:
! 1764: break;
! 1765: }
! 1766: cur = cur->next;
! 1767: }
! 1768: if (haveDelegate) {
! 1769: const xmlChar *delegates[MAX_DELEGATE];
! 1770: int nbList = 0, i;
! 1771:
! 1772: /*
! 1773: * Assume the entries have been sorted by decreasing substring
! 1774: * matches when the list was produced.
! 1775: */
! 1776: cur = catal;
! 1777: while (cur != NULL) {
! 1778: if ((cur->type == XML_CATA_DELEGATE_PUBLIC) &&
! 1779: (cur->prefer == XML_CATA_PREFER_PUBLIC) &&
! 1780: (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)))) {
! 1781:
! 1782: for (i = 0;i < nbList;i++)
! 1783: if (xmlStrEqual(cur->URL, delegates[i]))
! 1784: break;
! 1785: if (i < nbList) {
! 1786: cur = cur->next;
! 1787: continue;
! 1788: }
! 1789: if (nbList < MAX_DELEGATE)
! 1790: delegates[nbList++] = cur->URL;
! 1791:
! 1792: if (cur->children == NULL) {
! 1793: xmlFetchXMLCatalogFile(cur);
! 1794: }
! 1795: if (cur->children != NULL) {
! 1796: if (xmlDebugCatalogs)
! 1797: xmlGenericError(xmlGenericErrorContext,
! 1798: "Trying public delegate %s\n", cur->URL);
! 1799: ret = xmlCatalogListXMLResolve(
! 1800: cur->children, pubID, NULL);
! 1801: if (ret != NULL) {
! 1802: catal->depth--;
! 1803: return(ret);
! 1804: }
! 1805: }
! 1806: }
! 1807: cur = cur->next;
! 1808: }
! 1809: /*
! 1810: * Apply the cut algorithm explained in 4/
! 1811: */
! 1812: catal->depth--;
! 1813: return(XML_CATAL_BREAK);
! 1814: }
! 1815: }
! 1816: if (haveNext) {
! 1817: cur = catal;
! 1818: while (cur != NULL) {
! 1819: if (cur->type == XML_CATA_NEXT_CATALOG) {
! 1820: if (cur->children == NULL) {
! 1821: xmlFetchXMLCatalogFile(cur);
! 1822: }
! 1823: if (cur->children != NULL) {
! 1824: ret = xmlCatalogListXMLResolve(cur->children, pubID, sysID);
! 1825: if (ret != NULL) {
! 1826: catal->depth--;
! 1827: return(ret);
! 1828: } else if (catal->depth > MAX_CATAL_DEPTH) {
! 1829: return(NULL);
! 1830: }
! 1831: }
! 1832: }
! 1833: cur = cur->next;
! 1834: }
! 1835: }
! 1836:
! 1837: catal->depth--;
! 1838: return(NULL);
! 1839: }
! 1840:
! 1841: /**
! 1842: * xmlCatalogXMLResolveURI:
! 1843: * @catal: a catalog list
! 1844: * @URI: the URI
! 1845: * @sysID: the system ID string
! 1846: *
! 1847: * Do a complete resolution lookup of an External Identifier for a
! 1848: * list of catalog entries.
! 1849: *
! 1850: * Implements (or tries to) 7.2.2. URI Resolution
! 1851: * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
! 1852: *
! 1853: * Returns the URI of the resource or NULL if not found
! 1854: */
! 1855: static xmlChar *
! 1856: xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
! 1857: xmlChar *ret = NULL;
! 1858: xmlCatalogEntryPtr cur;
! 1859: int haveDelegate = 0;
! 1860: int haveNext = 0;
! 1861: xmlCatalogEntryPtr rewrite = NULL;
! 1862: int lenrewrite = 0, len;
! 1863:
! 1864: if (catal == NULL)
! 1865: return(NULL);
! 1866:
! 1867: if (URI == NULL)
! 1868: return(NULL);
! 1869:
! 1870: if (catal->depth > MAX_CATAL_DEPTH) {
! 1871: xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
! 1872: "Detected recursion in catalog %s\n",
! 1873: catal->name, NULL, NULL);
! 1874: return(NULL);
! 1875: }
! 1876:
! 1877: /*
! 1878: * First tries steps 2/ 3/ 4/ if a system ID is provided.
! 1879: */
! 1880: cur = catal;
! 1881: haveDelegate = 0;
! 1882: while (cur != NULL) {
! 1883: switch (cur->type) {
! 1884: case XML_CATA_URI:
! 1885: if (xmlStrEqual(URI, cur->name)) {
! 1886: if (xmlDebugCatalogs)
! 1887: xmlGenericError(xmlGenericErrorContext,
! 1888: "Found URI match %s\n", cur->name);
! 1889: return(xmlStrdup(cur->URL));
! 1890: }
! 1891: break;
! 1892: case XML_CATA_REWRITE_URI:
! 1893: len = xmlStrlen(cur->name);
! 1894: if ((len > lenrewrite) &&
! 1895: (!xmlStrncmp(URI, cur->name, len))) {
! 1896: lenrewrite = len;
! 1897: rewrite = cur;
! 1898: }
! 1899: break;
! 1900: case XML_CATA_DELEGATE_URI:
! 1901: if (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))
! 1902: haveDelegate++;
! 1903: break;
! 1904: case XML_CATA_NEXT_CATALOG:
! 1905: haveNext++;
! 1906: break;
! 1907: default:
! 1908: break;
! 1909: }
! 1910: cur = cur->next;
! 1911: }
! 1912: if (rewrite != NULL) {
! 1913: if (xmlDebugCatalogs)
! 1914: xmlGenericError(xmlGenericErrorContext,
! 1915: "Using rewriting rule %s\n", rewrite->name);
! 1916: ret = xmlStrdup(rewrite->URL);
! 1917: if (ret != NULL)
! 1918: ret = xmlStrcat(ret, &URI[lenrewrite]);
! 1919: return(ret);
! 1920: }
! 1921: if (haveDelegate) {
! 1922: const xmlChar *delegates[MAX_DELEGATE];
! 1923: int nbList = 0, i;
! 1924:
! 1925: /*
! 1926: * Assume the entries have been sorted by decreasing substring
! 1927: * matches when the list was produced.
! 1928: */
! 1929: cur = catal;
! 1930: while (cur != NULL) {
! 1931: if (((cur->type == XML_CATA_DELEGATE_SYSTEM) ||
! 1932: (cur->type == XML_CATA_DELEGATE_URI)) &&
! 1933: (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))) {
! 1934: for (i = 0;i < nbList;i++)
! 1935: if (xmlStrEqual(cur->URL, delegates[i]))
! 1936: break;
! 1937: if (i < nbList) {
! 1938: cur = cur->next;
! 1939: continue;
! 1940: }
! 1941: if (nbList < MAX_DELEGATE)
! 1942: delegates[nbList++] = cur->URL;
! 1943:
! 1944: if (cur->children == NULL) {
! 1945: xmlFetchXMLCatalogFile(cur);
! 1946: }
! 1947: if (cur->children != NULL) {
! 1948: if (xmlDebugCatalogs)
! 1949: xmlGenericError(xmlGenericErrorContext,
! 1950: "Trying URI delegate %s\n", cur->URL);
! 1951: ret = xmlCatalogListXMLResolveURI(
! 1952: cur->children, URI);
! 1953: if (ret != NULL)
! 1954: return(ret);
! 1955: }
! 1956: }
! 1957: cur = cur->next;
! 1958: }
! 1959: /*
! 1960: * Apply the cut algorithm explained in 4/
! 1961: */
! 1962: return(XML_CATAL_BREAK);
! 1963: }
! 1964: if (haveNext) {
! 1965: cur = catal;
! 1966: while (cur != NULL) {
! 1967: if (cur->type == XML_CATA_NEXT_CATALOG) {
! 1968: if (cur->children == NULL) {
! 1969: xmlFetchXMLCatalogFile(cur);
! 1970: }
! 1971: if (cur->children != NULL) {
! 1972: ret = xmlCatalogListXMLResolveURI(cur->children, URI);
! 1973: if (ret != NULL)
! 1974: return(ret);
! 1975: }
! 1976: }
! 1977: cur = cur->next;
! 1978: }
! 1979: }
! 1980:
! 1981: return(NULL);
! 1982: }
! 1983:
! 1984: /**
! 1985: * xmlCatalogListXMLResolve:
! 1986: * @catal: a catalog list
! 1987: * @pubID: the public ID string
! 1988: * @sysID: the system ID string
! 1989: *
! 1990: * Do a complete resolution lookup of an External Identifier for a
! 1991: * list of catalogs
! 1992: *
! 1993: * Implements (or tries to) 7.1. External Identifier Resolution
! 1994: * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
! 1995: *
! 1996: * Returns the URI of the resource or NULL if not found
! 1997: */
! 1998: static xmlChar *
! 1999: xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
! 2000: const xmlChar *sysID) {
! 2001: xmlChar *ret = NULL;
! 2002: xmlChar *urnID = NULL;
! 2003: xmlChar *normid;
! 2004:
! 2005: if (catal == NULL)
! 2006: return(NULL);
! 2007: if ((pubID == NULL) && (sysID == NULL))
! 2008: return(NULL);
! 2009:
! 2010: normid = xmlCatalogNormalizePublic(pubID);
! 2011: if (normid != NULL)
! 2012: pubID = (*normid != 0 ? normid : NULL);
! 2013:
! 2014: if (!xmlStrncmp(pubID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
! 2015: urnID = xmlCatalogUnWrapURN(pubID);
! 2016: if (xmlDebugCatalogs) {
! 2017: if (urnID == NULL)
! 2018: xmlGenericError(xmlGenericErrorContext,
! 2019: "Public URN ID %s expanded to NULL\n", pubID);
! 2020: else
! 2021: xmlGenericError(xmlGenericErrorContext,
! 2022: "Public URN ID expanded to %s\n", urnID);
! 2023: }
! 2024: ret = xmlCatalogListXMLResolve(catal, urnID, sysID);
! 2025: if (urnID != NULL)
! 2026: xmlFree(urnID);
! 2027: if (normid != NULL)
! 2028: xmlFree(normid);
! 2029: return(ret);
! 2030: }
! 2031: if (!xmlStrncmp(sysID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
! 2032: urnID = xmlCatalogUnWrapURN(sysID);
! 2033: if (xmlDebugCatalogs) {
! 2034: if (urnID == NULL)
! 2035: xmlGenericError(xmlGenericErrorContext,
! 2036: "System URN ID %s expanded to NULL\n", sysID);
! 2037: else
! 2038: xmlGenericError(xmlGenericErrorContext,
! 2039: "System URN ID expanded to %s\n", urnID);
! 2040: }
! 2041: if (pubID == NULL)
! 2042: ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
! 2043: else if (xmlStrEqual(pubID, urnID))
! 2044: ret = xmlCatalogListXMLResolve(catal, pubID, NULL);
! 2045: else {
! 2046: ret = xmlCatalogListXMLResolve(catal, pubID, urnID);
! 2047: }
! 2048: if (urnID != NULL)
! 2049: xmlFree(urnID);
! 2050: if (normid != NULL)
! 2051: xmlFree(normid);
! 2052: return(ret);
! 2053: }
! 2054: while (catal != NULL) {
! 2055: if (catal->type == XML_CATA_CATALOG) {
! 2056: if (catal->children == NULL) {
! 2057: xmlFetchXMLCatalogFile(catal);
! 2058: }
! 2059: if (catal->children != NULL) {
! 2060: ret = xmlCatalogXMLResolve(catal->children, pubID, sysID);
! 2061: if (ret != NULL) {
! 2062: break;
! 2063: } else if ((catal->children != NULL) &&
! 2064: (catal->children->depth > MAX_CATAL_DEPTH)) {
! 2065: ret = NULL;
! 2066: break;
! 2067: }
! 2068: }
! 2069: }
! 2070: catal = catal->next;
! 2071: }
! 2072: if (normid != NULL)
! 2073: xmlFree(normid);
! 2074: return(ret);
! 2075: }
! 2076:
! 2077: /**
! 2078: * xmlCatalogListXMLResolveURI:
! 2079: * @catal: a catalog list
! 2080: * @URI: the URI
! 2081: *
! 2082: * Do a complete resolution lookup of an URI for a list of catalogs
! 2083: *
! 2084: * Implements (or tries to) 7.2. URI Resolution
! 2085: * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
! 2086: *
! 2087: * Returns the URI of the resource or NULL if not found
! 2088: */
! 2089: static xmlChar *
! 2090: xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
! 2091: xmlChar *ret = NULL;
! 2092: xmlChar *urnID = NULL;
! 2093:
! 2094: if (catal == NULL)
! 2095: return(NULL);
! 2096: if (URI == NULL)
! 2097: return(NULL);
! 2098:
! 2099: if (!xmlStrncmp(URI, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
! 2100: urnID = xmlCatalogUnWrapURN(URI);
! 2101: if (xmlDebugCatalogs) {
! 2102: if (urnID == NULL)
! 2103: xmlGenericError(xmlGenericErrorContext,
! 2104: "URN ID %s expanded to NULL\n", URI);
! 2105: else
! 2106: xmlGenericError(xmlGenericErrorContext,
! 2107: "URN ID expanded to %s\n", urnID);
! 2108: }
! 2109: ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
! 2110: if (urnID != NULL)
! 2111: xmlFree(urnID);
! 2112: return(ret);
! 2113: }
! 2114: while (catal != NULL) {
! 2115: if (catal->type == XML_CATA_CATALOG) {
! 2116: if (catal->children == NULL) {
! 2117: xmlFetchXMLCatalogFile(catal);
! 2118: }
! 2119: if (catal->children != NULL) {
! 2120: ret = xmlCatalogXMLResolveURI(catal->children, URI);
! 2121: if (ret != NULL)
! 2122: return(ret);
! 2123: }
! 2124: }
! 2125: catal = catal->next;
! 2126: }
! 2127: return(ret);
! 2128: }
! 2129:
! 2130: /************************************************************************
! 2131: * *
! 2132: * The SGML Catalog parser *
! 2133: * *
! 2134: ************************************************************************/
! 2135:
! 2136:
! 2137: #define RAW *cur
! 2138: #define NEXT cur++;
! 2139: #define SKIP(x) cur += x;
! 2140:
! 2141: #define SKIP_BLANKS while (IS_BLANK_CH(*cur)) NEXT;
! 2142:
! 2143: /**
! 2144: * xmlParseSGMLCatalogComment:
! 2145: * @cur: the current character
! 2146: *
! 2147: * Skip a comment in an SGML catalog
! 2148: *
! 2149: * Returns new current character
! 2150: */
! 2151: static const xmlChar *
! 2152: xmlParseSGMLCatalogComment(const xmlChar *cur) {
! 2153: if ((cur[0] != '-') || (cur[1] != '-'))
! 2154: return(cur);
! 2155: SKIP(2);
! 2156: while ((cur[0] != 0) && ((cur[0] != '-') || ((cur[1] != '-'))))
! 2157: NEXT;
! 2158: if (cur[0] == 0) {
! 2159: return(NULL);
! 2160: }
! 2161: return(cur + 2);
! 2162: }
! 2163:
! 2164: /**
! 2165: * xmlParseSGMLCatalogPubid:
! 2166: * @cur: the current character
! 2167: * @id: the return location
! 2168: *
! 2169: * Parse an SGML catalog ID
! 2170: *
! 2171: * Returns new current character and store the value in @id
! 2172: */
! 2173: static const xmlChar *
! 2174: xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) {
! 2175: xmlChar *buf = NULL, *tmp;
! 2176: int len = 0;
! 2177: int size = 50;
! 2178: xmlChar stop;
! 2179: int count = 0;
! 2180:
! 2181: *id = NULL;
! 2182:
! 2183: if (RAW == '"') {
! 2184: NEXT;
! 2185: stop = '"';
! 2186: } else if (RAW == '\'') {
! 2187: NEXT;
! 2188: stop = '\'';
! 2189: } else {
! 2190: stop = ' ';
! 2191: }
! 2192: buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
! 2193: if (buf == NULL) {
! 2194: xmlCatalogErrMemory("allocating public ID");
! 2195: return(NULL);
! 2196: }
! 2197: while (IS_PUBIDCHAR_CH(*cur) || (*cur == '?')) {
! 2198: if ((*cur == stop) && (stop != ' '))
! 2199: break;
! 2200: if ((stop == ' ') && (IS_BLANK_CH(*cur)))
! 2201: break;
! 2202: if (len + 1 >= size) {
! 2203: size *= 2;
! 2204: tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
! 2205: if (tmp == NULL) {
! 2206: xmlCatalogErrMemory("allocating public ID");
! 2207: xmlFree(buf);
! 2208: return(NULL);
! 2209: }
! 2210: buf = tmp;
! 2211: }
! 2212: buf[len++] = *cur;
! 2213: count++;
! 2214: NEXT;
! 2215: }
! 2216: buf[len] = 0;
! 2217: if (stop == ' ') {
! 2218: if (!IS_BLANK_CH(*cur)) {
! 2219: xmlFree(buf);
! 2220: return(NULL);
! 2221: }
! 2222: } else {
! 2223: if (*cur != stop) {
! 2224: xmlFree(buf);
! 2225: return(NULL);
! 2226: }
! 2227: NEXT;
! 2228: }
! 2229: *id = buf;
! 2230: return(cur);
! 2231: }
! 2232:
! 2233: /**
! 2234: * xmlParseSGMLCatalogName:
! 2235: * @cur: the current character
! 2236: * @name: the return location
! 2237: *
! 2238: * Parse an SGML catalog name
! 2239: *
! 2240: * Returns new current character and store the value in @name
! 2241: */
! 2242: static const xmlChar *
! 2243: xmlParseSGMLCatalogName(const xmlChar *cur, xmlChar **name) {
! 2244: xmlChar buf[XML_MAX_NAMELEN + 5];
! 2245: int len = 0;
! 2246: int c;
! 2247:
! 2248: *name = NULL;
! 2249:
! 2250: /*
! 2251: * Handler for more complex cases
! 2252: */
! 2253: c = *cur;
! 2254: if ((!IS_LETTER(c) && (c != '_') && (c != ':'))) {
! 2255: return(NULL);
! 2256: }
! 2257:
! 2258: while (((IS_LETTER(c)) || (IS_DIGIT(c)) ||
! 2259: (c == '.') || (c == '-') ||
! 2260: (c == '_') || (c == ':'))) {
! 2261: buf[len++] = c;
! 2262: cur++;
! 2263: c = *cur;
! 2264: if (len >= XML_MAX_NAMELEN)
! 2265: return(NULL);
! 2266: }
! 2267: *name = xmlStrndup(buf, len);
! 2268: return(cur);
! 2269: }
! 2270:
! 2271: /**
! 2272: * xmlGetSGMLCatalogEntryType:
! 2273: * @name: the entry name
! 2274: *
! 2275: * Get the Catalog entry type for a given SGML Catalog name
! 2276: *
! 2277: * Returns Catalog entry type
! 2278: */
! 2279: static xmlCatalogEntryType
! 2280: xmlGetSGMLCatalogEntryType(const xmlChar *name) {
! 2281: xmlCatalogEntryType type = XML_CATA_NONE;
! 2282: if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
! 2283: type = SGML_CATA_SYSTEM;
! 2284: else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
! 2285: type = SGML_CATA_PUBLIC;
! 2286: else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
! 2287: type = SGML_CATA_DELEGATE;
! 2288: else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
! 2289: type = SGML_CATA_ENTITY;
! 2290: else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
! 2291: type = SGML_CATA_DOCTYPE;
! 2292: else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
! 2293: type = SGML_CATA_LINKTYPE;
! 2294: else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
! 2295: type = SGML_CATA_NOTATION;
! 2296: else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
! 2297: type = SGML_CATA_SGMLDECL;
! 2298: else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
! 2299: type = SGML_CATA_DOCUMENT;
! 2300: else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
! 2301: type = SGML_CATA_CATALOG;
! 2302: else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
! 2303: type = SGML_CATA_BASE;
! 2304: return(type);
! 2305: }
! 2306:
! 2307: /**
! 2308: * xmlParseSGMLCatalog:
! 2309: * @catal: the SGML Catalog
! 2310: * @value: the content of the SGML Catalog serialization
! 2311: * @file: the filepath for the catalog
! 2312: * @super: should this be handled as a Super Catalog in which case
! 2313: * parsing is not recursive
! 2314: *
! 2315: * Parse an SGML catalog content and fill up the @catal hash table with
! 2316: * the new entries found.
! 2317: *
! 2318: * Returns 0 in case of success, -1 in case of error.
! 2319: */
! 2320: static int
! 2321: xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value,
! 2322: const char *file, int super) {
! 2323: const xmlChar *cur = value;
! 2324: xmlChar *base = NULL;
! 2325: int res;
! 2326:
! 2327: if ((cur == NULL) || (file == NULL))
! 2328: return(-1);
! 2329: base = xmlStrdup((const xmlChar *) file);
! 2330:
! 2331: while ((cur != NULL) && (cur[0] != 0)) {
! 2332: SKIP_BLANKS;
! 2333: if (cur[0] == 0)
! 2334: break;
! 2335: if ((cur[0] == '-') && (cur[1] == '-')) {
! 2336: cur = xmlParseSGMLCatalogComment(cur);
! 2337: if (cur == NULL) {
! 2338: /* error */
! 2339: break;
! 2340: }
! 2341: } else {
! 2342: xmlChar *sysid = NULL;
! 2343: xmlChar *name = NULL;
! 2344: xmlCatalogEntryType type = XML_CATA_NONE;
! 2345:
! 2346: cur = xmlParseSGMLCatalogName(cur, &name);
! 2347: if (name == NULL) {
! 2348: /* error */
! 2349: break;
! 2350: }
! 2351: if (!IS_BLANK_CH(*cur)) {
! 2352: /* error */
! 2353: break;
! 2354: }
! 2355: SKIP_BLANKS;
! 2356: if (xmlStrEqual(name, (const xmlChar *) "SYSTEM"))
! 2357: type = SGML_CATA_SYSTEM;
! 2358: else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC"))
! 2359: type = SGML_CATA_PUBLIC;
! 2360: else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE"))
! 2361: type = SGML_CATA_DELEGATE;
! 2362: else if (xmlStrEqual(name, (const xmlChar *) "ENTITY"))
! 2363: type = SGML_CATA_ENTITY;
! 2364: else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE"))
! 2365: type = SGML_CATA_DOCTYPE;
! 2366: else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE"))
! 2367: type = SGML_CATA_LINKTYPE;
! 2368: else if (xmlStrEqual(name, (const xmlChar *) "NOTATION"))
! 2369: type = SGML_CATA_NOTATION;
! 2370: else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL"))
! 2371: type = SGML_CATA_SGMLDECL;
! 2372: else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT"))
! 2373: type = SGML_CATA_DOCUMENT;
! 2374: else if (xmlStrEqual(name, (const xmlChar *) "CATALOG"))
! 2375: type = SGML_CATA_CATALOG;
! 2376: else if (xmlStrEqual(name, (const xmlChar *) "BASE"))
! 2377: type = SGML_CATA_BASE;
! 2378: else if (xmlStrEqual(name, (const xmlChar *) "OVERRIDE")) {
! 2379: xmlFree(name);
! 2380: cur = xmlParseSGMLCatalogName(cur, &name);
! 2381: if (name == NULL) {
! 2382: /* error */
! 2383: break;
! 2384: }
! 2385: xmlFree(name);
! 2386: continue;
! 2387: }
! 2388: xmlFree(name);
! 2389: name = NULL;
! 2390:
! 2391: switch(type) {
! 2392: case SGML_CATA_ENTITY:
! 2393: if (*cur == '%')
! 2394: type = SGML_CATA_PENTITY;
! 2395: case SGML_CATA_PENTITY:
! 2396: case SGML_CATA_DOCTYPE:
! 2397: case SGML_CATA_LINKTYPE:
! 2398: case SGML_CATA_NOTATION:
! 2399: cur = xmlParseSGMLCatalogName(cur, &name);
! 2400: if (cur == NULL) {
! 2401: /* error */
! 2402: break;
! 2403: }
! 2404: if (!IS_BLANK_CH(*cur)) {
! 2405: /* error */
! 2406: break;
! 2407: }
! 2408: SKIP_BLANKS;
! 2409: cur = xmlParseSGMLCatalogPubid(cur, &sysid);
! 2410: if (cur == NULL) {
! 2411: /* error */
! 2412: break;
! 2413: }
! 2414: break;
! 2415: case SGML_CATA_PUBLIC:
! 2416: case SGML_CATA_SYSTEM:
! 2417: case SGML_CATA_DELEGATE:
! 2418: cur = xmlParseSGMLCatalogPubid(cur, &name);
! 2419: if (cur == NULL) {
! 2420: /* error */
! 2421: break;
! 2422: }
! 2423: if (type != SGML_CATA_SYSTEM) {
! 2424: xmlChar *normid;
! 2425:
! 2426: normid = xmlCatalogNormalizePublic(name);
! 2427: if (normid != NULL) {
! 2428: if (name != NULL)
! 2429: xmlFree(name);
! 2430: if (*normid != 0)
! 2431: name = normid;
! 2432: else {
! 2433: xmlFree(normid);
! 2434: name = NULL;
! 2435: }
! 2436: }
! 2437: }
! 2438: if (!IS_BLANK_CH(*cur)) {
! 2439: /* error */
! 2440: break;
! 2441: }
! 2442: SKIP_BLANKS;
! 2443: cur = xmlParseSGMLCatalogPubid(cur, &sysid);
! 2444: if (cur == NULL) {
! 2445: /* error */
! 2446: break;
! 2447: }
! 2448: break;
! 2449: case SGML_CATA_BASE:
! 2450: case SGML_CATA_CATALOG:
! 2451: case SGML_CATA_DOCUMENT:
! 2452: case SGML_CATA_SGMLDECL:
! 2453: cur = xmlParseSGMLCatalogPubid(cur, &sysid);
! 2454: if (cur == NULL) {
! 2455: /* error */
! 2456: break;
! 2457: }
! 2458: break;
! 2459: default:
! 2460: break;
! 2461: }
! 2462: if (cur == NULL) {
! 2463: if (name != NULL)
! 2464: xmlFree(name);
! 2465: if (sysid != NULL)
! 2466: xmlFree(sysid);
! 2467: break;
! 2468: } else if (type == SGML_CATA_BASE) {
! 2469: if (base != NULL)
! 2470: xmlFree(base);
! 2471: base = xmlStrdup(sysid);
! 2472: } else if ((type == SGML_CATA_PUBLIC) ||
! 2473: (type == SGML_CATA_SYSTEM)) {
! 2474: xmlChar *filename;
! 2475:
! 2476: filename = xmlBuildURI(sysid, base);
! 2477: if (filename != NULL) {
! 2478: xmlCatalogEntryPtr entry;
! 2479:
! 2480: entry = xmlNewCatalogEntry(type, name, filename,
! 2481: NULL, XML_CATA_PREFER_NONE, NULL);
! 2482: res = xmlHashAddEntry(catal->sgml, name, entry);
! 2483: if (res < 0) {
! 2484: xmlFreeCatalogEntry(entry);
! 2485: }
! 2486: xmlFree(filename);
! 2487: }
! 2488:
! 2489: } else if (type == SGML_CATA_CATALOG) {
! 2490: if (super) {
! 2491: xmlCatalogEntryPtr entry;
! 2492:
! 2493: entry = xmlNewCatalogEntry(type, sysid, NULL, NULL,
! 2494: XML_CATA_PREFER_NONE, NULL);
! 2495: res = xmlHashAddEntry(catal->sgml, sysid, entry);
! 2496: if (res < 0) {
! 2497: xmlFreeCatalogEntry(entry);
! 2498: }
! 2499: } else {
! 2500: xmlChar *filename;
! 2501:
! 2502: filename = xmlBuildURI(sysid, base);
! 2503: if (filename != NULL) {
! 2504: xmlExpandCatalog(catal, (const char *)filename);
! 2505: xmlFree(filename);
! 2506: }
! 2507: }
! 2508: }
! 2509: /*
! 2510: * drop anything else we won't handle it
! 2511: */
! 2512: if (name != NULL)
! 2513: xmlFree(name);
! 2514: if (sysid != NULL)
! 2515: xmlFree(sysid);
! 2516: }
! 2517: }
! 2518: if (base != NULL)
! 2519: xmlFree(base);
! 2520: if (cur == NULL)
! 2521: return(-1);
! 2522: return(0);
! 2523: }
! 2524:
! 2525: /************************************************************************
! 2526: * *
! 2527: * SGML Catalog handling *
! 2528: * *
! 2529: ************************************************************************/
! 2530:
! 2531: /**
! 2532: * xmlCatalogGetSGMLPublic:
! 2533: * @catal: an SGML catalog hash
! 2534: * @pubID: the public ID string
! 2535: *
! 2536: * Try to lookup the catalog local reference associated to a public ID
! 2537: *
! 2538: * Returns the local resource if found or NULL otherwise.
! 2539: */
! 2540: static const xmlChar *
! 2541: xmlCatalogGetSGMLPublic(xmlHashTablePtr catal, const xmlChar *pubID) {
! 2542: xmlCatalogEntryPtr entry;
! 2543: xmlChar *normid;
! 2544:
! 2545: if (catal == NULL)
! 2546: return(NULL);
! 2547:
! 2548: normid = xmlCatalogNormalizePublic(pubID);
! 2549: if (normid != NULL)
! 2550: pubID = (*normid != 0 ? normid : NULL);
! 2551:
! 2552: entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, pubID);
! 2553: if (entry == NULL) {
! 2554: if (normid != NULL)
! 2555: xmlFree(normid);
! 2556: return(NULL);
! 2557: }
! 2558: if (entry->type == SGML_CATA_PUBLIC) {
! 2559: if (normid != NULL)
! 2560: xmlFree(normid);
! 2561: return(entry->URL);
! 2562: }
! 2563: if (normid != NULL)
! 2564: xmlFree(normid);
! 2565: return(NULL);
! 2566: }
! 2567:
! 2568: /**
! 2569: * xmlCatalogGetSGMLSystem:
! 2570: * @catal: an SGML catalog hash
! 2571: * @sysID: the system ID string
! 2572: *
! 2573: * Try to lookup the catalog local reference for a system ID
! 2574: *
! 2575: * Returns the local resource if found or NULL otherwise.
! 2576: */
! 2577: static const xmlChar *
! 2578: xmlCatalogGetSGMLSystem(xmlHashTablePtr catal, const xmlChar *sysID) {
! 2579: xmlCatalogEntryPtr entry;
! 2580:
! 2581: if (catal == NULL)
! 2582: return(NULL);
! 2583:
! 2584: entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, sysID);
! 2585: if (entry == NULL)
! 2586: return(NULL);
! 2587: if (entry->type == SGML_CATA_SYSTEM)
! 2588: return(entry->URL);
! 2589: return(NULL);
! 2590: }
! 2591:
! 2592: /**
! 2593: * xmlCatalogSGMLResolve:
! 2594: * @catal: the SGML catalog
! 2595: * @pubID: the public ID string
! 2596: * @sysID: the system ID string
! 2597: *
! 2598: * Do a complete resolution lookup of an External Identifier
! 2599: *
! 2600: * Returns the URI of the resource or NULL if not found
! 2601: */
! 2602: static const xmlChar *
! 2603: xmlCatalogSGMLResolve(xmlCatalogPtr catal, const xmlChar *pubID,
! 2604: const xmlChar *sysID) {
! 2605: const xmlChar *ret = NULL;
! 2606:
! 2607: if (catal->sgml == NULL)
! 2608: return(NULL);
! 2609:
! 2610: if (pubID != NULL)
! 2611: ret = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
! 2612: if (ret != NULL)
! 2613: return(ret);
! 2614: if (sysID != NULL)
! 2615: ret = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
! 2616: if (ret != NULL)
! 2617: return(ret);
! 2618: return(NULL);
! 2619: }
! 2620:
! 2621: /************************************************************************
! 2622: * *
! 2623: * Specific Public interfaces *
! 2624: * *
! 2625: ************************************************************************/
! 2626:
! 2627: /**
! 2628: * xmlLoadSGMLSuperCatalog:
! 2629: * @filename: a file path
! 2630: *
! 2631: * Load an SGML super catalog. It won't expand CATALOG or DELEGATE
! 2632: * references. This is only needed for manipulating SGML Super Catalogs
! 2633: * like adding and removing CATALOG or DELEGATE entries.
! 2634: *
! 2635: * Returns the catalog parsed or NULL in case of error
! 2636: */
! 2637: xmlCatalogPtr
! 2638: xmlLoadSGMLSuperCatalog(const char *filename)
! 2639: {
! 2640: xmlChar *content;
! 2641: xmlCatalogPtr catal;
! 2642: int ret;
! 2643:
! 2644: content = xmlLoadFileContent(filename);
! 2645: if (content == NULL)
! 2646: return(NULL);
! 2647:
! 2648: catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
! 2649: if (catal == NULL) {
! 2650: xmlFree(content);
! 2651: return(NULL);
! 2652: }
! 2653:
! 2654: ret = xmlParseSGMLCatalog(catal, content, filename, 1);
! 2655: xmlFree(content);
! 2656: if (ret < 0) {
! 2657: xmlFreeCatalog(catal);
! 2658: return(NULL);
! 2659: }
! 2660: return (catal);
! 2661: }
! 2662:
! 2663: /**
! 2664: * xmlLoadACatalog:
! 2665: * @filename: a file path
! 2666: *
! 2667: * Load the catalog and build the associated data structures.
! 2668: * This can be either an XML Catalog or an SGML Catalog
! 2669: * It will recurse in SGML CATALOG entries. On the other hand XML
! 2670: * Catalogs are not handled recursively.
! 2671: *
! 2672: * Returns the catalog parsed or NULL in case of error
! 2673: */
! 2674: xmlCatalogPtr
! 2675: xmlLoadACatalog(const char *filename)
! 2676: {
! 2677: xmlChar *content;
! 2678: xmlChar *first;
! 2679: xmlCatalogPtr catal;
! 2680: int ret;
! 2681:
! 2682: content = xmlLoadFileContent(filename);
! 2683: if (content == NULL)
! 2684: return(NULL);
! 2685:
! 2686:
! 2687: first = content;
! 2688:
! 2689: while ((*first != 0) && (*first != '-') && (*first != '<') &&
! 2690: (!(((*first >= 'A') && (*first <= 'Z')) ||
! 2691: ((*first >= 'a') && (*first <= 'z')))))
! 2692: first++;
! 2693:
! 2694: if (*first != '<') {
! 2695: catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
! 2696: if (catal == NULL) {
! 2697: xmlFree(content);
! 2698: return(NULL);
! 2699: }
! 2700: ret = xmlParseSGMLCatalog(catal, content, filename, 0);
! 2701: if (ret < 0) {
! 2702: xmlFreeCatalog(catal);
! 2703: xmlFree(content);
! 2704: return(NULL);
! 2705: }
! 2706: } else {
! 2707: catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer);
! 2708: if (catal == NULL) {
! 2709: xmlFree(content);
! 2710: return(NULL);
! 2711: }
! 2712: catal->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
! 2713: NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
! 2714: }
! 2715: xmlFree(content);
! 2716: return (catal);
! 2717: }
! 2718:
! 2719: /**
! 2720: * xmlExpandCatalog:
! 2721: * @catal: a catalog
! 2722: * @filename: a file path
! 2723: *
! 2724: * Load the catalog and expand the existing catal structure.
! 2725: * This can be either an XML Catalog or an SGML Catalog
! 2726: *
! 2727: * Returns 0 in case of success, -1 in case of error
! 2728: */
! 2729: static int
! 2730: xmlExpandCatalog(xmlCatalogPtr catal, const char *filename)
! 2731: {
! 2732: int ret;
! 2733:
! 2734: if ((catal == NULL) || (filename == NULL))
! 2735: return(-1);
! 2736:
! 2737:
! 2738: if (catal->type == XML_SGML_CATALOG_TYPE) {
! 2739: xmlChar *content;
! 2740:
! 2741: content = xmlLoadFileContent(filename);
! 2742: if (content == NULL)
! 2743: return(-1);
! 2744:
! 2745: ret = xmlParseSGMLCatalog(catal, content, filename, 0);
! 2746: if (ret < 0) {
! 2747: xmlFree(content);
! 2748: return(-1);
! 2749: }
! 2750: xmlFree(content);
! 2751: } else {
! 2752: xmlCatalogEntryPtr tmp, cur;
! 2753: tmp = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
! 2754: NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
! 2755:
! 2756: cur = catal->xml;
! 2757: if (cur == NULL) {
! 2758: catal->xml = tmp;
! 2759: } else {
! 2760: while (cur->next != NULL) cur = cur->next;
! 2761: cur->next = tmp;
! 2762: }
! 2763: }
! 2764: return (0);
! 2765: }
! 2766:
! 2767: /**
! 2768: * xmlACatalogResolveSystem:
! 2769: * @catal: a Catalog
! 2770: * @sysID: the system ID string
! 2771: *
! 2772: * Try to lookup the catalog resource for a system ID
! 2773: *
! 2774: * Returns the resource if found or NULL otherwise, the value returned
! 2775: * must be freed by the caller.
! 2776: */
! 2777: xmlChar *
! 2778: xmlACatalogResolveSystem(xmlCatalogPtr catal, const xmlChar *sysID) {
! 2779: xmlChar *ret = NULL;
! 2780:
! 2781: if ((sysID == NULL) || (catal == NULL))
! 2782: return(NULL);
! 2783:
! 2784: if (xmlDebugCatalogs)
! 2785: xmlGenericError(xmlGenericErrorContext,
! 2786: "Resolve sysID %s\n", sysID);
! 2787:
! 2788: if (catal->type == XML_XML_CATALOG_TYPE) {
! 2789: ret = xmlCatalogListXMLResolve(catal->xml, NULL, sysID);
! 2790: if (ret == XML_CATAL_BREAK)
! 2791: ret = NULL;
! 2792: } else {
! 2793: const xmlChar *sgml;
! 2794:
! 2795: sgml = xmlCatalogGetSGMLSystem(catal->sgml, sysID);
! 2796: if (sgml != NULL)
! 2797: ret = xmlStrdup(sgml);
! 2798: }
! 2799: return(ret);
! 2800: }
! 2801:
! 2802: /**
! 2803: * xmlACatalogResolvePublic:
! 2804: * @catal: a Catalog
! 2805: * @pubID: the public ID string
! 2806: *
! 2807: * Try to lookup the catalog local reference associated to a public ID in that catalog
! 2808: *
! 2809: * Returns the local resource if found or NULL otherwise, the value returned
! 2810: * must be freed by the caller.
! 2811: */
! 2812: xmlChar *
! 2813: xmlACatalogResolvePublic(xmlCatalogPtr catal, const xmlChar *pubID) {
! 2814: xmlChar *ret = NULL;
! 2815:
! 2816: if ((pubID == NULL) || (catal == NULL))
! 2817: return(NULL);
! 2818:
! 2819: if (xmlDebugCatalogs)
! 2820: xmlGenericError(xmlGenericErrorContext,
! 2821: "Resolve pubID %s\n", pubID);
! 2822:
! 2823: if (catal->type == XML_XML_CATALOG_TYPE) {
! 2824: ret = xmlCatalogListXMLResolve(catal->xml, pubID, NULL);
! 2825: if (ret == XML_CATAL_BREAK)
! 2826: ret = NULL;
! 2827: } else {
! 2828: const xmlChar *sgml;
! 2829:
! 2830: sgml = xmlCatalogGetSGMLPublic(catal->sgml, pubID);
! 2831: if (sgml != NULL)
! 2832: ret = xmlStrdup(sgml);
! 2833: }
! 2834: return(ret);
! 2835: }
! 2836:
! 2837: /**
! 2838: * xmlACatalogResolve:
! 2839: * @catal: a Catalog
! 2840: * @pubID: the public ID string
! 2841: * @sysID: the system ID string
! 2842: *
! 2843: * Do a complete resolution lookup of an External Identifier
! 2844: *
! 2845: * Returns the URI of the resource or NULL if not found, it must be freed
! 2846: * by the caller.
! 2847: */
! 2848: xmlChar *
! 2849: xmlACatalogResolve(xmlCatalogPtr catal, const xmlChar * pubID,
! 2850: const xmlChar * sysID)
! 2851: {
! 2852: xmlChar *ret = NULL;
! 2853:
! 2854: if (((pubID == NULL) && (sysID == NULL)) || (catal == NULL))
! 2855: return (NULL);
! 2856:
! 2857: if (xmlDebugCatalogs) {
! 2858: if ((pubID != NULL) && (sysID != NULL)) {
! 2859: xmlGenericError(xmlGenericErrorContext,
! 2860: "Resolve: pubID %s sysID %s\n", pubID, sysID);
! 2861: } else if (pubID != NULL) {
! 2862: xmlGenericError(xmlGenericErrorContext,
! 2863: "Resolve: pubID %s\n", pubID);
! 2864: } else {
! 2865: xmlGenericError(xmlGenericErrorContext,
! 2866: "Resolve: sysID %s\n", sysID);
! 2867: }
! 2868: }
! 2869:
! 2870: if (catal->type == XML_XML_CATALOG_TYPE) {
! 2871: ret = xmlCatalogListXMLResolve(catal->xml, pubID, sysID);
! 2872: if (ret == XML_CATAL_BREAK)
! 2873: ret = NULL;
! 2874: } else {
! 2875: const xmlChar *sgml;
! 2876:
! 2877: sgml = xmlCatalogSGMLResolve(catal, pubID, sysID);
! 2878: if (sgml != NULL)
! 2879: ret = xmlStrdup(sgml);
! 2880: }
! 2881: return (ret);
! 2882: }
! 2883:
! 2884: /**
! 2885: * xmlACatalogResolveURI:
! 2886: * @catal: a Catalog
! 2887: * @URI: the URI
! 2888: *
! 2889: * Do a complete resolution lookup of an URI
! 2890: *
! 2891: * Returns the URI of the resource or NULL if not found, it must be freed
! 2892: * by the caller.
! 2893: */
! 2894: xmlChar *
! 2895: xmlACatalogResolveURI(xmlCatalogPtr catal, const xmlChar *URI) {
! 2896: xmlChar *ret = NULL;
! 2897:
! 2898: if ((URI == NULL) || (catal == NULL))
! 2899: return(NULL);
! 2900:
! 2901: if (xmlDebugCatalogs)
! 2902: xmlGenericError(xmlGenericErrorContext,
! 2903: "Resolve URI %s\n", URI);
! 2904:
! 2905: if (catal->type == XML_XML_CATALOG_TYPE) {
! 2906: ret = xmlCatalogListXMLResolveURI(catal->xml, URI);
! 2907: if (ret == XML_CATAL_BREAK)
! 2908: ret = NULL;
! 2909: } else {
! 2910: const xmlChar *sgml;
! 2911:
! 2912: sgml = xmlCatalogSGMLResolve(catal, NULL, URI);
! 2913: if (sgml != NULL)
! 2914: ret = xmlStrdup(sgml);
! 2915: }
! 2916: return(ret);
! 2917: }
! 2918:
! 2919: #ifdef LIBXML_OUTPUT_ENABLED
! 2920: /**
! 2921: * xmlACatalogDump:
! 2922: * @catal: a Catalog
! 2923: * @out: the file.
! 2924: *
! 2925: * Dump the given catalog to the given file.
! 2926: */
! 2927: void
! 2928: xmlACatalogDump(xmlCatalogPtr catal, FILE *out) {
! 2929: if ((out == NULL) || (catal == NULL))
! 2930: return;
! 2931:
! 2932: if (catal->type == XML_XML_CATALOG_TYPE) {
! 2933: xmlDumpXMLCatalog(out, catal->xml);
! 2934: } else {
! 2935: xmlHashScan(catal->sgml,
! 2936: (xmlHashScanner) xmlCatalogDumpEntry, out);
! 2937: }
! 2938: }
! 2939: #endif /* LIBXML_OUTPUT_ENABLED */
! 2940:
! 2941: /**
! 2942: * xmlACatalogAdd:
! 2943: * @catal: a Catalog
! 2944: * @type: the type of record to add to the catalog
! 2945: * @orig: the system, public or prefix to match
! 2946: * @replace: the replacement value for the match
! 2947: *
! 2948: * Add an entry in the catalog, it may overwrite existing but
! 2949: * different entries.
! 2950: *
! 2951: * Returns 0 if successful, -1 otherwise
! 2952: */
! 2953: int
! 2954: xmlACatalogAdd(xmlCatalogPtr catal, const xmlChar * type,
! 2955: const xmlChar * orig, const xmlChar * replace)
! 2956: {
! 2957: int res = -1;
! 2958:
! 2959: if (catal == NULL)
! 2960: return(-1);
! 2961:
! 2962: if (catal->type == XML_XML_CATALOG_TYPE) {
! 2963: res = xmlAddXMLCatalog(catal->xml, type, orig, replace);
! 2964: } else {
! 2965: xmlCatalogEntryType cattype;
! 2966:
! 2967: cattype = xmlGetSGMLCatalogEntryType(type);
! 2968: if (cattype != XML_CATA_NONE) {
! 2969: xmlCatalogEntryPtr entry;
! 2970:
! 2971: entry = xmlNewCatalogEntry(cattype, orig, replace, NULL,
! 2972: XML_CATA_PREFER_NONE, NULL);
! 2973: if (catal->sgml == NULL)
! 2974: catal->sgml = xmlHashCreate(10);
! 2975: res = xmlHashAddEntry(catal->sgml, orig, entry);
! 2976: }
! 2977: }
! 2978: return (res);
! 2979: }
! 2980:
! 2981: /**
! 2982: * xmlACatalogRemove:
! 2983: * @catal: a Catalog
! 2984: * @value: the value to remove
! 2985: *
! 2986: * Remove an entry from the catalog
! 2987: *
! 2988: * Returns the number of entries removed if successful, -1 otherwise
! 2989: */
! 2990: int
! 2991: xmlACatalogRemove(xmlCatalogPtr catal, const xmlChar *value) {
! 2992: int res = -1;
! 2993:
! 2994: if ((catal == NULL) || (value == NULL))
! 2995: return(-1);
! 2996:
! 2997: if (catal->type == XML_XML_CATALOG_TYPE) {
! 2998: res = xmlDelXMLCatalog(catal->xml, value);
! 2999: } else {
! 3000: res = xmlHashRemoveEntry(catal->sgml, value,
! 3001: (xmlHashDeallocator) xmlFreeCatalogEntry);
! 3002: if (res == 0)
! 3003: res = 1;
! 3004: }
! 3005: return(res);
! 3006: }
! 3007:
! 3008: /**
! 3009: * xmlNewCatalog:
! 3010: * @sgml: should this create an SGML catalog
! 3011: *
! 3012: * create a new Catalog.
! 3013: *
! 3014: * Returns the xmlCatalogPtr or NULL in case of error
! 3015: */
! 3016: xmlCatalogPtr
! 3017: xmlNewCatalog(int sgml) {
! 3018: xmlCatalogPtr catal = NULL;
! 3019:
! 3020: if (sgml) {
! 3021: catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE,
! 3022: xmlCatalogDefaultPrefer);
! 3023: if ((catal != NULL) && (catal->sgml == NULL))
! 3024: catal->sgml = xmlHashCreate(10);
! 3025: } else
! 3026: catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
! 3027: xmlCatalogDefaultPrefer);
! 3028: return(catal);
! 3029: }
! 3030:
! 3031: /**
! 3032: * xmlCatalogIsEmpty:
! 3033: * @catal: should this create an SGML catalog
! 3034: *
! 3035: * Check is a catalog is empty
! 3036: *
! 3037: * Returns 1 if the catalog is empty, 0 if not, amd -1 in case of error.
! 3038: */
! 3039: int
! 3040: xmlCatalogIsEmpty(xmlCatalogPtr catal) {
! 3041: if (catal == NULL)
! 3042: return(-1);
! 3043:
! 3044: if (catal->type == XML_XML_CATALOG_TYPE) {
! 3045: if (catal->xml == NULL)
! 3046: return(1);
! 3047: if ((catal->xml->type != XML_CATA_CATALOG) &&
! 3048: (catal->xml->type != XML_CATA_BROKEN_CATALOG))
! 3049: return(-1);
! 3050: if (catal->xml->children == NULL)
! 3051: return(1);
! 3052: return(0);
! 3053: } else {
! 3054: int res;
! 3055:
! 3056: if (catal->sgml == NULL)
! 3057: return(1);
! 3058: res = xmlHashSize(catal->sgml);
! 3059: if (res == 0)
! 3060: return(1);
! 3061: if (res < 0)
! 3062: return(-1);
! 3063: }
! 3064: return(0);
! 3065: }
! 3066:
! 3067: /************************************************************************
! 3068: * *
! 3069: * Public interfaces manipulating the global shared default catalog *
! 3070: * *
! 3071: ************************************************************************/
! 3072:
! 3073: /**
! 3074: * xmlInitializeCatalogData:
! 3075: *
! 3076: * Do the catalog initialization only of global data, doesn't try to load
! 3077: * any catalog actually.
! 3078: * this function is not thread safe, catalog initialization should
! 3079: * preferably be done once at startup
! 3080: */
! 3081: static void
! 3082: xmlInitializeCatalogData(void) {
! 3083: if (xmlCatalogInitialized != 0)
! 3084: return;
! 3085:
! 3086: if (getenv("XML_DEBUG_CATALOG"))
! 3087: xmlDebugCatalogs = 1;
! 3088: xmlCatalogMutex = xmlNewRMutex();
! 3089:
! 3090: xmlCatalogInitialized = 1;
! 3091: }
! 3092: /**
! 3093: * xmlInitializeCatalog:
! 3094: *
! 3095: * Do the catalog initialization.
! 3096: * this function is not thread safe, catalog initialization should
! 3097: * preferably be done once at startup
! 3098: */
! 3099: void
! 3100: xmlInitializeCatalog(void) {
! 3101: if (xmlCatalogInitialized != 0)
! 3102: return;
! 3103:
! 3104: xmlInitializeCatalogData();
! 3105: xmlRMutexLock(xmlCatalogMutex);
! 3106:
! 3107: if (getenv("XML_DEBUG_CATALOG"))
! 3108: xmlDebugCatalogs = 1;
! 3109:
! 3110: if (xmlDefaultCatalog == NULL) {
! 3111: const char *catalogs;
! 3112: char *path;
! 3113: const char *cur, *paths;
! 3114: xmlCatalogPtr catal;
! 3115: xmlCatalogEntryPtr *nextent;
! 3116:
! 3117: catalogs = (const char *) getenv("XML_CATALOG_FILES");
! 3118: if (catalogs == NULL)
! 3119: #if defined(_WIN32) && defined(_MSC_VER)
! 3120: {
! 3121: void* hmodule;
! 3122: hmodule = GetModuleHandleA("libxml2.dll");
! 3123: if (hmodule == NULL)
! 3124: hmodule = GetModuleHandleA(NULL);
! 3125: if (hmodule != NULL) {
! 3126: char buf[256];
! 3127: unsigned long len = GetModuleFileNameA(hmodule, buf, 255);
! 3128: if (len != 0) {
! 3129: char* p = &(buf[len]);
! 3130: while (*p != '\\' && p > buf)
! 3131: p--;
! 3132: if (p != buf) {
! 3133: xmlChar* uri;
! 3134: strncpy(p, "\\..\\etc\\catalog", 255 - (p - buf));
! 3135: uri = xmlCanonicPath(buf);
! 3136: if (uri != NULL) {
! 3137: strncpy(XML_XML_DEFAULT_CATALOG, uri, 255);
! 3138: xmlFree(uri);
! 3139: }
! 3140: }
! 3141: }
! 3142: }
! 3143: catalogs = XML_XML_DEFAULT_CATALOG;
! 3144: }
! 3145: #else
! 3146: catalogs = XML_XML_DEFAULT_CATALOG;
! 3147: #endif
! 3148:
! 3149: catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
! 3150: xmlCatalogDefaultPrefer);
! 3151: if (catal != NULL) {
! 3152: /* the XML_CATALOG_FILES envvar is allowed to contain a
! 3153: space-separated list of entries. */
! 3154: cur = catalogs;
! 3155: nextent = &catal->xml;
! 3156: while (*cur != '\0') {
! 3157: while (xmlIsBlank_ch(*cur))
! 3158: cur++;
! 3159: if (*cur != 0) {
! 3160: paths = cur;
! 3161: while ((*cur != 0) && (!xmlIsBlank_ch(*cur)))
! 3162: cur++;
! 3163: path = (char *) xmlStrndup((const xmlChar *)paths, cur - paths);
! 3164: if (path != NULL) {
! 3165: *nextent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
! 3166: NULL, BAD_CAST path, xmlCatalogDefaultPrefer, NULL);
! 3167: if (*nextent != NULL)
! 3168: nextent = &((*nextent)->next);
! 3169: xmlFree(path);
! 3170: }
! 3171: }
! 3172: }
! 3173: xmlDefaultCatalog = catal;
! 3174: }
! 3175: }
! 3176:
! 3177: xmlRMutexUnlock(xmlCatalogMutex);
! 3178: }
! 3179:
! 3180:
! 3181: /**
! 3182: * xmlLoadCatalog:
! 3183: * @filename: a file path
! 3184: *
! 3185: * Load the catalog and makes its definitions effective for the default
! 3186: * external entity loader. It will recurse in SGML CATALOG entries.
! 3187: * this function is not thread safe, catalog initialization should
! 3188: * preferably be done once at startup
! 3189: *
! 3190: * Returns 0 in case of success -1 in case of error
! 3191: */
! 3192: int
! 3193: xmlLoadCatalog(const char *filename)
! 3194: {
! 3195: int ret;
! 3196: xmlCatalogPtr catal;
! 3197:
! 3198: if (!xmlCatalogInitialized)
! 3199: xmlInitializeCatalogData();
! 3200:
! 3201: xmlRMutexLock(xmlCatalogMutex);
! 3202:
! 3203: if (xmlDefaultCatalog == NULL) {
! 3204: catal = xmlLoadACatalog(filename);
! 3205: if (catal == NULL) {
! 3206: xmlRMutexUnlock(xmlCatalogMutex);
! 3207: return(-1);
! 3208: }
! 3209:
! 3210: xmlDefaultCatalog = catal;
! 3211: xmlRMutexUnlock(xmlCatalogMutex);
! 3212: return(0);
! 3213: }
! 3214:
! 3215: ret = xmlExpandCatalog(xmlDefaultCatalog, filename);
! 3216: xmlRMutexUnlock(xmlCatalogMutex);
! 3217: return(ret);
! 3218: }
! 3219:
! 3220: /**
! 3221: * xmlLoadCatalogs:
! 3222: * @pathss: a list of directories separated by a colon or a space.
! 3223: *
! 3224: * Load the catalogs and makes their definitions effective for the default
! 3225: * external entity loader.
! 3226: * this function is not thread safe, catalog initialization should
! 3227: * preferably be done once at startup
! 3228: */
! 3229: void
! 3230: xmlLoadCatalogs(const char *pathss) {
! 3231: const char *cur;
! 3232: const char *paths;
! 3233: xmlChar *path;
! 3234: #ifdef _WIN32
! 3235: int i, iLen;
! 3236: #endif
! 3237:
! 3238: if (pathss == NULL)
! 3239: return;
! 3240:
! 3241: cur = pathss;
! 3242: while (*cur != 0) {
! 3243: while (xmlIsBlank_ch(*cur)) cur++;
! 3244: if (*cur != 0) {
! 3245: paths = cur;
! 3246: while ((*cur != 0) && (*cur != PATH_SEAPARATOR) && (!xmlIsBlank_ch(*cur)))
! 3247: cur++;
! 3248: path = xmlStrndup((const xmlChar *)paths, cur - paths);
! 3249: #ifdef _WIN32
! 3250: iLen = strlen(path);
! 3251: for(i = 0; i < iLen; i++) {
! 3252: if(path[i] == '\\') {
! 3253: path[i] = '/';
! 3254: }
! 3255: }
! 3256: #endif
! 3257: if (path != NULL) {
! 3258: xmlLoadCatalog((const char *) path);
! 3259: xmlFree(path);
! 3260: }
! 3261: }
! 3262: while (*cur == PATH_SEAPARATOR)
! 3263: cur++;
! 3264: }
! 3265: }
! 3266:
! 3267: /**
! 3268: * xmlCatalogCleanup:
! 3269: *
! 3270: * Free up all the memory associated with catalogs
! 3271: */
! 3272: void
! 3273: xmlCatalogCleanup(void) {
! 3274: if (xmlCatalogInitialized == 0)
! 3275: return;
! 3276:
! 3277: xmlRMutexLock(xmlCatalogMutex);
! 3278: if (xmlDebugCatalogs)
! 3279: xmlGenericError(xmlGenericErrorContext,
! 3280: "Catalogs cleanup\n");
! 3281: if (xmlCatalogXMLFiles != NULL)
! 3282: xmlHashFree(xmlCatalogXMLFiles,
! 3283: (xmlHashDeallocator)xmlFreeCatalogHashEntryList);
! 3284: xmlCatalogXMLFiles = NULL;
! 3285: if (xmlDefaultCatalog != NULL)
! 3286: xmlFreeCatalog(xmlDefaultCatalog);
! 3287: xmlDefaultCatalog = NULL;
! 3288: xmlDebugCatalogs = 0;
! 3289: xmlCatalogInitialized = 0;
! 3290: xmlRMutexUnlock(xmlCatalogMutex);
! 3291: xmlFreeRMutex(xmlCatalogMutex);
! 3292: }
! 3293:
! 3294: /**
! 3295: * xmlCatalogResolveSystem:
! 3296: * @sysID: the system ID string
! 3297: *
! 3298: * Try to lookup the catalog resource for a system ID
! 3299: *
! 3300: * Returns the resource if found or NULL otherwise, the value returned
! 3301: * must be freed by the caller.
! 3302: */
! 3303: xmlChar *
! 3304: xmlCatalogResolveSystem(const xmlChar *sysID) {
! 3305: xmlChar *ret;
! 3306:
! 3307: if (!xmlCatalogInitialized)
! 3308: xmlInitializeCatalog();
! 3309:
! 3310: ret = xmlACatalogResolveSystem(xmlDefaultCatalog, sysID);
! 3311: return(ret);
! 3312: }
! 3313:
! 3314: /**
! 3315: * xmlCatalogResolvePublic:
! 3316: * @pubID: the public ID string
! 3317: *
! 3318: * Try to lookup the catalog reference associated to a public ID
! 3319: *
! 3320: * Returns the resource if found or NULL otherwise, the value returned
! 3321: * must be freed by the caller.
! 3322: */
! 3323: xmlChar *
! 3324: xmlCatalogResolvePublic(const xmlChar *pubID) {
! 3325: xmlChar *ret;
! 3326:
! 3327: if (!xmlCatalogInitialized)
! 3328: xmlInitializeCatalog();
! 3329:
! 3330: ret = xmlACatalogResolvePublic(xmlDefaultCatalog, pubID);
! 3331: return(ret);
! 3332: }
! 3333:
! 3334: /**
! 3335: * xmlCatalogResolve:
! 3336: * @pubID: the public ID string
! 3337: * @sysID: the system ID string
! 3338: *
! 3339: * Do a complete resolution lookup of an External Identifier
! 3340: *
! 3341: * Returns the URI of the resource or NULL if not found, it must be freed
! 3342: * by the caller.
! 3343: */
! 3344: xmlChar *
! 3345: xmlCatalogResolve(const xmlChar *pubID, const xmlChar *sysID) {
! 3346: xmlChar *ret;
! 3347:
! 3348: if (!xmlCatalogInitialized)
! 3349: xmlInitializeCatalog();
! 3350:
! 3351: ret = xmlACatalogResolve(xmlDefaultCatalog, pubID, sysID);
! 3352: return(ret);
! 3353: }
! 3354:
! 3355: /**
! 3356: * xmlCatalogResolveURI:
! 3357: * @URI: the URI
! 3358: *
! 3359: * Do a complete resolution lookup of an URI
! 3360: *
! 3361: * Returns the URI of the resource or NULL if not found, it must be freed
! 3362: * by the caller.
! 3363: */
! 3364: xmlChar *
! 3365: xmlCatalogResolveURI(const xmlChar *URI) {
! 3366: xmlChar *ret;
! 3367:
! 3368: if (!xmlCatalogInitialized)
! 3369: xmlInitializeCatalog();
! 3370:
! 3371: ret = xmlACatalogResolveURI(xmlDefaultCatalog, URI);
! 3372: return(ret);
! 3373: }
! 3374:
! 3375: #ifdef LIBXML_OUTPUT_ENABLED
! 3376: /**
! 3377: * xmlCatalogDump:
! 3378: * @out: the file.
! 3379: *
! 3380: * Dump all the global catalog content to the given file.
! 3381: */
! 3382: void
! 3383: xmlCatalogDump(FILE *out) {
! 3384: if (out == NULL)
! 3385: return;
! 3386:
! 3387: if (!xmlCatalogInitialized)
! 3388: xmlInitializeCatalog();
! 3389:
! 3390: xmlACatalogDump(xmlDefaultCatalog, out);
! 3391: }
! 3392: #endif /* LIBXML_OUTPUT_ENABLED */
! 3393:
! 3394: /**
! 3395: * xmlCatalogAdd:
! 3396: * @type: the type of record to add to the catalog
! 3397: * @orig: the system, public or prefix to match
! 3398: * @replace: the replacement value for the match
! 3399: *
! 3400: * Add an entry in the catalog, it may overwrite existing but
! 3401: * different entries.
! 3402: * If called before any other catalog routine, allows to override the
! 3403: * default shared catalog put in place by xmlInitializeCatalog();
! 3404: *
! 3405: * Returns 0 if successful, -1 otherwise
! 3406: */
! 3407: int
! 3408: xmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace) {
! 3409: int res = -1;
! 3410:
! 3411: if (!xmlCatalogInitialized)
! 3412: xmlInitializeCatalogData();
! 3413:
! 3414: xmlRMutexLock(xmlCatalogMutex);
! 3415: /*
! 3416: * Specific case where one want to override the default catalog
! 3417: * put in place by xmlInitializeCatalog();
! 3418: */
! 3419: if ((xmlDefaultCatalog == NULL) &&
! 3420: (xmlStrEqual(type, BAD_CAST "catalog"))) {
! 3421: xmlDefaultCatalog = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
! 3422: xmlCatalogDefaultPrefer);
! 3423: xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
! 3424: orig, NULL, xmlCatalogDefaultPrefer, NULL);
! 3425:
! 3426: xmlRMutexUnlock(xmlCatalogMutex);
! 3427: return(0);
! 3428: }
! 3429:
! 3430: res = xmlACatalogAdd(xmlDefaultCatalog, type, orig, replace);
! 3431: xmlRMutexUnlock(xmlCatalogMutex);
! 3432: return(res);
! 3433: }
! 3434:
! 3435: /**
! 3436: * xmlCatalogRemove:
! 3437: * @value: the value to remove
! 3438: *
! 3439: * Remove an entry from the catalog
! 3440: *
! 3441: * Returns the number of entries removed if successful, -1 otherwise
! 3442: */
! 3443: int
! 3444: xmlCatalogRemove(const xmlChar *value) {
! 3445: int res;
! 3446:
! 3447: if (!xmlCatalogInitialized)
! 3448: xmlInitializeCatalog();
! 3449:
! 3450: xmlRMutexLock(xmlCatalogMutex);
! 3451: res = xmlACatalogRemove(xmlDefaultCatalog, value);
! 3452: xmlRMutexUnlock(xmlCatalogMutex);
! 3453: return(res);
! 3454: }
! 3455:
! 3456: /**
! 3457: * xmlCatalogConvert:
! 3458: *
! 3459: * Convert all the SGML catalog entries as XML ones
! 3460: *
! 3461: * Returns the number of entries converted if successful, -1 otherwise
! 3462: */
! 3463: int
! 3464: xmlCatalogConvert(void) {
! 3465: int res = -1;
! 3466:
! 3467: if (!xmlCatalogInitialized)
! 3468: xmlInitializeCatalog();
! 3469:
! 3470: xmlRMutexLock(xmlCatalogMutex);
! 3471: res = xmlConvertSGMLCatalog(xmlDefaultCatalog);
! 3472: xmlRMutexUnlock(xmlCatalogMutex);
! 3473: return(res);
! 3474: }
! 3475:
! 3476: /************************************************************************
! 3477: * *
! 3478: * Public interface manipulating the common preferences *
! 3479: * *
! 3480: ************************************************************************/
! 3481:
! 3482: /**
! 3483: * xmlCatalogGetDefaults:
! 3484: *
! 3485: * Used to get the user preference w.r.t. to what catalogs should
! 3486: * be accepted
! 3487: *
! 3488: * Returns the current xmlCatalogAllow value
! 3489: */
! 3490: xmlCatalogAllow
! 3491: xmlCatalogGetDefaults(void) {
! 3492: return(xmlCatalogDefaultAllow);
! 3493: }
! 3494:
! 3495: /**
! 3496: * xmlCatalogSetDefaults:
! 3497: * @allow: what catalogs should be accepted
! 3498: *
! 3499: * Used to set the user preference w.r.t. to what catalogs should
! 3500: * be accepted
! 3501: */
! 3502: void
! 3503: xmlCatalogSetDefaults(xmlCatalogAllow allow) {
! 3504: if (xmlDebugCatalogs) {
! 3505: switch (allow) {
! 3506: case XML_CATA_ALLOW_NONE:
! 3507: xmlGenericError(xmlGenericErrorContext,
! 3508: "Disabling catalog usage\n");
! 3509: break;
! 3510: case XML_CATA_ALLOW_GLOBAL:
! 3511: xmlGenericError(xmlGenericErrorContext,
! 3512: "Allowing only global catalogs\n");
! 3513: break;
! 3514: case XML_CATA_ALLOW_DOCUMENT:
! 3515: xmlGenericError(xmlGenericErrorContext,
! 3516: "Allowing only catalogs from the document\n");
! 3517: break;
! 3518: case XML_CATA_ALLOW_ALL:
! 3519: xmlGenericError(xmlGenericErrorContext,
! 3520: "Allowing all catalogs\n");
! 3521: break;
! 3522: }
! 3523: }
! 3524: xmlCatalogDefaultAllow = allow;
! 3525: }
! 3526:
! 3527: /**
! 3528: * xmlCatalogSetDefaultPrefer:
! 3529: * @prefer: the default preference for delegation
! 3530: *
! 3531: * Allows to set the preference between public and system for deletion
! 3532: * in XML Catalog resolution. C.f. section 4.1.1 of the spec
! 3533: * Values accepted are XML_CATA_PREFER_PUBLIC or XML_CATA_PREFER_SYSTEM
! 3534: *
! 3535: * Returns the previous value of the default preference for delegation
! 3536: */
! 3537: xmlCatalogPrefer
! 3538: xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer) {
! 3539: xmlCatalogPrefer ret = xmlCatalogDefaultPrefer;
! 3540:
! 3541: if (prefer == XML_CATA_PREFER_NONE)
! 3542: return(ret);
! 3543:
! 3544: if (xmlDebugCatalogs) {
! 3545: switch (prefer) {
! 3546: case XML_CATA_PREFER_PUBLIC:
! 3547: xmlGenericError(xmlGenericErrorContext,
! 3548: "Setting catalog preference to PUBLIC\n");
! 3549: break;
! 3550: case XML_CATA_PREFER_SYSTEM:
! 3551: xmlGenericError(xmlGenericErrorContext,
! 3552: "Setting catalog preference to SYSTEM\n");
! 3553: break;
! 3554: case XML_CATA_PREFER_NONE:
! 3555: break;
! 3556: }
! 3557: }
! 3558: xmlCatalogDefaultPrefer = prefer;
! 3559: return(ret);
! 3560: }
! 3561:
! 3562: /**
! 3563: * xmlCatalogSetDebug:
! 3564: * @level: the debug level of catalogs required
! 3565: *
! 3566: * Used to set the debug level for catalog operation, 0 disable
! 3567: * debugging, 1 enable it
! 3568: *
! 3569: * Returns the previous value of the catalog debugging level
! 3570: */
! 3571: int
! 3572: xmlCatalogSetDebug(int level) {
! 3573: int ret = xmlDebugCatalogs;
! 3574:
! 3575: if (level <= 0)
! 3576: xmlDebugCatalogs = 0;
! 3577: else
! 3578: xmlDebugCatalogs = level;
! 3579: return(ret);
! 3580: }
! 3581:
! 3582: /************************************************************************
! 3583: * *
! 3584: * Minimal interfaces used for per-document catalogs by the parser *
! 3585: * *
! 3586: ************************************************************************/
! 3587:
! 3588: /**
! 3589: * xmlCatalogFreeLocal:
! 3590: * @catalogs: a document's list of catalogs
! 3591: *
! 3592: * Free up the memory associated to the catalog list
! 3593: */
! 3594: void
! 3595: xmlCatalogFreeLocal(void *catalogs) {
! 3596: xmlCatalogEntryPtr catal;
! 3597:
! 3598: if (!xmlCatalogInitialized)
! 3599: xmlInitializeCatalog();
! 3600:
! 3601: catal = (xmlCatalogEntryPtr) catalogs;
! 3602: if (catal != NULL)
! 3603: xmlFreeCatalogEntryList(catal);
! 3604: }
! 3605:
! 3606:
! 3607: /**
! 3608: * xmlCatalogAddLocal:
! 3609: * @catalogs: a document's list of catalogs
! 3610: * @URL: the URL to a new local catalog
! 3611: *
! 3612: * Add the new entry to the catalog list
! 3613: *
! 3614: * Returns the updated list
! 3615: */
! 3616: void *
! 3617: xmlCatalogAddLocal(void *catalogs, const xmlChar *URL) {
! 3618: xmlCatalogEntryPtr catal, add;
! 3619:
! 3620: if (!xmlCatalogInitialized)
! 3621: xmlInitializeCatalog();
! 3622:
! 3623: if (URL == NULL)
! 3624: return(catalogs);
! 3625:
! 3626: if (xmlDebugCatalogs)
! 3627: xmlGenericError(xmlGenericErrorContext,
! 3628: "Adding document catalog %s\n", URL);
! 3629:
! 3630: add = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, URL, NULL,
! 3631: xmlCatalogDefaultPrefer, NULL);
! 3632: if (add == NULL)
! 3633: return(catalogs);
! 3634:
! 3635: catal = (xmlCatalogEntryPtr) catalogs;
! 3636: if (catal == NULL)
! 3637: return((void *) add);
! 3638:
! 3639: while (catal->next != NULL)
! 3640: catal = catal->next;
! 3641: catal->next = add;
! 3642: return(catalogs);
! 3643: }
! 3644:
! 3645: /**
! 3646: * xmlCatalogLocalResolve:
! 3647: * @catalogs: a document's list of catalogs
! 3648: * @pubID: the public ID string
! 3649: * @sysID: the system ID string
! 3650: *
! 3651: * Do a complete resolution lookup of an External Identifier using a
! 3652: * document's private catalog list
! 3653: *
! 3654: * Returns the URI of the resource or NULL if not found, it must be freed
! 3655: * by the caller.
! 3656: */
! 3657: xmlChar *
! 3658: xmlCatalogLocalResolve(void *catalogs, const xmlChar *pubID,
! 3659: const xmlChar *sysID) {
! 3660: xmlCatalogEntryPtr catal;
! 3661: xmlChar *ret;
! 3662:
! 3663: if (!xmlCatalogInitialized)
! 3664: xmlInitializeCatalog();
! 3665:
! 3666: if ((pubID == NULL) && (sysID == NULL))
! 3667: return(NULL);
! 3668:
! 3669: if (xmlDebugCatalogs) {
! 3670: if ((pubID != NULL) && (sysID != NULL)) {
! 3671: xmlGenericError(xmlGenericErrorContext,
! 3672: "Local Resolve: pubID %s sysID %s\n", pubID, sysID);
! 3673: } else if (pubID != NULL) {
! 3674: xmlGenericError(xmlGenericErrorContext,
! 3675: "Local Resolve: pubID %s\n", pubID);
! 3676: } else {
! 3677: xmlGenericError(xmlGenericErrorContext,
! 3678: "Local Resolve: sysID %s\n", sysID);
! 3679: }
! 3680: }
! 3681:
! 3682: catal = (xmlCatalogEntryPtr) catalogs;
! 3683: if (catal == NULL)
! 3684: return(NULL);
! 3685: ret = xmlCatalogListXMLResolve(catal, pubID, sysID);
! 3686: if ((ret != NULL) && (ret != XML_CATAL_BREAK))
! 3687: return(ret);
! 3688: return(NULL);
! 3689: }
! 3690:
! 3691: /**
! 3692: * xmlCatalogLocalResolveURI:
! 3693: * @catalogs: a document's list of catalogs
! 3694: * @URI: the URI
! 3695: *
! 3696: * Do a complete resolution lookup of an URI using a
! 3697: * document's private catalog list
! 3698: *
! 3699: * Returns the URI of the resource or NULL if not found, it must be freed
! 3700: * by the caller.
! 3701: */
! 3702: xmlChar *
! 3703: xmlCatalogLocalResolveURI(void *catalogs, const xmlChar *URI) {
! 3704: xmlCatalogEntryPtr catal;
! 3705: xmlChar *ret;
! 3706:
! 3707: if (!xmlCatalogInitialized)
! 3708: xmlInitializeCatalog();
! 3709:
! 3710: if (URI == NULL)
! 3711: return(NULL);
! 3712:
! 3713: if (xmlDebugCatalogs)
! 3714: xmlGenericError(xmlGenericErrorContext,
! 3715: "Resolve URI %s\n", URI);
! 3716:
! 3717: catal = (xmlCatalogEntryPtr) catalogs;
! 3718: if (catal == NULL)
! 3719: return(NULL);
! 3720: ret = xmlCatalogListXMLResolveURI(catal, URI);
! 3721: if ((ret != NULL) && (ret != XML_CATAL_BREAK))
! 3722: return(ret);
! 3723: return(NULL);
! 3724: }
! 3725:
! 3726: /************************************************************************
! 3727: * *
! 3728: * Deprecated interfaces *
! 3729: * *
! 3730: ************************************************************************/
! 3731: /**
! 3732: * xmlCatalogGetSystem:
! 3733: * @sysID: the system ID string
! 3734: *
! 3735: * Try to lookup the catalog reference associated to a system ID
! 3736: * DEPRECATED, use xmlCatalogResolveSystem()
! 3737: *
! 3738: * Returns the resource if found or NULL otherwise.
! 3739: */
! 3740: const xmlChar *
! 3741: xmlCatalogGetSystem(const xmlChar *sysID) {
! 3742: xmlChar *ret;
! 3743: static xmlChar result[1000];
! 3744: static int msg = 0;
! 3745:
! 3746: if (!xmlCatalogInitialized)
! 3747: xmlInitializeCatalog();
! 3748:
! 3749: if (msg == 0) {
! 3750: xmlGenericError(xmlGenericErrorContext,
! 3751: "Use of deprecated xmlCatalogGetSystem() call\n");
! 3752: msg++;
! 3753: }
! 3754:
! 3755: if (sysID == NULL)
! 3756: return(NULL);
! 3757:
! 3758: /*
! 3759: * Check first the XML catalogs
! 3760: */
! 3761: if (xmlDefaultCatalog != NULL) {
! 3762: ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, NULL, sysID);
! 3763: if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
! 3764: snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
! 3765: result[sizeof(result) - 1] = 0;
! 3766: return(result);
! 3767: }
! 3768: }
! 3769:
! 3770: if (xmlDefaultCatalog != NULL)
! 3771: return(xmlCatalogGetSGMLSystem(xmlDefaultCatalog->sgml, sysID));
! 3772: return(NULL);
! 3773: }
! 3774:
! 3775: /**
! 3776: * xmlCatalogGetPublic:
! 3777: * @pubID: the public ID string
! 3778: *
! 3779: * Try to lookup the catalog reference associated to a public ID
! 3780: * DEPRECATED, use xmlCatalogResolvePublic()
! 3781: *
! 3782: * Returns the resource if found or NULL otherwise.
! 3783: */
! 3784: const xmlChar *
! 3785: xmlCatalogGetPublic(const xmlChar *pubID) {
! 3786: xmlChar *ret;
! 3787: static xmlChar result[1000];
! 3788: static int msg = 0;
! 3789:
! 3790: if (!xmlCatalogInitialized)
! 3791: xmlInitializeCatalog();
! 3792:
! 3793: if (msg == 0) {
! 3794: xmlGenericError(xmlGenericErrorContext,
! 3795: "Use of deprecated xmlCatalogGetPublic() call\n");
! 3796: msg++;
! 3797: }
! 3798:
! 3799: if (pubID == NULL)
! 3800: return(NULL);
! 3801:
! 3802: /*
! 3803: * Check first the XML catalogs
! 3804: */
! 3805: if (xmlDefaultCatalog != NULL) {
! 3806: ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, pubID, NULL);
! 3807: if ((ret != NULL) && (ret != XML_CATAL_BREAK)) {
! 3808: snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret);
! 3809: result[sizeof(result) - 1] = 0;
! 3810: return(result);
! 3811: }
! 3812: }
! 3813:
! 3814: if (xmlDefaultCatalog != NULL)
! 3815: return(xmlCatalogGetSGMLPublic(xmlDefaultCatalog->sgml, pubID));
! 3816: return(NULL);
! 3817: }
! 3818:
! 3819: #define bottom_catalog
! 3820: #include "elfgcchack.h"
! 3821: #endif /* LIBXML_CATALOG_ENABLED */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>