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