Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencatalog.c
Go to the documentation of this file.
00001 00015 #define IN_LIBXML 00016 #include "libxml.h" 00017 00018 #ifdef LIBXML_CATALOG_ENABLED 00019 #ifdef HAVE_SYS_TYPES_H 00020 #include <sys/types.h> 00021 #endif 00022 #ifdef HAVE_SYS_STAT_H 00023 #include <sys/stat.h> 00024 #endif 00025 #ifdef HAVE_UNISTD_H 00026 #include <unistd.h> 00027 #endif 00028 #ifdef HAVE_FCNTL_H 00029 #include <fcntl.h> 00030 #endif 00031 #ifdef HAVE_STDLIB_H 00032 #include <stdlib.h> 00033 #endif 00034 #include <string.h> 00035 #include <libxml/xmlmemory.h> 00036 #include <libxml/hash.h> 00037 #include <libxml/uri.h> 00038 #include <libxml/parserInternals.h> 00039 #include <libxml/catalog.h> 00040 #include <libxml/xmlerror.h> 00041 #include <libxml/threads.h> 00042 #include <libxml/globals.h> 00043 00044 #define MAX_DELEGATE 50 00045 #define MAX_CATAL_DEPTH 50 00046 00047 #ifdef _WIN32 00048 # define PATH_SEAPARATOR ';' 00049 #else 00050 # define PATH_SEAPARATOR ':' 00051 #endif 00052 00063 #define TODO \ 00064 xmlGenericError(xmlGenericErrorContext, \ 00065 "Unimplemented block at %s:%d\n", \ 00066 __FILE__, __LINE__); 00067 00068 #define XML_URN_PUBID "urn:publicid:" 00069 #define XML_CATAL_BREAK ((xmlChar *) -1) 00070 #ifndef XML_XML_DEFAULT_CATALOG 00071 #define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog" 00072 #endif 00073 #ifndef XML_SGML_DEFAULT_CATALOG 00074 #define XML_SGML_DEFAULT_CATALOG "file:///etc/sgml/catalog" 00075 #endif 00076 00077 #if defined(_WIN32) && defined(_MSC_VER) 00078 #undef XML_XML_DEFAULT_CATALOG 00079 static char XML_XML_DEFAULT_CATALOG[256] = "file:///etc/xml/catalog"; 00080 #if defined(_WIN32_WCE) 00081 /* Windows CE don't have a A variant */ 00082 #define GetModuleHandleA GetModuleHandle 00083 #define GetModuleFileNameA GetModuleFileName 00084 #else 00085 void* __stdcall GetModuleHandleA(const char*); 00086 unsigned long __stdcall GetModuleFileNameA(void*, char*, unsigned long); 00087 #endif 00088 #endif 00089 00090 static xmlChar *xmlCatalogNormalizePublic(const xmlChar *pubID); 00091 static int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename); 00092 00093 /************************************************************************ 00094 * * 00095 * Types, all private * 00096 * * 00097 ************************************************************************/ 00098 00099 typedef enum { 00100 XML_CATA_REMOVED = -1, 00101 XML_CATA_NONE = 0, 00102 XML_CATA_CATALOG, 00103 XML_CATA_BROKEN_CATALOG, 00104 XML_CATA_NEXT_CATALOG, 00105 XML_CATA_GROUP, 00106 XML_CATA_PUBLIC, 00107 XML_CATA_SYSTEM, 00108 XML_CATA_REWRITE_SYSTEM, 00109 XML_CATA_DELEGATE_PUBLIC, 00110 XML_CATA_DELEGATE_SYSTEM, 00111 XML_CATA_URI, 00112 XML_CATA_REWRITE_URI, 00113 XML_CATA_DELEGATE_URI, 00114 SGML_CATA_SYSTEM, 00115 SGML_CATA_PUBLIC, 00116 SGML_CATA_ENTITY, 00117 SGML_CATA_PENTITY, 00118 SGML_CATA_DOCTYPE, 00119 SGML_CATA_LINKTYPE, 00120 SGML_CATA_NOTATION, 00121 SGML_CATA_DELEGATE, 00122 SGML_CATA_BASE, 00123 SGML_CATA_CATALOG, 00124 SGML_CATA_DOCUMENT, 00125 SGML_CATA_SGMLDECL 00126 } xmlCatalogEntryType; 00127 00128 typedef struct _xmlCatalogEntry xmlCatalogEntry; 00129 typedef xmlCatalogEntry *xmlCatalogEntryPtr; 00130 struct _xmlCatalogEntry { 00131 struct _xmlCatalogEntry *next; 00132 struct _xmlCatalogEntry *parent; 00133 struct _xmlCatalogEntry *children; 00134 xmlCatalogEntryType type; 00135 xmlChar *name; 00136 xmlChar *value; 00137 xmlChar *URL; /* The expanded URL using the base */ 00138 xmlCatalogPrefer prefer; 00139 int dealloc; 00140 int depth; 00141 struct _xmlCatalogEntry *group; 00142 }; 00143 00144 typedef enum { 00145 XML_XML_CATALOG_TYPE = 1, 00146 XML_SGML_CATALOG_TYPE 00147 } xmlCatalogType; 00148 00149 #define XML_MAX_SGML_CATA_DEPTH 10 00150 struct _xmlCatalog { 00151 xmlCatalogType type; /* either XML or SGML */ 00152 00153 /* 00154 * SGML Catalogs are stored as a simple hash table of catalog entries 00155 * Catalog stack to check against overflows when building the 00156 * SGML catalog 00157 */ 00158 char *catalTab[XML_MAX_SGML_CATA_DEPTH]; /* stack of catals */ 00159 int catalNr; /* Number of current catal streams */ 00160 int catalMax; /* Max number of catal streams */ 00161 xmlHashTablePtr sgml; 00162 00163 /* 00164 * XML Catalogs are stored as a tree of Catalog entries 00165 */ 00166 xmlCatalogPrefer prefer; 00167 xmlCatalogEntryPtr xml; 00168 }; 00169 00170 /************************************************************************ 00171 * * 00172 * Global variables * 00173 * * 00174 ************************************************************************/ 00175 00176 /* 00177 * Those are preferences 00178 */ 00179 static int xmlDebugCatalogs = 0; /* used for debugging */ 00180 static xmlCatalogAllow xmlCatalogDefaultAllow = XML_CATA_ALLOW_ALL; 00181 static xmlCatalogPrefer xmlCatalogDefaultPrefer = XML_CATA_PREFER_PUBLIC; 00182 00183 /* 00184 * Hash table containing all the trees of XML catalogs parsed by 00185 * the application. 00186 */ 00187 static xmlHashTablePtr xmlCatalogXMLFiles = NULL; 00188 00189 /* 00190 * The default catalog in use by the application 00191 */ 00192 static xmlCatalogPtr xmlDefaultCatalog = NULL; 00193 00194 /* 00195 * A mutex for modifying the shared global catalog(s) 00196 * xmlDefaultCatalog tree. 00197 * It also protects xmlCatalogXMLFiles 00198 * The core of this readers/writer scheme is in xmlFetchXMLCatalogFile() 00199 */ 00200 static xmlRMutexPtr xmlCatalogMutex = NULL; 00201 00202 /* 00203 * Whether the catalog support was initialized. 00204 */ 00205 static int xmlCatalogInitialized = 0; 00206 00207 /************************************************************************ 00208 * * 00209 * Catalog error handlers * 00210 * * 00211 ************************************************************************/ 00212 00219 static void 00220 xmlCatalogErrMemory(const char *extra) 00221 { 00222 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_CATALOG, 00223 XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, 00224 extra, NULL, NULL, 0, 0, 00225 "Memory allocation failed : %s\n", extra); 00226 } 00227 00237 static void 00238 xmlCatalogErr(xmlCatalogEntryPtr catal, xmlNodePtr node, int error, 00239 const char *msg, const xmlChar *str1, const xmlChar *str2, 00240 const xmlChar *str3) 00241 { 00242 __xmlRaiseError(NULL, NULL, NULL, catal, node, XML_FROM_CATALOG, 00243 error, XML_ERR_ERROR, NULL, 0, 00244 (const char *) str1, (const char *) str2, 00245 (const char *) str3, 0, 0, 00246 msg, str1, str2, str3); 00247 } 00248 00249 00250 /************************************************************************ 00251 * * 00252 * Allocation and Freeing * 00253 * * 00254 ************************************************************************/ 00255 00269 static xmlCatalogEntryPtr 00270 xmlNewCatalogEntry(xmlCatalogEntryType type, const xmlChar *name, 00271 const xmlChar *value, const xmlChar *URL, xmlCatalogPrefer prefer, 00272 xmlCatalogEntryPtr group) { 00273 xmlCatalogEntryPtr ret; 00274 xmlChar *normid = NULL; 00275 00276 ret = (xmlCatalogEntryPtr) xmlMalloc(sizeof(xmlCatalogEntry)); 00277 if (ret == NULL) { 00278 xmlCatalogErrMemory("allocating catalog entry"); 00279 return(NULL); 00280 } 00281 ret->next = NULL; 00282 ret->parent = NULL; 00283 ret->children = NULL; 00284 ret->type = type; 00285 if (type == XML_CATA_PUBLIC || type == XML_CATA_DELEGATE_PUBLIC) { 00286 normid = xmlCatalogNormalizePublic(name); 00287 if (normid != NULL) 00288 name = (*normid != 0 ? normid : NULL); 00289 } 00290 if (name != NULL) 00291 ret->name = xmlStrdup(name); 00292 else 00293 ret->name = NULL; 00294 if (normid != NULL) 00295 xmlFree(normid); 00296 if (value != NULL) 00297 ret->value = xmlStrdup(value); 00298 else 00299 ret->value = NULL; 00300 if (URL == NULL) 00301 URL = value; 00302 if (URL != NULL) 00303 ret->URL = xmlStrdup(URL); 00304 else 00305 ret->URL = NULL; 00306 ret->prefer = prefer; 00307 ret->dealloc = 0; 00308 ret->depth = 0; 00309 ret->group = group; 00310 return(ret); 00311 } 00312 00313 static void 00314 xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret); 00315 00322 static void 00323 xmlFreeCatalogEntry(xmlCatalogEntryPtr ret) { 00324 if (ret == NULL) 00325 return; 00326 /* 00327 * Entries stored in the file hash must be deallocated 00328 * only by the file hash cleaner ! 00329 */ 00330 if (ret->dealloc == 1) 00331 return; 00332 00333 if (xmlDebugCatalogs) { 00334 if (ret->name != NULL) 00335 xmlGenericError(xmlGenericErrorContext, 00336 "Free catalog entry %s\n", ret->name); 00337 else if (ret->value != NULL) 00338 xmlGenericError(xmlGenericErrorContext, 00339 "Free catalog entry %s\n", ret->value); 00340 else 00341 xmlGenericError(xmlGenericErrorContext, 00342 "Free catalog entry\n"); 00343 } 00344 00345 if (ret->name != NULL) 00346 xmlFree(ret->name); 00347 if (ret->value != NULL) 00348 xmlFree(ret->value); 00349 if (ret->URL != NULL) 00350 xmlFree(ret->URL); 00351 xmlFree(ret); 00352 } 00353 00360 static void 00361 xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret) { 00362 xmlCatalogEntryPtr next; 00363 00364 while (ret != NULL) { 00365 next = ret->next; 00366 xmlFreeCatalogEntry(ret); 00367 ret = next; 00368 } 00369 } 00370 00378 static void 00379 xmlFreeCatalogHashEntryList(xmlCatalogEntryPtr catal) { 00380 xmlCatalogEntryPtr children, next; 00381 00382 if (catal == NULL) 00383 return; 00384 00385 children = catal->children; 00386 while (children != NULL) { 00387 next = children->next; 00388 children->dealloc = 0; 00389 children->children = NULL; 00390 xmlFreeCatalogEntry(children); 00391 children = next; 00392 } 00393 catal->dealloc = 0; 00394 xmlFreeCatalogEntry(catal); 00395 } 00396 00407 static xmlCatalogPtr 00408 xmlCreateNewCatalog(xmlCatalogType type, xmlCatalogPrefer prefer) { 00409 xmlCatalogPtr ret; 00410 00411 ret = (xmlCatalogPtr) xmlMalloc(sizeof(xmlCatalog)); 00412 if (ret == NULL) { 00413 xmlCatalogErrMemory("allocating catalog"); 00414 return(NULL); 00415 } 00416 memset(ret, 0, sizeof(xmlCatalog)); 00417 ret->type = type; 00418 ret->catalNr = 0; 00419 ret->catalMax = XML_MAX_SGML_CATA_DEPTH; 00420 ret->prefer = prefer; 00421 if (ret->type == XML_SGML_CATALOG_TYPE) 00422 ret->sgml = xmlHashCreate(10); 00423 return(ret); 00424 } 00425 00432 void 00433 xmlFreeCatalog(xmlCatalogPtr catal) { 00434 if (catal == NULL) 00435 return; 00436 if (catal->xml != NULL) 00437 xmlFreeCatalogEntryList(catal->xml); 00438 if (catal->sgml != NULL) 00439 xmlHashFree(catal->sgml, 00440 (xmlHashDeallocator) xmlFreeCatalogEntry); 00441 xmlFree(catal); 00442 } 00443 00444 /************************************************************************ 00445 * * 00446 * Serializing Catalogs * 00447 * * 00448 ************************************************************************/ 00449 00450 #ifdef LIBXML_OUTPUT_ENABLED 00451 00458 static void 00459 xmlCatalogDumpEntry(xmlCatalogEntryPtr entry, FILE *out) { 00460 if ((entry == NULL) || (out == NULL)) 00461 return; 00462 switch (entry->type) { 00463 case SGML_CATA_ENTITY: 00464 fprintf(out, "ENTITY "); break; 00465 case SGML_CATA_PENTITY: 00466 fprintf(out, "ENTITY %%"); break; 00467 case SGML_CATA_DOCTYPE: 00468 fprintf(out, "DOCTYPE "); break; 00469 case SGML_CATA_LINKTYPE: 00470 fprintf(out, "LINKTYPE "); break; 00471 case SGML_CATA_NOTATION: 00472 fprintf(out, "NOTATION "); break; 00473 case SGML_CATA_PUBLIC: 00474 fprintf(out, "PUBLIC "); break; 00475 case SGML_CATA_SYSTEM: 00476 fprintf(out, "SYSTEM "); break; 00477 case SGML_CATA_DELEGATE: 00478 fprintf(out, "DELEGATE "); break; 00479 case SGML_CATA_BASE: 00480 fprintf(out, "BASE "); break; 00481 case SGML_CATA_CATALOG: 00482 fprintf(out, "CATALOG "); break; 00483 case SGML_CATA_DOCUMENT: 00484 fprintf(out, "DOCUMENT "); break; 00485 case SGML_CATA_SGMLDECL: 00486 fprintf(out, "SGMLDECL "); break; 00487 default: 00488 return; 00489 } 00490 switch (entry->type) { 00491 case SGML_CATA_ENTITY: 00492 case SGML_CATA_PENTITY: 00493 case SGML_CATA_DOCTYPE: 00494 case SGML_CATA_LINKTYPE: 00495 case SGML_CATA_NOTATION: 00496 fprintf(out, "%s", (const char *) entry->name); break; 00497 case SGML_CATA_PUBLIC: 00498 case SGML_CATA_SYSTEM: 00499 case SGML_CATA_SGMLDECL: 00500 case SGML_CATA_DOCUMENT: 00501 case SGML_CATA_CATALOG: 00502 case SGML_CATA_BASE: 00503 case SGML_CATA_DELEGATE: 00504 fprintf(out, "\"%s\"", entry->name); break; 00505 default: 00506 break; 00507 } 00508 switch (entry->type) { 00509 case SGML_CATA_ENTITY: 00510 case SGML_CATA_PENTITY: 00511 case SGML_CATA_DOCTYPE: 00512 case SGML_CATA_LINKTYPE: 00513 case SGML_CATA_NOTATION: 00514 case SGML_CATA_PUBLIC: 00515 case SGML_CATA_SYSTEM: 00516 case SGML_CATA_DELEGATE: 00517 fprintf(out, " \"%s\"", entry->value); break; 00518 default: 00519 break; 00520 } 00521 fprintf(out, "\n"); 00522 } 00523 00535 static void xmlDumpXMLCatalogNode(xmlCatalogEntryPtr catal, xmlNodePtr catalog, 00536 xmlDocPtr doc, xmlNsPtr ns, xmlCatalogEntryPtr cgroup) { 00537 xmlNodePtr node; 00538 xmlCatalogEntryPtr cur; 00539 /* 00540 * add all the catalog entries 00541 */ 00542 cur = catal; 00543 while (cur != NULL) { 00544 if (cur->group == cgroup) { 00545 switch (cur->type) { 00546 case XML_CATA_REMOVED: 00547 break; 00548 case XML_CATA_BROKEN_CATALOG: 00549 case XML_CATA_CATALOG: 00550 if (cur == catal) { 00551 cur = cur->children; 00552 continue; 00553 } 00554 break; 00555 case XML_CATA_NEXT_CATALOG: 00556 node = xmlNewDocNode(doc, ns, BAD_CAST "nextCatalog", NULL); 00557 xmlSetProp(node, BAD_CAST "catalog", cur->value); 00558 xmlAddChild(catalog, node); 00559 break; 00560 case XML_CATA_NONE: 00561 break; 00562 case XML_CATA_GROUP: 00563 node = xmlNewDocNode(doc, ns, BAD_CAST "group", NULL); 00564 xmlSetProp(node, BAD_CAST "id", cur->name); 00565 if (cur->value != NULL) { 00566 xmlNsPtr xns; 00567 xns = xmlSearchNsByHref(doc, node, XML_XML_NAMESPACE); 00568 if (xns != NULL) 00569 xmlSetNsProp(node, xns, BAD_CAST "base", 00570 cur->value); 00571 } 00572 switch (cur->prefer) { 00573 case XML_CATA_PREFER_NONE: 00574 break; 00575 case XML_CATA_PREFER_PUBLIC: 00576 xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "public"); 00577 break; 00578 case XML_CATA_PREFER_SYSTEM: 00579 xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "system"); 00580 break; 00581 } 00582 xmlDumpXMLCatalogNode(cur->next, node, doc, ns, cur); 00583 xmlAddChild(catalog, node); 00584 break; 00585 case XML_CATA_PUBLIC: 00586 node = xmlNewDocNode(doc, ns, BAD_CAST "public", NULL); 00587 xmlSetProp(node, BAD_CAST "publicId", cur->name); 00588 xmlSetProp(node, BAD_CAST "uri", cur->value); 00589 xmlAddChild(catalog, node); 00590 break; 00591 case XML_CATA_SYSTEM: 00592 node = xmlNewDocNode(doc, ns, BAD_CAST "system", NULL); 00593 xmlSetProp(node, BAD_CAST "systemId", cur->name); 00594 xmlSetProp(node, BAD_CAST "uri", cur->value); 00595 xmlAddChild(catalog, node); 00596 break; 00597 case XML_CATA_REWRITE_SYSTEM: 00598 node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteSystem", NULL); 00599 xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name); 00600 xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value); 00601 xmlAddChild(catalog, node); 00602 break; 00603 case XML_CATA_DELEGATE_PUBLIC: 00604 node = xmlNewDocNode(doc, ns, BAD_CAST "delegatePublic", NULL); 00605 xmlSetProp(node, BAD_CAST "publicIdStartString", cur->name); 00606 xmlSetProp(node, BAD_CAST "catalog", cur->value); 00607 xmlAddChild(catalog, node); 00608 break; 00609 case XML_CATA_DELEGATE_SYSTEM: 00610 node = xmlNewDocNode(doc, ns, BAD_CAST "delegateSystem", NULL); 00611 xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name); 00612 xmlSetProp(node, BAD_CAST "catalog", cur->value); 00613 xmlAddChild(catalog, node); 00614 break; 00615 case XML_CATA_URI: 00616 node = xmlNewDocNode(doc, ns, BAD_CAST "uri", NULL); 00617 xmlSetProp(node, BAD_CAST "name", cur->name); 00618 xmlSetProp(node, BAD_CAST "uri", cur->value); 00619 xmlAddChild(catalog, node); 00620 break; 00621 case XML_CATA_REWRITE_URI: 00622 node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteURI", NULL); 00623 xmlSetProp(node, BAD_CAST "uriStartString", cur->name); 00624 xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value); 00625 xmlAddChild(catalog, node); 00626 break; 00627 case XML_CATA_DELEGATE_URI: 00628 node = xmlNewDocNode(doc, ns, BAD_CAST "delegateURI", NULL); 00629 xmlSetProp(node, BAD_CAST "uriStartString", cur->name); 00630 xmlSetProp(node, BAD_CAST "catalog", cur->value); 00631 xmlAddChild(catalog, node); 00632 break; 00633 case SGML_CATA_SYSTEM: 00634 case SGML_CATA_PUBLIC: 00635 case SGML_CATA_ENTITY: 00636 case SGML_CATA_PENTITY: 00637 case SGML_CATA_DOCTYPE: 00638 case SGML_CATA_LINKTYPE: 00639 case SGML_CATA_NOTATION: 00640 case SGML_CATA_DELEGATE: 00641 case SGML_CATA_BASE: 00642 case SGML_CATA_CATALOG: 00643 case SGML_CATA_DOCUMENT: 00644 case SGML_CATA_SGMLDECL: 00645 break; 00646 } 00647 } 00648 cur = cur->next; 00649 } 00650 } 00651 00652 static int 00653 xmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) { 00654 int ret; 00655 xmlDocPtr doc; 00656 xmlNsPtr ns; 00657 xmlDtdPtr dtd; 00658 xmlNodePtr catalog; 00659 xmlOutputBufferPtr buf; 00660 00661 /* 00662 * Rebuild a catalog 00663 */ 00664 doc = xmlNewDoc(NULL); 00665 if (doc == NULL) 00666 return(-1); 00667 dtd = xmlNewDtd(doc, BAD_CAST "catalog", 00668 BAD_CAST "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN", 00669 BAD_CAST "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd"); 00670 00671 xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd); 00672 00673 ns = xmlNewNs(NULL, XML_CATALOGS_NAMESPACE, NULL); 00674 if (ns == NULL) { 00675 xmlFreeDoc(doc); 00676 return(-1); 00677 } 00678 catalog = xmlNewDocNode(doc, ns, BAD_CAST "catalog", NULL); 00679 if (catalog == NULL) { 00680 xmlFreeNs(ns); 00681 xmlFreeDoc(doc); 00682 return(-1); 00683 } 00684 catalog->nsDef = ns; 00685 xmlAddChild((xmlNodePtr) doc, catalog); 00686 00687 xmlDumpXMLCatalogNode(catal, catalog, doc, ns, NULL); 00688 00689 /* 00690 * reserialize it 00691 */ 00692 buf = xmlOutputBufferCreateFile(out, NULL); 00693 if (buf == NULL) { 00694 xmlFreeDoc(doc); 00695 return(-1); 00696 } 00697 ret = xmlSaveFormatFileTo(buf, doc, NULL, 1); 00698 00699 /* 00700 * Free it 00701 */ 00702 xmlFreeDoc(doc); 00703 00704 return(ret); 00705 } 00706 #endif /* LIBXML_OUTPUT_ENABLED */ 00707 00708 /************************************************************************ 00709 * * 00710 * Converting SGML Catalogs to XML * 00711 * * 00712 ************************************************************************/ 00713 00721 static void 00722 xmlCatalogConvertEntry(xmlCatalogEntryPtr entry, xmlCatalogPtr catal) { 00723 if ((entry == NULL) || (catal == NULL) || (catal->sgml == NULL) || 00724 (catal->xml == NULL)) 00725 return; 00726 switch (entry->type) { 00727 case SGML_CATA_ENTITY: 00728 entry->type = XML_CATA_PUBLIC; 00729 break; 00730 case SGML_CATA_PENTITY: 00731 entry->type = XML_CATA_PUBLIC; 00732 break; 00733 case SGML_CATA_DOCTYPE: 00734 entry->type = XML_CATA_PUBLIC; 00735 break; 00736 case SGML_CATA_LINKTYPE: 00737 entry->type = XML_CATA_PUBLIC; 00738 break; 00739 case SGML_CATA_NOTATION: 00740 entry->type = XML_CATA_PUBLIC; 00741 break; 00742 case SGML_CATA_PUBLIC: 00743 entry->type = XML_CATA_PUBLIC; 00744 break; 00745 case SGML_CATA_SYSTEM: 00746 entry->type = XML_CATA_SYSTEM; 00747 break; 00748 case SGML_CATA_DELEGATE: 00749 entry->type = XML_CATA_DELEGATE_PUBLIC; 00750 break; 00751 case SGML_CATA_CATALOG: 00752 entry->type = XML_CATA_CATALOG; 00753 break; 00754 default: 00755 xmlHashRemoveEntry(catal->sgml, entry->name, 00756 (xmlHashDeallocator) xmlFreeCatalogEntry); 00757 return; 00758 } 00759 /* 00760 * Conversion successful, remove from the SGML catalog 00761 * and add it to the default XML one 00762 */ 00763 xmlHashRemoveEntry(catal->sgml, entry->name, NULL); 00764 entry->parent = catal->xml; 00765 entry->next = NULL; 00766 if (catal->xml->children == NULL) 00767 catal->xml->children = entry; 00768 else { 00769 xmlCatalogEntryPtr prev; 00770 00771 prev = catal->xml->children; 00772 while (prev->next != NULL) 00773 prev = prev->next; 00774 prev->next = entry; 00775 } 00776 } 00777 00786 int 00787 xmlConvertSGMLCatalog(xmlCatalogPtr catal) { 00788 00789 if ((catal == NULL) || (catal->type != XML_SGML_CATALOG_TYPE)) 00790 return(-1); 00791 00792 if (xmlDebugCatalogs) { 00793 xmlGenericError(xmlGenericErrorContext, 00794 "Converting SGML catalog to XML\n"); 00795 } 00796 xmlHashScan(catal->sgml, 00797 (xmlHashScanner) xmlCatalogConvertEntry, 00798 &catal); 00799 return(0); 00800 } 00801 00802 /************************************************************************ 00803 * * 00804 * Helper function * 00805 * * 00806 ************************************************************************/ 00807 00817 static xmlChar * 00818 xmlCatalogUnWrapURN(const xmlChar *urn) { 00819 xmlChar result[2000]; 00820 unsigned int i = 0; 00821 00822 if (xmlStrncmp(urn, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) 00823 return(NULL); 00824 urn += sizeof(XML_URN_PUBID) - 1; 00825 00826 while (*urn != 0) { 00827 if (i > sizeof(result) - 4) 00828 break; 00829 if (*urn == '+') { 00830 result[i++] = ' '; 00831 urn++; 00832 } else if (*urn == ':') { 00833 result[i++] = '/'; 00834 result[i++] = '/'; 00835 urn++; 00836 } else if (*urn == ';') { 00837 result[i++] = ':'; 00838 result[i++] = ':'; 00839 urn++; 00840 } else if (*urn == '%') { 00841 if ((urn[1] == '2') && (urn[2] == 'B')) 00842 result[i++] = '+'; 00843 else if ((urn[1] == '3') && (urn[2] == 'A')) 00844 result[i++] = ':'; 00845 else if ((urn[1] == '2') && (urn[2] == 'F')) 00846 result[i++] = '/'; 00847 else if ((urn[1] == '3') && (urn[2] == 'B')) 00848 result[i++] = ';'; 00849 else if ((urn[1] == '2') && (urn[2] == '7')) 00850 result[i++] = '\''; 00851 else if ((urn[1] == '3') && (urn[2] == 'F')) 00852 result[i++] = '?'; 00853 else if ((urn[1] == '2') && (urn[2] == '3')) 00854 result[i++] = '#'; 00855 else if ((urn[1] == '2') && (urn[2] == '5')) 00856 result[i++] = '%'; 00857 else { 00858 result[i++] = *urn; 00859 urn++; 00860 continue; 00861 } 00862 urn += 3; 00863 } else { 00864 result[i++] = *urn; 00865 urn++; 00866 } 00867 } 00868 result[i] = 0; 00869 00870 return(xmlStrdup(result)); 00871 } 00872 00883 xmlDocPtr 00884 xmlParseCatalogFile(const char *filename) { 00885 xmlDocPtr ret; 00886 xmlParserCtxtPtr ctxt; 00887 char *directory = NULL; 00888 xmlParserInputPtr inputStream; 00889 xmlParserInputBufferPtr buf; 00890 00891 ctxt = xmlNewParserCtxt(); 00892 if (ctxt == NULL) { 00893 #ifdef LIBXML_SAX1_ENABLED 00894 if (xmlDefaultSAXHandler.error != NULL) { 00895 xmlDefaultSAXHandler.error(NULL, "out of memory\n"); 00896 } 00897 #endif 00898 return(NULL); 00899 } 00900 00901 buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE); 00902 if (buf == NULL) { 00903 xmlFreeParserCtxt(ctxt); 00904 return(NULL); 00905 } 00906 00907 inputStream = xmlNewInputStream(ctxt); 00908 if (inputStream == NULL) { 00909 xmlFreeParserCtxt(ctxt); 00910 return(NULL); 00911 } 00912 00913 inputStream->filename = (char *) xmlCanonicPath((const xmlChar *)filename); 00914 inputStream->buf = buf; 00915 inputStream->base = inputStream->buf->buffer->content; 00916 inputStream->cur = inputStream->buf->buffer->content; 00917 inputStream->end = 00918 &inputStream->buf->buffer->content[inputStream->buf->buffer->use]; 00919 00920 inputPush(ctxt, inputStream); 00921 if ((ctxt->directory == NULL) && (directory == NULL)) 00922 directory = xmlParserGetDirectory(filename); 00923 if ((ctxt->directory == NULL) && (directory != NULL)) 00924 ctxt->directory = directory; 00925 ctxt->valid = 0; 00926 ctxt->validate = 0; 00927 ctxt->loadsubset = 0; 00928 ctxt->pedantic = 0; 00929 ctxt->dictNames = 1; 00930 00931 xmlParseDocument(ctxt); 00932 00933 if (ctxt->wellFormed) 00934 ret = ctxt->myDoc; 00935 else { 00936 ret = NULL; 00937 xmlFreeDoc(ctxt->myDoc); 00938 ctxt->myDoc = NULL; 00939 } 00940 xmlFreeParserCtxt(ctxt); 00941 00942 return(ret); 00943 } 00944 00953 static xmlChar * 00954 xmlLoadFileContent(const char *filename) 00955 { 00956 #ifdef HAVE_STAT 00957 int fd; 00958 #else 00959 FILE *fd; 00960 #endif 00961 int len; 00962 long size; 00963 00964 #ifdef HAVE_STAT 00965 struct stat info; 00966 #endif 00967 xmlChar *content; 00968 00969 if (filename == NULL) 00970 return (NULL); 00971 00972 #ifdef HAVE_STAT 00973 if (stat(filename, &info) < 0) 00974 return (NULL); 00975 #endif 00976 00977 #ifdef HAVE_STAT 00978 if ((fd = open(filename, O_RDONLY)) < 0) 00979 #else 00980 if ((fd = fopen(filename, "rb")) == NULL) 00981 #endif 00982 { 00983 return (NULL); 00984 } 00985 #ifdef HAVE_STAT 00986 size = info.st_size; 00987 #else 00988 if (fseek(fd, 0, SEEK_END) || (size = ftell(fd)) == EOF || fseek(fd, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */ 00989 fclose(fd); 00990 return (NULL); 00991 } 00992 #endif 00993 content = xmlMallocAtomic(size + 10); 00994 if (content == NULL) { 00995 xmlCatalogErrMemory("allocating catalog data"); 00996 return (NULL); 00997 } 00998 #ifdef HAVE_STAT 00999 len = read(fd, content, size); 01000 close(fd); 01001 #else 01002 len = fread(content, 1, size, fd); 01003 fclose(fd); 01004 #endif 01005 if (len < 0) { 01006 xmlFree(content); 01007 return (NULL); 01008 } 01009 content[len] = 0; 01010 01011 return(content); 01012 } 01013 01026 static xmlChar * 01027 xmlCatalogNormalizePublic(const xmlChar *pubID) 01028 { 01029 int ok = 1; 01030 int white; 01031 const xmlChar *p; 01032 xmlChar *ret; 01033 xmlChar *q; 01034 01035 if (pubID == NULL) 01036 return(NULL); 01037 01038 white = 1; 01039 for (p = pubID;*p != 0 && ok;p++) { 01040 if (!xmlIsBlank_ch(*p)) 01041 white = 0; 01042 else if (*p == 0x20 && !white) 01043 white = 1; 01044 else 01045 ok = 0; 01046 } 01047 if (ok && !white) /* is normalized */ 01048 return(NULL); 01049 01050 ret = xmlStrdup(pubID); 01051 q = ret; 01052 white = 0; 01053 for (p = pubID;*p != 0;p++) { 01054 if (xmlIsBlank_ch(*p)) { 01055 if (q != ret) 01056 white = 1; 01057 } else { 01058 if (white) { 01059 *(q++) = 0x20; 01060 white = 0; 01061 } 01062 *(q++) = *p; 01063 } 01064 } 01065 *q = 0; 01066 return(ret); 01067 } 01068 01069 /************************************************************************ 01070 * * 01071 * The XML Catalog parser * 01072 * * 01073 ************************************************************************/ 01074 01075 static xmlCatalogEntryPtr 01076 xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename); 01077 static void 01078 xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer, 01079 xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup); 01080 static xmlChar * 01081 xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, 01082 const xmlChar *sysID); 01083 static xmlChar * 01084 xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI); 01085 01086 01095 static xmlCatalogEntryType 01096 xmlGetXMLCatalogEntryType(const xmlChar *name) { 01097 xmlCatalogEntryType type = XML_CATA_NONE; 01098 if (xmlStrEqual(name, (const xmlChar *) "system")) 01099 type = XML_CATA_SYSTEM; 01100 else if (xmlStrEqual(name, (const xmlChar *) "public")) 01101 type = XML_CATA_PUBLIC; 01102 else if (xmlStrEqual(name, (const xmlChar *) "rewriteSystem")) 01103 type = XML_CATA_REWRITE_SYSTEM; 01104 else if (xmlStrEqual(name, (const xmlChar *) "delegatePublic")) 01105 type = XML_CATA_DELEGATE_PUBLIC; 01106 else if (xmlStrEqual(name, (const xmlChar *) "delegateSystem")) 01107 type = XML_CATA_DELEGATE_SYSTEM; 01108 else if (xmlStrEqual(name, (const xmlChar *) "uri")) 01109 type = XML_CATA_URI; 01110 else if (xmlStrEqual(name, (const xmlChar *) "rewriteURI")) 01111 type = XML_CATA_REWRITE_URI; 01112 else if (xmlStrEqual(name, (const xmlChar *) "delegateURI")) 01113 type = XML_CATA_DELEGATE_URI; 01114 else if (xmlStrEqual(name, (const xmlChar *) "nextCatalog")) 01115 type = XML_CATA_NEXT_CATALOG; 01116 else if (xmlStrEqual(name, (const xmlChar *) "catalog")) 01117 type = XML_CATA_CATALOG; 01118 return(type); 01119 } 01120 01136 static xmlCatalogEntryPtr 01137 xmlParseXMLCatalogOneNode(xmlNodePtr cur, xmlCatalogEntryType type, 01138 const xmlChar *name, const xmlChar *attrName, 01139 const xmlChar *uriAttrName, xmlCatalogPrefer prefer, 01140 xmlCatalogEntryPtr cgroup) { 01141 int ok = 1; 01142 xmlChar *uriValue; 01143 xmlChar *nameValue = NULL; 01144 xmlChar *base = NULL; 01145 xmlChar *URL = NULL; 01146 xmlCatalogEntryPtr ret = NULL; 01147 01148 if (attrName != NULL) { 01149 nameValue = xmlGetProp(cur, attrName); 01150 if (nameValue == NULL) { 01151 xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR, 01152 "%s entry lacks '%s'\n", name, attrName, NULL); 01153 ok = 0; 01154 } 01155 } 01156 uriValue = xmlGetProp(cur, uriAttrName); 01157 if (uriValue == NULL) { 01158 xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR, 01159 "%s entry lacks '%s'\n", name, uriAttrName, NULL); 01160 ok = 0; 01161 } 01162 if (!ok) { 01163 if (nameValue != NULL) 01164 xmlFree(nameValue); 01165 if (uriValue != NULL) 01166 xmlFree(uriValue); 01167 return(NULL); 01168 } 01169 01170 base = xmlNodeGetBase(cur->doc, cur); 01171 URL = xmlBuildURI(uriValue, base); 01172 if (URL != NULL) { 01173 if (xmlDebugCatalogs > 1) { 01174 if (nameValue != NULL) 01175 xmlGenericError(xmlGenericErrorContext, 01176 "Found %s: '%s' '%s'\n", name, nameValue, URL); 01177 else 01178 xmlGenericError(xmlGenericErrorContext, 01179 "Found %s: '%s'\n", name, URL); 01180 } 01181 ret = xmlNewCatalogEntry(type, nameValue, uriValue, URL, prefer, cgroup); 01182 } else { 01183 xmlCatalogErr(ret, cur, XML_CATALOG_ENTRY_BROKEN, 01184 "%s entry '%s' broken ?: %s\n", name, uriAttrName, uriValue); 01185 } 01186 if (nameValue != NULL) 01187 xmlFree(nameValue); 01188 if (uriValue != NULL) 01189 xmlFree(uriValue); 01190 if (base != NULL) 01191 xmlFree(base); 01192 if (URL != NULL) 01193 xmlFree(URL); 01194 return(ret); 01195 } 01196 01208 static void 01209 xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer, 01210 xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup) 01211 { 01212 xmlChar *base = NULL; 01213 xmlCatalogEntryPtr entry = NULL; 01214 01215 if (cur == NULL) 01216 return; 01217 if (xmlStrEqual(cur->name, BAD_CAST "group")) { 01218 xmlChar *prop; 01219 xmlCatalogPrefer pref = XML_CATA_PREFER_NONE; 01220 01221 prop = xmlGetProp(cur, BAD_CAST "prefer"); 01222 if (prop != NULL) { 01223 if (xmlStrEqual(prop, BAD_CAST "system")) { 01224 prefer = XML_CATA_PREFER_SYSTEM; 01225 } else if (xmlStrEqual(prop, BAD_CAST "public")) { 01226 prefer = XML_CATA_PREFER_PUBLIC; 01227 } else { 01228 xmlCatalogErr(parent, cur, XML_CATALOG_PREFER_VALUE, 01229 "Invalid value for prefer: '%s'\n", 01230 prop, NULL, NULL); 01231 } 01232 xmlFree(prop); 01233 pref = prefer; 01234 } 01235 prop = xmlGetProp(cur, BAD_CAST "id"); 01236 base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE); 01237 entry = xmlNewCatalogEntry(XML_CATA_GROUP, prop, base, NULL, pref, cgroup); 01238 xmlFree(prop); 01239 } else if (xmlStrEqual(cur->name, BAD_CAST "public")) { 01240 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_PUBLIC, 01241 BAD_CAST "public", BAD_CAST "publicId", BAD_CAST "uri", prefer, cgroup); 01242 } else if (xmlStrEqual(cur->name, BAD_CAST "system")) { 01243 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_SYSTEM, 01244 BAD_CAST "system", BAD_CAST "systemId", BAD_CAST "uri", prefer, cgroup); 01245 } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteSystem")) { 01246 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_SYSTEM, 01247 BAD_CAST "rewriteSystem", BAD_CAST "systemIdStartString", 01248 BAD_CAST "rewritePrefix", prefer, cgroup); 01249 } else if (xmlStrEqual(cur->name, BAD_CAST "delegatePublic")) { 01250 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_PUBLIC, 01251 BAD_CAST "delegatePublic", BAD_CAST "publicIdStartString", 01252 BAD_CAST "catalog", prefer, cgroup); 01253 } else if (xmlStrEqual(cur->name, BAD_CAST "delegateSystem")) { 01254 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_SYSTEM, 01255 BAD_CAST "delegateSystem", BAD_CAST "systemIdStartString", 01256 BAD_CAST "catalog", prefer, cgroup); 01257 } else if (xmlStrEqual(cur->name, BAD_CAST "uri")) { 01258 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_URI, 01259 BAD_CAST "uri", BAD_CAST "name", 01260 BAD_CAST "uri", prefer, cgroup); 01261 } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteURI")) { 01262 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_URI, 01263 BAD_CAST "rewriteURI", BAD_CAST "uriStartString", 01264 BAD_CAST "rewritePrefix", prefer, cgroup); 01265 } else if (xmlStrEqual(cur->name, BAD_CAST "delegateURI")) { 01266 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_URI, 01267 BAD_CAST "delegateURI", BAD_CAST "uriStartString", 01268 BAD_CAST "catalog", prefer, cgroup); 01269 } else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) { 01270 entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG, 01271 BAD_CAST "nextCatalog", NULL, 01272 BAD_CAST "catalog", prefer, cgroup); 01273 } 01274 if (entry != NULL) { 01275 if (parent != NULL) { 01276 entry->parent = parent; 01277 if (parent->children == NULL) 01278 parent->children = entry; 01279 else { 01280 xmlCatalogEntryPtr prev; 01281 01282 prev = parent->children; 01283 while (prev->next != NULL) 01284 prev = prev->next; 01285 prev->next = entry; 01286 } 01287 } 01288 if (entry->type == XML_CATA_GROUP) { 01289 /* 01290 * Recurse to propagate prefer to the subtree 01291 * (xml:base handling is automated) 01292 */ 01293 xmlParseXMLCatalogNodeList(cur->children, prefer, parent, entry); 01294 } 01295 } 01296 if (base != NULL) 01297 xmlFree(base); 01298 } 01299 01311 static void 01312 xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer, 01313 xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup) { 01314 while (cur != NULL) { 01315 if ((cur->ns != NULL) && (cur->ns->href != NULL) && 01316 (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) { 01317 xmlParseXMLCatalogNode(cur, prefer, parent, cgroup); 01318 } 01319 cur = cur->next; 01320 } 01321 /* TODO: sort the list according to REWRITE lengths and prefer value */ 01322 } 01323 01334 static xmlCatalogEntryPtr 01335 xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename) { 01336 xmlDocPtr doc; 01337 xmlNodePtr cur; 01338 xmlChar *prop; 01339 xmlCatalogEntryPtr parent = NULL; 01340 01341 if (filename == NULL) 01342 return(NULL); 01343 01344 doc = xmlParseCatalogFile((const char *) filename); 01345 if (doc == NULL) { 01346 if (xmlDebugCatalogs) 01347 xmlGenericError(xmlGenericErrorContext, 01348 "Failed to parse catalog %s\n", filename); 01349 return(NULL); 01350 } 01351 01352 if (xmlDebugCatalogs) 01353 xmlGenericError(xmlGenericErrorContext, 01354 "%d Parsing catalog %s\n", xmlGetThreadId(), filename); 01355 01356 cur = xmlDocGetRootElement(doc); 01357 if ((cur != NULL) && (xmlStrEqual(cur->name, BAD_CAST "catalog")) && 01358 (cur->ns != NULL) && (cur->ns->href != NULL) && 01359 (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) { 01360 01361 parent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, 01362 (const xmlChar *)filename, NULL, prefer, NULL); 01363 if (parent == NULL) { 01364 xmlFreeDoc(doc); 01365 return(NULL); 01366 } 01367 01368 prop = xmlGetProp(cur, BAD_CAST "prefer"); 01369 if (prop != NULL) { 01370 if (xmlStrEqual(prop, BAD_CAST "system")) { 01371 prefer = XML_CATA_PREFER_SYSTEM; 01372 } else if (xmlStrEqual(prop, BAD_CAST "public")) { 01373 prefer = XML_CATA_PREFER_PUBLIC; 01374 } else { 01375 xmlCatalogErr(NULL, cur, XML_CATALOG_PREFER_VALUE, 01376 "Invalid value for prefer: '%s'\n", 01377 prop, NULL, NULL); 01378 } 01379 xmlFree(prop); 01380 } 01381 cur = cur->children; 01382 xmlParseXMLCatalogNodeList(cur, prefer, parent, NULL); 01383 } else { 01384 xmlCatalogErr(NULL, (xmlNodePtr) doc, XML_CATALOG_NOT_CATALOG, 01385 "File %s is not an XML Catalog\n", 01386 filename, NULL, NULL); 01387 xmlFreeDoc(doc); 01388 return(NULL); 01389 } 01390 xmlFreeDoc(doc); 01391 return(parent); 01392 } 01393 01402 static int 01403 xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) { 01404 xmlCatalogEntryPtr doc; 01405 01406 if (catal == NULL) 01407 return(-1); 01408 if (catal->URL == NULL) 01409 return(-1); 01410 if (catal->children != NULL) 01411 return(-1); 01412 01413 /* 01414 * lock the whole catalog for modification 01415 */ 01416 xmlRMutexLock(xmlCatalogMutex); 01417 if (catal->children != NULL) { 01418 /* Okay someone else did it in the meantime */ 01419 xmlRMutexUnlock(xmlCatalogMutex); 01420 return(0); 01421 } 01422 01423 if (xmlCatalogXMLFiles != NULL) { 01424 doc = (xmlCatalogEntryPtr) 01425 xmlHashLookup(xmlCatalogXMLFiles, catal->URL); 01426 if (doc != NULL) { 01427 if (xmlDebugCatalogs) 01428 xmlGenericError(xmlGenericErrorContext, 01429 "Found %s in file hash\n", catal->URL); 01430 01431 if (catal->type == XML_CATA_CATALOG) 01432 catal->children = doc->children; 01433 else 01434 catal->children = doc; 01435 catal->dealloc = 0; 01436 xmlRMutexUnlock(xmlCatalogMutex); 01437 return(0); 01438 } 01439 if (xmlDebugCatalogs) 01440 xmlGenericError(xmlGenericErrorContext, 01441 "%s not found in file hash\n", catal->URL); 01442 } 01443 01444 /* 01445 * Fetch and parse. Note that xmlParseXMLCatalogFile does not 01446 * use the existing catalog, there is no recursion allowed at 01447 * that level. 01448 */ 01449 doc = xmlParseXMLCatalogFile(catal->prefer, catal->URL); 01450 if (doc == NULL) { 01451 catal->type = XML_CATA_BROKEN_CATALOG; 01452 xmlRMutexUnlock(xmlCatalogMutex); 01453 return(-1); 01454 } 01455 01456 if (catal->type == XML_CATA_CATALOG) 01457 catal->children = doc->children; 01458 else 01459 catal->children = doc; 01460 01461 doc->dealloc = 1; 01462 01463 if (xmlCatalogXMLFiles == NULL) 01464 xmlCatalogXMLFiles = xmlHashCreate(10); 01465 if (xmlCatalogXMLFiles != NULL) { 01466 if (xmlDebugCatalogs) 01467 xmlGenericError(xmlGenericErrorContext, 01468 "%s added to file hash\n", catal->URL); 01469 xmlHashAddEntry(xmlCatalogXMLFiles, catal->URL, doc); 01470 } 01471 xmlRMutexUnlock(xmlCatalogMutex); 01472 return(0); 01473 } 01474 01475 /************************************************************************ 01476 * * 01477 * XML Catalog handling * 01478 * * 01479 ************************************************************************/ 01480 01493 static int 01494 xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type, 01495 const xmlChar *orig, const xmlChar *replace) { 01496 xmlCatalogEntryPtr cur; 01497 xmlCatalogEntryType typ; 01498 int doregister = 0; 01499 01500 if ((catal == NULL) || 01501 ((catal->type != XML_CATA_CATALOG) && 01502 (catal->type != XML_CATA_BROKEN_CATALOG))) 01503 return(-1); 01504 if (catal->children == NULL) { 01505 xmlFetchXMLCatalogFile(catal); 01506 } 01507 if (catal->children == NULL) 01508 doregister = 1; 01509 01510 typ = xmlGetXMLCatalogEntryType(type); 01511 if (typ == XML_CATA_NONE) { 01512 if (xmlDebugCatalogs) 01513 xmlGenericError(xmlGenericErrorContext, 01514 "Failed to add unknown element %s to catalog\n", type); 01515 return(-1); 01516 } 01517 01518 cur = catal->children; 01519 /* 01520 * Might be a simple "update in place" 01521 */ 01522 if (cur != NULL) { 01523 while (cur != NULL) { 01524 if ((orig != NULL) && (cur->type == typ) && 01525 (xmlStrEqual(orig, cur->name))) { 01526 if (xmlDebugCatalogs) 01527 xmlGenericError(xmlGenericErrorContext, 01528 "Updating element %s to catalog\n", type); 01529 if (cur->value != NULL) 01530 xmlFree(cur->value); 01531 if (cur->URL != NULL) 01532 xmlFree(cur->URL); 01533 cur->value = xmlStrdup(replace); 01534 cur->URL = xmlStrdup(replace); 01535 return(0); 01536 } 01537 if (cur->next == NULL) 01538 break; 01539 cur = cur->next; 01540 } 01541 } 01542 if (xmlDebugCatalogs) 01543 xmlGenericError(xmlGenericErrorContext, 01544 "Adding element %s to catalog\n", type); 01545 if (cur == NULL) 01546 catal->children = xmlNewCatalogEntry(typ, orig, replace, 01547 NULL, catal->prefer, NULL); 01548 else 01549 cur->next = xmlNewCatalogEntry(typ, orig, replace, 01550 NULL, catal->prefer, NULL); 01551 if (doregister) { 01552 catal->type = XML_CATA_CATALOG; 01553 cur = xmlHashLookup(xmlCatalogXMLFiles, catal->URL); 01554 if (cur != NULL) 01555 cur->children = catal->children; 01556 } 01557 01558 return(0); 01559 } 01560 01571 static int 01572 xmlDelXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *value) { 01573 xmlCatalogEntryPtr cur; 01574 int ret = 0; 01575 01576 if ((catal == NULL) || 01577 ((catal->type != XML_CATA_CATALOG) && 01578 (catal->type != XML_CATA_BROKEN_CATALOG))) 01579 return(-1); 01580 if (value == NULL) 01581 return(-1); 01582 if (catal->children == NULL) { 01583 xmlFetchXMLCatalogFile(catal); 01584 } 01585 01586 /* 01587 * Scan the children 01588 */ 01589 cur = catal->children; 01590 while (cur != NULL) { 01591 if (((cur->name != NULL) && (xmlStrEqual(value, cur->name))) || 01592 (xmlStrEqual(value, cur->value))) { 01593 if (xmlDebugCatalogs) { 01594 if (cur->name != NULL) 01595 xmlGenericError(xmlGenericErrorContext, 01596 "Removing element %s from catalog\n", cur->name); 01597 else 01598 xmlGenericError(xmlGenericErrorContext, 01599 "Removing element %s from catalog\n", cur->value); 01600 } 01601 cur->type = XML_CATA_REMOVED; 01602 } 01603 cur = cur->next; 01604 } 01605 return(ret); 01606 } 01607 01622 static xmlChar * 01623 xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, 01624 const xmlChar *sysID) { 01625 xmlChar *ret = NULL; 01626 xmlCatalogEntryPtr cur; 01627 int haveDelegate = 0; 01628 int haveNext = 0; 01629 01630 /* 01631 * protection against loops 01632 */ 01633 if (catal->depth > MAX_CATAL_DEPTH) { 01634 xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION, 01635 "Detected recursion in catalog %s\n", 01636 catal->name, NULL, NULL); 01637 return(NULL); 01638 } 01639 catal->depth++; 01640 01641 /* 01642 * First tries steps 2/ 3/ 4/ if a system ID is provided. 01643 */ 01644 if (sysID != NULL) { 01645 xmlCatalogEntryPtr rewrite = NULL; 01646 int lenrewrite = 0, len; 01647 cur = catal; 01648 haveDelegate = 0; 01649 while (cur != NULL) { 01650 switch (cur->type) { 01651 case XML_CATA_SYSTEM: 01652 if (xmlStrEqual(sysID, cur->name)) { 01653 if (xmlDebugCatalogs) 01654 xmlGenericError(xmlGenericErrorContext, 01655 "Found system match %s, using %s\n", 01656 cur->name, cur->URL); 01657 catal->depth--; 01658 return(xmlStrdup(cur->URL)); 01659 } 01660 break; 01661 case XML_CATA_REWRITE_SYSTEM: 01662 len = xmlStrlen(cur->name); 01663 if ((len > lenrewrite) && 01664 (!xmlStrncmp(sysID, cur->name, len))) { 01665 lenrewrite = len; 01666 rewrite = cur; 01667 } 01668 break; 01669 case XML_CATA_DELEGATE_SYSTEM: 01670 if (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name))) 01671 haveDelegate++; 01672 break; 01673 case XML_CATA_NEXT_CATALOG: 01674 haveNext++; 01675 break; 01676 default: 01677 break; 01678 } 01679 cur = cur->next; 01680 } 01681 if (rewrite != NULL) { 01682 if (xmlDebugCatalogs) 01683 xmlGenericError(xmlGenericErrorContext, 01684 "Using rewriting rule %s\n", rewrite->name); 01685 ret = xmlStrdup(rewrite->URL); 01686 if (ret != NULL) 01687 ret = xmlStrcat(ret, &sysID[lenrewrite]); 01688 catal->depth--; 01689 return(ret); 01690 } 01691 if (haveDelegate) { 01692 const xmlChar *delegates[MAX_DELEGATE]; 01693 int nbList = 0, i; 01694 01695 /* 01696 * Assume the entries have been sorted by decreasing substring 01697 * matches when the list was produced. 01698 */ 01699 cur = catal; 01700 while (cur != NULL) { 01701 if ((cur->type == XML_CATA_DELEGATE_SYSTEM) && 01702 (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))) { 01703 for (i = 0;i < nbList;i++) 01704 if (xmlStrEqual(cur->URL, delegates[i])) 01705 break; 01706 if (i < nbList) { 01707 cur = cur->next; 01708 continue; 01709 } 01710 if (nbList < MAX_DELEGATE) 01711 delegates[nbList++] = cur->URL; 01712 01713 if (cur->children == NULL) { 01714 xmlFetchXMLCatalogFile(cur); 01715 } 01716 if (cur->children != NULL) { 01717 if (xmlDebugCatalogs) 01718 xmlGenericError(xmlGenericErrorContext, 01719 "Trying system delegate %s\n", cur->URL); 01720 ret = xmlCatalogListXMLResolve( 01721 cur->children, NULL, sysID); 01722 if (ret != NULL) { 01723 catal->depth--; 01724 return(ret); 01725 } 01726 } 01727 } 01728 cur = cur->next; 01729 } 01730 /* 01731 * Apply the cut algorithm explained in 4/ 01732 */ 01733 catal->depth--; 01734 return(XML_CATAL_BREAK); 01735 } 01736 } 01737 /* 01738 * Then tries 5/ 6/ if a public ID is provided 01739 */ 01740 if (pubID != NULL) { 01741 cur = catal; 01742 haveDelegate = 0; 01743 while (cur != NULL) { 01744 switch (cur->type) { 01745 case XML_CATA_PUBLIC: 01746 if (xmlStrEqual(pubID, cur->name)) { 01747 if (xmlDebugCatalogs) 01748 xmlGenericError(xmlGenericErrorContext, 01749 "Found public match %s\n", cur->name); 01750 catal->depth--; 01751 return(xmlStrdup(cur->URL)); 01752 } 01753 break; 01754 case XML_CATA_DELEGATE_PUBLIC: 01755 if (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)) && 01756 (cur->prefer == XML_CATA_PREFER_PUBLIC)) 01757 haveDelegate++; 01758 break; 01759 case XML_CATA_NEXT_CATALOG: 01760 if (sysID == NULL) 01761 haveNext++; 01762 break; 01763 default: 01764 break; 01765 } 01766 cur = cur->next; 01767 } 01768 if (haveDelegate) { 01769 const xmlChar *delegates[MAX_DELEGATE]; 01770 int nbList = 0, i; 01771 01772 /* 01773 * Assume the entries have been sorted by decreasing substring 01774 * matches when the list was produced. 01775 */ 01776 cur = catal; 01777 while (cur != NULL) { 01778 if ((cur->type == XML_CATA_DELEGATE_PUBLIC) && 01779 (cur->prefer == XML_CATA_PREFER_PUBLIC) && 01780 (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)))) { 01781 01782 for (i = 0;i < nbList;i++) 01783 if (xmlStrEqual(cur->URL, delegates[i])) 01784 break; 01785 if (i < nbList) { 01786 cur = cur->next; 01787 continue; 01788 } 01789 if (nbList < MAX_DELEGATE) 01790 delegates[nbList++] = cur->URL; 01791 01792 if (cur->children == NULL) { 01793 xmlFetchXMLCatalogFile(cur); 01794 } 01795 if (cur->children != NULL) { 01796 if (xmlDebugCatalogs) 01797 xmlGenericError(xmlGenericErrorContext, 01798 "Trying public delegate %s\n", cur->URL); 01799 ret = xmlCatalogListXMLResolve( 01800 cur->children, pubID, NULL); 01801 if (ret != NULL) { 01802 catal->depth--; 01803 return(ret); 01804 } 01805 } 01806 } 01807 cur = cur->next; 01808 } 01809 /* 01810 * Apply the cut algorithm explained in 4/ 01811 */ 01812 catal->depth--; 01813 return(XML_CATAL_BREAK); 01814 } 01815 } 01816 if (haveNext) { 01817 cur = catal; 01818 while (cur != NULL) { 01819 if (cur->type == XML_CATA_NEXT_CATALOG) { 01820 if (cur->children == NULL) { 01821 xmlFetchXMLCatalogFile(cur); 01822 } 01823 if (cur->children != NULL) { 01824 ret = xmlCatalogListXMLResolve(cur->children, pubID, sysID); 01825 if (ret != NULL) { 01826 catal->depth--; 01827 return(ret); 01828 } else if (catal->depth > MAX_CATAL_DEPTH) { 01829 return(NULL); 01830 } 01831 } 01832 } 01833 cur = cur->next; 01834 } 01835 } 01836 01837 catal->depth--; 01838 return(NULL); 01839 } 01840 01855 static xmlChar * 01856 xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) { 01857 xmlChar *ret = NULL; 01858 xmlCatalogEntryPtr cur; 01859 int haveDelegate = 0; 01860 int haveNext = 0; 01861 xmlCatalogEntryPtr rewrite = NULL; 01862 int lenrewrite = 0, len; 01863 01864 if (catal == NULL) 01865 return(NULL); 01866 01867 if (URI == NULL) 01868 return(NULL); 01869 01870 if (catal->depth > MAX_CATAL_DEPTH) { 01871 xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION, 01872 "Detected recursion in catalog %s\n", 01873 catal->name, NULL, NULL); 01874 return(NULL); 01875 } 01876 01877 /* 01878 * First tries steps 2/ 3/ 4/ if a system ID is provided. 01879 */ 01880 cur = catal; 01881 haveDelegate = 0; 01882 while (cur != NULL) { 01883 switch (cur->type) { 01884 case XML_CATA_URI: 01885 if (xmlStrEqual(URI, cur->name)) { 01886 if (xmlDebugCatalogs) 01887 xmlGenericError(xmlGenericErrorContext, 01888 "Found URI match %s\n", cur->name); 01889 return(xmlStrdup(cur->URL)); 01890 } 01891 break; 01892 case XML_CATA_REWRITE_URI: 01893 len = xmlStrlen(cur->name); 01894 if ((len > lenrewrite) && 01895 (!xmlStrncmp(URI, cur->name, len))) { 01896 lenrewrite = len; 01897 rewrite = cur; 01898 } 01899 break; 01900 case XML_CATA_DELEGATE_URI: 01901 if (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name))) 01902 haveDelegate++; 01903 break; 01904 case XML_CATA_NEXT_CATALOG: 01905 haveNext++; 01906 break; 01907 default: 01908 break; 01909 } 01910 cur = cur->next; 01911 } 01912 if (rewrite != NULL) { 01913 if (xmlDebugCatalogs) 01914 xmlGenericError(xmlGenericErrorContext, 01915 "Using rewriting rule %s\n", rewrite->name); 01916 ret = xmlStrdup(rewrite->URL); 01917 if (ret != NULL) 01918 ret = xmlStrcat(ret, &URI[lenrewrite]); 01919 return(ret); 01920 } 01921 if (haveDelegate) { 01922 const xmlChar *delegates[MAX_DELEGATE]; 01923 int nbList = 0, i; 01924 01925 /* 01926 * Assume the entries have been sorted by decreasing substring 01927 * matches when the list was produced. 01928 */ 01929 cur = catal; 01930 while (cur != NULL) { 01931 if (((cur->type == XML_CATA_DELEGATE_SYSTEM) || 01932 (cur->type == XML_CATA_DELEGATE_URI)) && 01933 (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))) { 01934 for (i = 0;i < nbList;i++) 01935 if (xmlStrEqual(cur->URL, delegates[i])) 01936 break; 01937 if (i < nbList) { 01938 cur = cur->next; 01939 continue; 01940 } 01941 if (nbList < MAX_DELEGATE) 01942 delegates[nbList++] = cur->URL; 01943 01944 if (cur->children == NULL) { 01945 xmlFetchXMLCatalogFile(cur); 01946 } 01947 if (cur->children != NULL) { 01948 if (xmlDebugCatalogs) 01949 xmlGenericError(xmlGenericErrorContext, 01950 "Trying URI delegate %s\n", cur->URL); 01951 ret = xmlCatalogListXMLResolveURI( 01952 cur->children, URI); 01953 if (ret != NULL) 01954 return(ret); 01955 } 01956 } 01957 cur = cur->next; 01958 } 01959 /* 01960 * Apply the cut algorithm explained in 4/ 01961 */ 01962 return(XML_CATAL_BREAK); 01963 } 01964 if (haveNext) { 01965 cur = catal; 01966 while (cur != NULL) { 01967 if (cur->type == XML_CATA_NEXT_CATALOG) { 01968 if (cur->children == NULL) { 01969 xmlFetchXMLCatalogFile(cur); 01970 } 01971 if (cur->children != NULL) { 01972 ret = xmlCatalogListXMLResolveURI(cur->children, URI); 01973 if (ret != NULL) 01974 return(ret); 01975 } 01976 } 01977 cur = cur->next; 01978 } 01979 } 01980 01981 return(NULL); 01982 } 01983 01998 static xmlChar * 01999 xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, 02000 const xmlChar *sysID) { 02001 xmlChar *ret = NULL; 02002 xmlChar *urnID = NULL; 02003 xmlChar *normid; 02004 02005 if (catal == NULL) 02006 return(NULL); 02007 if ((pubID == NULL) && (sysID == NULL)) 02008 return(NULL); 02009 02010 normid = xmlCatalogNormalizePublic(pubID); 02011 if (normid != NULL) 02012 pubID = (*normid != 0 ? normid : NULL); 02013 02014 if (!xmlStrncmp(pubID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) { 02015 urnID = xmlCatalogUnWrapURN(pubID); 02016 if (xmlDebugCatalogs) { 02017 if (urnID == NULL) 02018 xmlGenericError(xmlGenericErrorContext, 02019 "Public URN ID %s expanded to NULL\n", pubID); 02020 else 02021 xmlGenericError(xmlGenericErrorContext, 02022 "Public URN ID expanded to %s\n", urnID); 02023 } 02024 ret = xmlCatalogListXMLResolve(catal, urnID, sysID); 02025 if (urnID != NULL) 02026 xmlFree(urnID); 02027 if (normid != NULL) 02028 xmlFree(normid); 02029 return(ret); 02030 } 02031 if (!xmlStrncmp(sysID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) { 02032 urnID = xmlCatalogUnWrapURN(sysID); 02033 if (xmlDebugCatalogs) { 02034 if (urnID == NULL) 02035 xmlGenericError(xmlGenericErrorContext, 02036 "System URN ID %s expanded to NULL\n", sysID); 02037 else 02038 xmlGenericError(xmlGenericErrorContext, 02039 "System URN ID expanded to %s\n", urnID); 02040 } 02041 if (pubID == NULL) 02042 ret = xmlCatalogListXMLResolve(catal, urnID, NULL); 02043 else if (xmlStrEqual(pubID, urnID)) 02044 ret = xmlCatalogListXMLResolve(catal, pubID, NULL); 02045 else { 02046 ret = xmlCatalogListXMLResolve(catal, pubID, urnID); 02047 } 02048 if (urnID != NULL) 02049 xmlFree(urnID); 02050 if (normid != NULL) 02051 xmlFree(normid); 02052 return(ret); 02053 } 02054 while (catal != NULL) { 02055 if (catal->type == XML_CATA_CATALOG) { 02056 if (catal->children == NULL) { 02057 xmlFetchXMLCatalogFile(catal); 02058 } 02059 if (catal->children != NULL) { 02060 ret = xmlCatalogXMLResolve(catal->children, pubID, sysID); 02061 if (ret != NULL) { 02062 break; 02063 } else if ((catal->children != NULL) && 02064 (catal->children->depth > MAX_CATAL_DEPTH)) { 02065 ret = NULL; 02066 break; 02067 } 02068 } 02069 } 02070 catal = catal->next; 02071 } 02072 if (normid != NULL) 02073 xmlFree(normid); 02074 return(ret); 02075 } 02076 02089 static xmlChar * 02090 xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) { 02091 xmlChar *ret = NULL; 02092 xmlChar *urnID = NULL; 02093 02094 if (catal == NULL) 02095 return(NULL); 02096 if (URI == NULL) 02097 return(NULL); 02098 02099 if (!xmlStrncmp(URI, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) { 02100 urnID = xmlCatalogUnWrapURN(URI); 02101 if (xmlDebugCatalogs) { 02102 if (urnID == NULL) 02103 xmlGenericError(xmlGenericErrorContext, 02104 "URN ID %s expanded to NULL\n", URI); 02105 else 02106 xmlGenericError(xmlGenericErrorContext, 02107 "URN ID expanded to %s\n", urnID); 02108 } 02109 ret = xmlCatalogListXMLResolve(catal, urnID, NULL); 02110 if (urnID != NULL) 02111 xmlFree(urnID); 02112 return(ret); 02113 } 02114 while (catal != NULL) { 02115 if (catal->type == XML_CATA_CATALOG) { 02116 if (catal->children == NULL) { 02117 xmlFetchXMLCatalogFile(catal); 02118 } 02119 if (catal->children != NULL) { 02120 ret = xmlCatalogXMLResolveURI(catal->children, URI); 02121 if (ret != NULL) 02122 return(ret); 02123 } 02124 } 02125 catal = catal->next; 02126 } 02127 return(ret); 02128 } 02129 02130 /************************************************************************ 02131 * * 02132 * The SGML Catalog parser * 02133 * * 02134 ************************************************************************/ 02135 02136 02137 #define RAW *cur 02138 #define NEXT cur++; 02139 #define SKIP(x) cur += x; 02140 02141 #define SKIP_BLANKS while (IS_BLANK_CH(*cur)) NEXT; 02142 02151 static const xmlChar * 02152 xmlParseSGMLCatalogComment(const xmlChar *cur) { 02153 if ((cur[0] != '-') || (cur[1] != '-')) 02154 return(cur); 02155 SKIP(2); 02156 while ((cur[0] != 0) && ((cur[0] != '-') || ((cur[1] != '-')))) 02157 NEXT; 02158 if (cur[0] == 0) { 02159 return(NULL); 02160 } 02161 return(cur + 2); 02162 } 02163 02173 static const xmlChar * 02174 xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) { 02175 xmlChar *buf = NULL, *tmp; 02176 int len = 0; 02177 int size = 50; 02178 xmlChar stop; 02179 int count = 0; 02180 02181 *id = NULL; 02182 02183 if (RAW == '"') { 02184 NEXT; 02185 stop = '"'; 02186 } else if (RAW == '\'') { 02187 NEXT; 02188 stop = '\''; 02189 } else { 02190 stop = ' '; 02191 } 02192 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); 02193 if (buf == NULL) { 02194 xmlCatalogErrMemory("allocating public ID"); 02195 return(NULL); 02196 } 02197 while (IS_PUBIDCHAR_CH(*cur) || (*cur == '?')) { 02198 if ((*cur == stop) && (stop != ' ')) 02199 break; 02200 if ((stop == ' ') && (IS_BLANK_CH(*cur))) 02201 break; 02202 if (len + 1 >= size) { 02203 size *= 2; 02204 tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); 02205 if (tmp == NULL) { 02206 xmlCatalogErrMemory("allocating public ID"); 02207 xmlFree(buf); 02208 return(NULL); 02209 } 02210 buf = tmp; 02211 } 02212 buf[len++] = *cur; 02213 count++; 02214 NEXT; 02215 } 02216 buf[len] = 0; 02217 if (stop == ' ') { 02218 if (!IS_BLANK_CH(*cur)) { 02219 xmlFree(buf); 02220 return(NULL); 02221 } 02222 } else { 02223 if (*cur != stop) { 02224 xmlFree(buf); 02225 return(NULL); 02226 } 02227 NEXT; 02228 } 02229 *id = buf; 02230 return(cur); 02231 } 02232 02242 static const xmlChar * 02243 xmlParseSGMLCatalogName(const xmlChar *cur, xmlChar **name) { 02244 xmlChar buf[XML_MAX_NAMELEN + 5]; 02245 int len = 0; 02246 int c; 02247 02248 *name = NULL; 02249 02250 /* 02251 * Handler for more complex cases 02252 */ 02253 c = *cur; 02254 if ((!IS_LETTER(c) && (c != '_') && (c != ':'))) { 02255 return(NULL); 02256 } 02257 02258 while (((IS_LETTER(c)) || (IS_DIGIT(c)) || 02259 (c == '.') || (c == '-') || 02260 (c == '_') || (c == ':'))) { 02261 buf[len++] = c; 02262 cur++; 02263 c = *cur; 02264 if (len >= XML_MAX_NAMELEN) 02265 return(NULL); 02266 } 02267 *name = xmlStrndup(buf, len); 02268 return(cur); 02269 } 02270 02279 static xmlCatalogEntryType 02280 xmlGetSGMLCatalogEntryType(const xmlChar *name) { 02281 xmlCatalogEntryType type = XML_CATA_NONE; 02282 if (xmlStrEqual(name, (const xmlChar *) "SYSTEM")) 02283 type = SGML_CATA_SYSTEM; 02284 else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC")) 02285 type = SGML_CATA_PUBLIC; 02286 else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE")) 02287 type = SGML_CATA_DELEGATE; 02288 else if (xmlStrEqual(name, (const xmlChar *) "ENTITY")) 02289 type = SGML_CATA_ENTITY; 02290 else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE")) 02291 type = SGML_CATA_DOCTYPE; 02292 else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE")) 02293 type = SGML_CATA_LINKTYPE; 02294 else if (xmlStrEqual(name, (const xmlChar *) "NOTATION")) 02295 type = SGML_CATA_NOTATION; 02296 else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL")) 02297 type = SGML_CATA_SGMLDECL; 02298 else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT")) 02299 type = SGML_CATA_DOCUMENT; 02300 else if (xmlStrEqual(name, (const xmlChar *) "CATALOG")) 02301 type = SGML_CATA_CATALOG; 02302 else if (xmlStrEqual(name, (const xmlChar *) "BASE")) 02303 type = SGML_CATA_BASE; 02304 return(type); 02305 } 02306 02320 static int 02321 xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value, 02322 const char *file, int super) { 02323 const xmlChar *cur = value; 02324 xmlChar *base = NULL; 02325 int res; 02326 02327 if ((cur == NULL) || (file == NULL)) 02328 return(-1); 02329 base = xmlStrdup((const xmlChar *) file); 02330 02331 while ((cur != NULL) && (cur[0] != 0)) { 02332 SKIP_BLANKS; 02333 if (cur[0] == 0) 02334 break; 02335 if ((cur[0] == '-') && (cur[1] == '-')) { 02336 cur = xmlParseSGMLCatalogComment(cur); 02337 if (cur == NULL) { 02338 /* error */ 02339 break; 02340 } 02341 } else { 02342 xmlChar *sysid = NULL; 02343 xmlChar *name = NULL; 02344 xmlCatalogEntryType type = XML_CATA_NONE; 02345 02346 cur = xmlParseSGMLCatalogName(cur, &name); 02347 if (name == NULL) { 02348 /* error */ 02349 break; 02350 } 02351 if (!IS_BLANK_CH(*cur)) { 02352 /* error */ 02353 break; 02354 } 02355 SKIP_BLANKS; 02356 if (xmlStrEqual(name, (const xmlChar *) "SYSTEM")) 02357 type = SGML_CATA_SYSTEM; 02358 else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC")) 02359 type = SGML_CATA_PUBLIC; 02360 else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE")) 02361 type = SGML_CATA_DELEGATE; 02362 else if (xmlStrEqual(name, (const xmlChar *) "ENTITY")) 02363 type = SGML_CATA_ENTITY; 02364 else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE")) 02365 type = SGML_CATA_DOCTYPE; 02366 else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE")) 02367 type = SGML_CATA_LINKTYPE; 02368 else if (xmlStrEqual(name, (const xmlChar *) "NOTATION")) 02369 type = SGML_CATA_NOTATION; 02370 else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL")) 02371 type = SGML_CATA_SGMLDECL; 02372 else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT")) 02373 type = SGML_CATA_DOCUMENT; 02374 else if (xmlStrEqual(name, (const xmlChar *) "CATALOG")) 02375 type = SGML_CATA_CATALOG; 02376 else if (xmlStrEqual(name, (const xmlChar *) "BASE")) 02377 type = SGML_CATA_BASE; 02378 else if (xmlStrEqual(name, (const xmlChar *) "OVERRIDE")) { 02379 xmlFree(name); 02380 cur = xmlParseSGMLCatalogName(cur, &name); 02381 if (name == NULL) { 02382 /* error */ 02383 break; 02384 } 02385 xmlFree(name); 02386 continue; 02387 } 02388 xmlFree(name); 02389 name = NULL; 02390 02391 switch(type) { 02392 case SGML_CATA_ENTITY: 02393 if (*cur == '%') 02394 type = SGML_CATA_PENTITY; 02395 case SGML_CATA_PENTITY: 02396 case SGML_CATA_DOCTYPE: 02397 case SGML_CATA_LINKTYPE: 02398 case SGML_CATA_NOTATION: 02399 cur = xmlParseSGMLCatalogName(cur, &name); 02400 if (cur == NULL) { 02401 /* error */ 02402 break; 02403 } 02404 if (!IS_BLANK_CH(*cur)) { 02405 /* error */ 02406 break; 02407 } 02408 SKIP_BLANKS; 02409 cur = xmlParseSGMLCatalogPubid(cur, &sysid); 02410 if (cur == NULL) { 02411 /* error */ 02412 break; 02413 } 02414 break; 02415 case SGML_CATA_PUBLIC: 02416 case SGML_CATA_SYSTEM: 02417 case SGML_CATA_DELEGATE: 02418 cur = xmlParseSGMLCatalogPubid(cur, &name); 02419 if (cur == NULL) { 02420 /* error */ 02421 break; 02422 } 02423 if (type != SGML_CATA_SYSTEM) { 02424 xmlChar *normid; 02425 02426 normid = xmlCatalogNormalizePublic(name); 02427 if (normid != NULL) { 02428 if (name != NULL) 02429 xmlFree(name); 02430 if (*normid != 0) 02431 name = normid; 02432 else { 02433 xmlFree(normid); 02434 name = NULL; 02435 } 02436 } 02437 } 02438 if (!IS_BLANK_CH(*cur)) { 02439 /* error */ 02440 break; 02441 } 02442 SKIP_BLANKS; 02443 cur = xmlParseSGMLCatalogPubid(cur, &sysid); 02444 if (cur == NULL) { 02445 /* error */ 02446 break; 02447 } 02448 break; 02449 case SGML_CATA_BASE: 02450 case SGML_CATA_CATALOG: 02451 case SGML_CATA_DOCUMENT: 02452 case SGML_CATA_SGMLDECL: 02453 cur = xmlParseSGMLCatalogPubid(cur, &sysid); 02454 if (cur == NULL) { 02455 /* error */ 02456 break; 02457 } 02458 break; 02459 default: 02460 break; 02461 } 02462 if (cur == NULL) { 02463 if (name != NULL) 02464 xmlFree(name); 02465 if (sysid != NULL) 02466 xmlFree(sysid); 02467 break; 02468 } else if (type == SGML_CATA_BASE) { 02469 if (base != NULL) 02470 xmlFree(base); 02471 base = xmlStrdup(sysid); 02472 } else if ((type == SGML_CATA_PUBLIC) || 02473 (type == SGML_CATA_SYSTEM)) { 02474 xmlChar *filename; 02475 02476 filename = xmlBuildURI(sysid, base); 02477 if (filename != NULL) { 02478 xmlCatalogEntryPtr entry; 02479 02480 entry = xmlNewCatalogEntry(type, name, filename, 02481 NULL, XML_CATA_PREFER_NONE, NULL); 02482 res = xmlHashAddEntry(catal->sgml, name, entry); 02483 if (res < 0) { 02484 xmlFreeCatalogEntry(entry); 02485 } 02486 xmlFree(filename); 02487 } 02488 02489 } else if (type == SGML_CATA_CATALOG) { 02490 if (super) { 02491 xmlCatalogEntryPtr entry; 02492 02493 entry = xmlNewCatalogEntry(type, sysid, NULL, NULL, 02494 XML_CATA_PREFER_NONE, NULL); 02495 res = xmlHashAddEntry(catal->sgml, sysid, entry); 02496 if (res < 0) { 02497 xmlFreeCatalogEntry(entry); 02498 } 02499 } else { 02500 xmlChar *filename; 02501 02502 filename = xmlBuildURI(sysid, base); 02503 if (filename != NULL) { 02504 xmlExpandCatalog(catal, (const char *)filename); 02505 xmlFree(filename); 02506 } 02507 } 02508 } 02509 /* 02510 * drop anything else we won't handle it 02511 */ 02512 if (name != NULL) 02513 xmlFree(name); 02514 if (sysid != NULL) 02515 xmlFree(sysid); 02516 } 02517 } 02518 if (base != NULL) 02519 xmlFree(base); 02520 if (cur == NULL) 02521 return(-1); 02522 return(0); 02523 } 02524 02525 /************************************************************************ 02526 * * 02527 * SGML Catalog handling * 02528 * * 02529 ************************************************************************/ 02530 02540 static const xmlChar * 02541 xmlCatalogGetSGMLPublic(xmlHashTablePtr catal, const xmlChar *pubID) { 02542 xmlCatalogEntryPtr entry; 02543 xmlChar *normid; 02544 02545 if (catal == NULL) 02546 return(NULL); 02547 02548 normid = xmlCatalogNormalizePublic(pubID); 02549 if (normid != NULL) 02550 pubID = (*normid != 0 ? normid : NULL); 02551 02552 entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, pubID); 02553 if (entry == NULL) { 02554 if (normid != NULL) 02555 xmlFree(normid); 02556 return(NULL); 02557 } 02558 if (entry->type == SGML_CATA_PUBLIC) { 02559 if (normid != NULL) 02560 xmlFree(normid); 02561 return(entry->URL); 02562 } 02563 if (normid != NULL) 02564 xmlFree(normid); 02565 return(NULL); 02566 } 02567 02577 static const xmlChar * 02578 xmlCatalogGetSGMLSystem(xmlHashTablePtr catal, const xmlChar *sysID) { 02579 xmlCatalogEntryPtr entry; 02580 02581 if (catal == NULL) 02582 return(NULL); 02583 02584 entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, sysID); 02585 if (entry == NULL) 02586 return(NULL); 02587 if (entry->type == SGML_CATA_SYSTEM) 02588 return(entry->URL); 02589 return(NULL); 02590 } 02591 02602 static const xmlChar * 02603 xmlCatalogSGMLResolve(xmlCatalogPtr catal, const xmlChar *pubID, 02604 const xmlChar *sysID) { 02605 const xmlChar *ret = NULL; 02606 02607 if (catal->sgml == NULL) 02608 return(NULL); 02609 02610 if (pubID != NULL) 02611 ret = xmlCatalogGetSGMLPublic(catal->sgml, pubID); 02612 if (ret != NULL) 02613 return(ret); 02614 if (sysID != NULL) 02615 ret = xmlCatalogGetSGMLSystem(catal->sgml, sysID); 02616 if (ret != NULL) 02617 return(ret); 02618 return(NULL); 02619 } 02620 02621 /************************************************************************ 02622 * * 02623 * Specific Public interfaces * 02624 * * 02625 ************************************************************************/ 02626 02637 xmlCatalogPtr 02638 xmlLoadSGMLSuperCatalog(const char *filename) 02639 { 02640 xmlChar *content; 02641 xmlCatalogPtr catal; 02642 int ret; 02643 02644 content = xmlLoadFileContent(filename); 02645 if (content == NULL) 02646 return(NULL); 02647 02648 catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer); 02649 if (catal == NULL) { 02650 xmlFree(content); 02651 return(NULL); 02652 } 02653 02654 ret = xmlParseSGMLCatalog(catal, content, filename, 1); 02655 xmlFree(content); 02656 if (ret < 0) { 02657 xmlFreeCatalog(catal); 02658 return(NULL); 02659 } 02660 return (catal); 02661 } 02662 02674 xmlCatalogPtr 02675 xmlLoadACatalog(const char *filename) 02676 { 02677 xmlChar *content; 02678 xmlChar *first; 02679 xmlCatalogPtr catal; 02680 int ret; 02681 02682 content = xmlLoadFileContent(filename); 02683 if (content == NULL) 02684 return(NULL); 02685 02686 02687 first = content; 02688 02689 while ((*first != 0) && (*first != '-') && (*first != '<') && 02690 (!(((*first >= 'A') && (*first <= 'Z')) || 02691 ((*first >= 'a') && (*first <= 'z'))))) 02692 first++; 02693 02694 if (*first != '<') { 02695 catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer); 02696 if (catal == NULL) { 02697 xmlFree(content); 02698 return(NULL); 02699 } 02700 ret = xmlParseSGMLCatalog(catal, content, filename, 0); 02701 if (ret < 0) { 02702 xmlFreeCatalog(catal); 02703 xmlFree(content); 02704 return(NULL); 02705 } 02706 } else { 02707 catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer); 02708 if (catal == NULL) { 02709 xmlFree(content); 02710 return(NULL); 02711 } 02712 catal->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, 02713 NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL); 02714 } 02715 xmlFree(content); 02716 return (catal); 02717 } 02718 02729 static int 02730 xmlExpandCatalog(xmlCatalogPtr catal, const char *filename) 02731 { 02732 int ret; 02733 02734 if ((catal == NULL) || (filename == NULL)) 02735 return(-1); 02736 02737 02738 if (catal->type == XML_SGML_CATALOG_TYPE) { 02739 xmlChar *content; 02740 02741 content = xmlLoadFileContent(filename); 02742 if (content == NULL) 02743 return(-1); 02744 02745 ret = xmlParseSGMLCatalog(catal, content, filename, 0); 02746 if (ret < 0) { 02747 xmlFree(content); 02748 return(-1); 02749 } 02750 xmlFree(content); 02751 } else { 02752 xmlCatalogEntryPtr tmp, cur; 02753 tmp = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, 02754 NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL); 02755 02756 cur = catal->xml; 02757 if (cur == NULL) { 02758 catal->xml = tmp; 02759 } else { 02760 while (cur->next != NULL) cur = cur->next; 02761 cur->next = tmp; 02762 } 02763 } 02764 return (0); 02765 } 02766 02777 xmlChar * 02778 xmlACatalogResolveSystem(xmlCatalogPtr catal, const xmlChar *sysID) { 02779 xmlChar *ret = NULL; 02780 02781 if ((sysID == NULL) || (catal == NULL)) 02782 return(NULL); 02783 02784 if (xmlDebugCatalogs) 02785 xmlGenericError(xmlGenericErrorContext, 02786 "Resolve sysID %s\n", sysID); 02787 02788 if (catal->type == XML_XML_CATALOG_TYPE) { 02789 ret = xmlCatalogListXMLResolve(catal->xml, NULL, sysID); 02790 if (ret == XML_CATAL_BREAK) 02791 ret = NULL; 02792 } else { 02793 const xmlChar *sgml; 02794 02795 sgml = xmlCatalogGetSGMLSystem(catal->sgml, sysID); 02796 if (sgml != NULL) 02797 ret = xmlStrdup(sgml); 02798 } 02799 return(ret); 02800 } 02801 02812 xmlChar * 02813 xmlACatalogResolvePublic(xmlCatalogPtr catal, const xmlChar *pubID) { 02814 xmlChar *ret = NULL; 02815 02816 if ((pubID == NULL) || (catal == NULL)) 02817 return(NULL); 02818 02819 if (xmlDebugCatalogs) 02820 xmlGenericError(xmlGenericErrorContext, 02821 "Resolve pubID %s\n", pubID); 02822 02823 if (catal->type == XML_XML_CATALOG_TYPE) { 02824 ret = xmlCatalogListXMLResolve(catal->xml, pubID, NULL); 02825 if (ret == XML_CATAL_BREAK) 02826 ret = NULL; 02827 } else { 02828 const xmlChar *sgml; 02829 02830 sgml = xmlCatalogGetSGMLPublic(catal->sgml, pubID); 02831 if (sgml != NULL) 02832 ret = xmlStrdup(sgml); 02833 } 02834 return(ret); 02835 } 02836 02848 xmlChar * 02849 xmlACatalogResolve(xmlCatalogPtr catal, const xmlChar * pubID, 02850 const xmlChar * sysID) 02851 { 02852 xmlChar *ret = NULL; 02853 02854 if (((pubID == NULL) && (sysID == NULL)) || (catal == NULL)) 02855 return (NULL); 02856 02857 if (xmlDebugCatalogs) { 02858 if ((pubID != NULL) && (sysID != NULL)) { 02859 xmlGenericError(xmlGenericErrorContext, 02860 "Resolve: pubID %s sysID %s\n", pubID, sysID); 02861 } else if (pubID != NULL) { 02862 xmlGenericError(xmlGenericErrorContext, 02863 "Resolve: pubID %s\n", pubID); 02864 } else { 02865 xmlGenericError(xmlGenericErrorContext, 02866 "Resolve: sysID %s\n", sysID); 02867 } 02868 } 02869 02870 if (catal->type == XML_XML_CATALOG_TYPE) { 02871 ret = xmlCatalogListXMLResolve(catal->xml, pubID, sysID); 02872 if (ret == XML_CATAL_BREAK) 02873 ret = NULL; 02874 } else { 02875 const xmlChar *sgml; 02876 02877 sgml = xmlCatalogSGMLResolve(catal, pubID, sysID); 02878 if (sgml != NULL) 02879 ret = xmlStrdup(sgml); 02880 } 02881 return (ret); 02882 } 02883 02894 xmlChar * 02895 xmlACatalogResolveURI(xmlCatalogPtr catal, const xmlChar *URI) { 02896 xmlChar *ret = NULL; 02897 02898 if ((URI == NULL) || (catal == NULL)) 02899 return(NULL); 02900 02901 if (xmlDebugCatalogs) 02902 xmlGenericError(xmlGenericErrorContext, 02903 "Resolve URI %s\n", URI); 02904 02905 if (catal->type == XML_XML_CATALOG_TYPE) { 02906 ret = xmlCatalogListXMLResolveURI(catal->xml, URI); 02907 if (ret == XML_CATAL_BREAK) 02908 ret = NULL; 02909 } else { 02910 const xmlChar *sgml; 02911 02912 sgml = xmlCatalogSGMLResolve(catal, NULL, URI); 02913 if (sgml != NULL) 02914 ret = xmlStrdup(sgml); 02915 } 02916 return(ret); 02917 } 02918 02919 #ifdef LIBXML_OUTPUT_ENABLED 02920 02927 void 02928 xmlACatalogDump(xmlCatalogPtr catal, FILE *out) { 02929 if ((out == NULL) || (catal == NULL)) 02930 return; 02931 02932 if (catal->type == XML_XML_CATALOG_TYPE) { 02933 xmlDumpXMLCatalog(out, catal->xml); 02934 } else { 02935 xmlHashScan(catal->sgml, 02936 (xmlHashScanner) xmlCatalogDumpEntry, out); 02937 } 02938 } 02939 #endif /* LIBXML_OUTPUT_ENABLED */ 02940 02953 int 02954 xmlACatalogAdd(xmlCatalogPtr catal, const xmlChar * type, 02955 const xmlChar * orig, const xmlChar * replace) 02956 { 02957 int res = -1; 02958 02959 if (catal == NULL) 02960 return(-1); 02961 02962 if (catal->type == XML_XML_CATALOG_TYPE) { 02963 res = xmlAddXMLCatalog(catal->xml, type, orig, replace); 02964 } else { 02965 xmlCatalogEntryType cattype; 02966 02967 cattype = xmlGetSGMLCatalogEntryType(type); 02968 if (cattype != XML_CATA_NONE) { 02969 xmlCatalogEntryPtr entry; 02970 02971 entry = xmlNewCatalogEntry(cattype, orig, replace, NULL, 02972 XML_CATA_PREFER_NONE, NULL); 02973 if (catal->sgml == NULL) 02974 catal->sgml = xmlHashCreate(10); 02975 res = xmlHashAddEntry(catal->sgml, orig, entry); 02976 } 02977 } 02978 return (res); 02979 } 02980 02990 int 02991 xmlACatalogRemove(xmlCatalogPtr catal, const xmlChar *value) { 02992 int res = -1; 02993 02994 if ((catal == NULL) || (value == NULL)) 02995 return(-1); 02996 02997 if (catal->type == XML_XML_CATALOG_TYPE) { 02998 res = xmlDelXMLCatalog(catal->xml, value); 02999 } else { 03000 res = xmlHashRemoveEntry(catal->sgml, value, 03001 (xmlHashDeallocator) xmlFreeCatalogEntry); 03002 if (res == 0) 03003 res = 1; 03004 } 03005 return(res); 03006 } 03007 03016 xmlCatalogPtr 03017 xmlNewCatalog(int sgml) { 03018 xmlCatalogPtr catal = NULL; 03019 03020 if (sgml) { 03021 catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, 03022 xmlCatalogDefaultPrefer); 03023 if ((catal != NULL) && (catal->sgml == NULL)) 03024 catal->sgml = xmlHashCreate(10); 03025 } else 03026 catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, 03027 xmlCatalogDefaultPrefer); 03028 return(catal); 03029 } 03030 03039 int 03040 xmlCatalogIsEmpty(xmlCatalogPtr catal) { 03041 if (catal == NULL) 03042 return(-1); 03043 03044 if (catal->type == XML_XML_CATALOG_TYPE) { 03045 if (catal->xml == NULL) 03046 return(1); 03047 if ((catal->xml->type != XML_CATA_CATALOG) && 03048 (catal->xml->type != XML_CATA_BROKEN_CATALOG)) 03049 return(-1); 03050 if (catal->xml->children == NULL) 03051 return(1); 03052 return(0); 03053 } else { 03054 int res; 03055 03056 if (catal->sgml == NULL) 03057 return(1); 03058 res = xmlHashSize(catal->sgml); 03059 if (res == 0) 03060 return(1); 03061 if (res < 0) 03062 return(-1); 03063 } 03064 return(0); 03065 } 03066 03067 /************************************************************************ 03068 * * 03069 * Public interfaces manipulating the global shared default catalog * 03070 * * 03071 ************************************************************************/ 03072 03081 static void 03082 xmlInitializeCatalogData(void) { 03083 if (xmlCatalogInitialized != 0) 03084 return; 03085 03086 if (getenv("XML_DEBUG_CATALOG")) 03087 xmlDebugCatalogs = 1; 03088 xmlCatalogMutex = xmlNewRMutex(); 03089 03090 xmlCatalogInitialized = 1; 03091 } 03099 void 03100 xmlInitializeCatalog(void) { 03101 if (xmlCatalogInitialized != 0) 03102 return; 03103 03104 xmlInitializeCatalogData(); 03105 xmlRMutexLock(xmlCatalogMutex); 03106 03107 if (getenv("XML_DEBUG_CATALOG")) 03108 xmlDebugCatalogs = 1; 03109 03110 if (xmlDefaultCatalog == NULL) { 03111 const char *catalogs; 03112 char *path; 03113 const char *cur, *paths; 03114 xmlCatalogPtr catal; 03115 xmlCatalogEntryPtr *nextent; 03116 03117 catalogs = (const char *) getenv("XML_CATALOG_FILES"); 03118 if (catalogs == NULL) 03119 #if defined(_WIN32) && defined(_MSC_VER) 03120 { 03121 void* hmodule; 03122 hmodule = GetModuleHandleA("libxml2.dll"); 03123 if (hmodule == NULL) 03124 hmodule = GetModuleHandleA(NULL); 03125 if (hmodule != NULL) { 03126 char buf[256]; 03127 unsigned long len = GetModuleFileNameA(hmodule, buf, 255); 03128 if (len != 0) { 03129 char* p = &(buf[len]); 03130 while (*p != '\\' && p > buf) 03131 p--; 03132 if (p != buf) { 03133 xmlChar* uri; 03134 strncpy(p, "\\..\\etc\\catalog", 255 - (p - buf)); 03135 uri = xmlCanonicPath(buf); 03136 if (uri != NULL) { 03137 strncpy(XML_XML_DEFAULT_CATALOG, uri, 255); 03138 xmlFree(uri); 03139 } 03140 } 03141 } 03142 } 03143 catalogs = XML_XML_DEFAULT_CATALOG; 03144 } 03145 #else 03146 catalogs = XML_XML_DEFAULT_CATALOG; 03147 #endif 03148 03149 catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, 03150 xmlCatalogDefaultPrefer); 03151 if (catal != NULL) { 03152 /* the XML_CATALOG_FILES envvar is allowed to contain a 03153 space-separated list of entries. */ 03154 cur = catalogs; 03155 nextent = &catal->xml; 03156 while (*cur != '\0') { 03157 while (xmlIsBlank_ch(*cur)) 03158 cur++; 03159 if (*cur != 0) { 03160 paths = cur; 03161 while ((*cur != 0) && (!xmlIsBlank_ch(*cur))) 03162 cur++; 03163 path = (char *) xmlStrndup((const xmlChar *)paths, cur - paths); 03164 if (path != NULL) { 03165 *nextent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, 03166 NULL, BAD_CAST path, xmlCatalogDefaultPrefer, NULL); 03167 if (*nextent != NULL) 03168 nextent = &((*nextent)->next); 03169 xmlFree(path); 03170 } 03171 } 03172 } 03173 xmlDefaultCatalog = catal; 03174 } 03175 } 03176 03177 xmlRMutexUnlock(xmlCatalogMutex); 03178 } 03179 03180 03192 int 03193 xmlLoadCatalog(const char *filename) 03194 { 03195 int ret; 03196 xmlCatalogPtr catal; 03197 03198 if (!xmlCatalogInitialized) 03199 xmlInitializeCatalogData(); 03200 03201 xmlRMutexLock(xmlCatalogMutex); 03202 03203 if (xmlDefaultCatalog == NULL) { 03204 catal = xmlLoadACatalog(filename); 03205 if (catal == NULL) { 03206 xmlRMutexUnlock(xmlCatalogMutex); 03207 return(-1); 03208 } 03209 03210 xmlDefaultCatalog = catal; 03211 xmlRMutexUnlock(xmlCatalogMutex); 03212 return(0); 03213 } 03214 03215 ret = xmlExpandCatalog(xmlDefaultCatalog, filename); 03216 xmlRMutexUnlock(xmlCatalogMutex); 03217 return(ret); 03218 } 03219 03229 void 03230 xmlLoadCatalogs(const char *pathss) { 03231 const char *cur; 03232 const char *paths; 03233 xmlChar *path; 03234 #ifdef _WIN32 03235 int i, iLen; 03236 #endif 03237 03238 if (pathss == NULL) 03239 return; 03240 03241 cur = pathss; 03242 while (*cur != 0) { 03243 while (xmlIsBlank_ch(*cur)) cur++; 03244 if (*cur != 0) { 03245 paths = cur; 03246 while ((*cur != 0) && (*cur != PATH_SEAPARATOR) && (!xmlIsBlank_ch(*cur))) 03247 cur++; 03248 path = xmlStrndup((const xmlChar *)paths, cur - paths); 03249 #ifdef _WIN32 03250 iLen = strlen(path); 03251 for(i = 0; i < iLen; i++) { 03252 if(path[i] == '\\') { 03253 path[i] = '/'; 03254 } 03255 } 03256 #endif 03257 if (path != NULL) { 03258 xmlLoadCatalog((const char *) path); 03259 xmlFree(path); 03260 } 03261 } 03262 while (*cur == PATH_SEAPARATOR) 03263 cur++; 03264 } 03265 } 03266 03272 void 03273 xmlCatalogCleanup(void) { 03274 if (xmlCatalogInitialized == 0) 03275 return; 03276 03277 xmlRMutexLock(xmlCatalogMutex); 03278 if (xmlDebugCatalogs) 03279 xmlGenericError(xmlGenericErrorContext, 03280 "Catalogs cleanup\n"); 03281 if (xmlCatalogXMLFiles != NULL) 03282 xmlHashFree(xmlCatalogXMLFiles, 03283 (xmlHashDeallocator)xmlFreeCatalogHashEntryList); 03284 xmlCatalogXMLFiles = NULL; 03285 if (xmlDefaultCatalog != NULL) 03286 xmlFreeCatalog(xmlDefaultCatalog); 03287 xmlDefaultCatalog = NULL; 03288 xmlDebugCatalogs = 0; 03289 xmlCatalogInitialized = 0; 03290 xmlRMutexUnlock(xmlCatalogMutex); 03291 xmlFreeRMutex(xmlCatalogMutex); 03292 } 03293 03303 xmlChar * 03304 xmlCatalogResolveSystem(const xmlChar *sysID) { 03305 xmlChar *ret; 03306 03307 if (!xmlCatalogInitialized) 03308 xmlInitializeCatalog(); 03309 03310 ret = xmlACatalogResolveSystem(xmlDefaultCatalog, sysID); 03311 return(ret); 03312 } 03313 03323 xmlChar * 03324 xmlCatalogResolvePublic(const xmlChar *pubID) { 03325 xmlChar *ret; 03326 03327 if (!xmlCatalogInitialized) 03328 xmlInitializeCatalog(); 03329 03330 ret = xmlACatalogResolvePublic(xmlDefaultCatalog, pubID); 03331 return(ret); 03332 } 03333 03344 xmlChar * 03345 xmlCatalogResolve(const xmlChar *pubID, const xmlChar *sysID) { 03346 xmlChar *ret; 03347 03348 if (!xmlCatalogInitialized) 03349 xmlInitializeCatalog(); 03350 03351 ret = xmlACatalogResolve(xmlDefaultCatalog, pubID, sysID); 03352 return(ret); 03353 } 03354 03364 xmlChar * 03365 xmlCatalogResolveURI(const xmlChar *URI) { 03366 xmlChar *ret; 03367 03368 if (!xmlCatalogInitialized) 03369 xmlInitializeCatalog(); 03370 03371 ret = xmlACatalogResolveURI(xmlDefaultCatalog, URI); 03372 return(ret); 03373 } 03374 03375 #ifdef LIBXML_OUTPUT_ENABLED 03376 03382 void 03383 xmlCatalogDump(FILE *out) { 03384 if (out == NULL) 03385 return; 03386 03387 if (!xmlCatalogInitialized) 03388 xmlInitializeCatalog(); 03389 03390 xmlACatalogDump(xmlDefaultCatalog, out); 03391 } 03392 #endif /* LIBXML_OUTPUT_ENABLED */ 03393 03407 int 03408 xmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace) { 03409 int res = -1; 03410 03411 if (!xmlCatalogInitialized) 03412 xmlInitializeCatalogData(); 03413 03414 xmlRMutexLock(xmlCatalogMutex); 03415 /* 03416 * Specific case where one want to override the default catalog 03417 * put in place by xmlInitializeCatalog(); 03418 */ 03419 if ((xmlDefaultCatalog == NULL) && 03420 (xmlStrEqual(type, BAD_CAST "catalog"))) { 03421 xmlDefaultCatalog = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, 03422 xmlCatalogDefaultPrefer); 03423 xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, 03424 orig, NULL, xmlCatalogDefaultPrefer, NULL); 03425 03426 xmlRMutexUnlock(xmlCatalogMutex); 03427 return(0); 03428 } 03429 03430 res = xmlACatalogAdd(xmlDefaultCatalog, type, orig, replace); 03431 xmlRMutexUnlock(xmlCatalogMutex); 03432 return(res); 03433 } 03434 03443 int 03444 xmlCatalogRemove(const xmlChar *value) { 03445 int res; 03446 03447 if (!xmlCatalogInitialized) 03448 xmlInitializeCatalog(); 03449 03450 xmlRMutexLock(xmlCatalogMutex); 03451 res = xmlACatalogRemove(xmlDefaultCatalog, value); 03452 xmlRMutexUnlock(xmlCatalogMutex); 03453 return(res); 03454 } 03455 03463 int 03464 xmlCatalogConvert(void) { 03465 int res = -1; 03466 03467 if (!xmlCatalogInitialized) 03468 xmlInitializeCatalog(); 03469 03470 xmlRMutexLock(xmlCatalogMutex); 03471 res = xmlConvertSGMLCatalog(xmlDefaultCatalog); 03472 xmlRMutexUnlock(xmlCatalogMutex); 03473 return(res); 03474 } 03475 03476 /************************************************************************ 03477 * * 03478 * Public interface manipulating the common preferences * 03479 * * 03480 ************************************************************************/ 03481 03490 xmlCatalogAllow 03491 xmlCatalogGetDefaults(void) { 03492 return(xmlCatalogDefaultAllow); 03493 } 03494 03502 void 03503 xmlCatalogSetDefaults(xmlCatalogAllow allow) { 03504 if (xmlDebugCatalogs) { 03505 switch (allow) { 03506 case XML_CATA_ALLOW_NONE: 03507 xmlGenericError(xmlGenericErrorContext, 03508 "Disabling catalog usage\n"); 03509 break; 03510 case XML_CATA_ALLOW_GLOBAL: 03511 xmlGenericError(xmlGenericErrorContext, 03512 "Allowing only global catalogs\n"); 03513 break; 03514 case XML_CATA_ALLOW_DOCUMENT: 03515 xmlGenericError(xmlGenericErrorContext, 03516 "Allowing only catalogs from the document\n"); 03517 break; 03518 case XML_CATA_ALLOW_ALL: 03519 xmlGenericError(xmlGenericErrorContext, 03520 "Allowing all catalogs\n"); 03521 break; 03522 } 03523 } 03524 xmlCatalogDefaultAllow = allow; 03525 } 03526 03537 xmlCatalogPrefer 03538 xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer) { 03539 xmlCatalogPrefer ret = xmlCatalogDefaultPrefer; 03540 03541 if (prefer == XML_CATA_PREFER_NONE) 03542 return(ret); 03543 03544 if (xmlDebugCatalogs) { 03545 switch (prefer) { 03546 case XML_CATA_PREFER_PUBLIC: 03547 xmlGenericError(xmlGenericErrorContext, 03548 "Setting catalog preference to PUBLIC\n"); 03549 break; 03550 case XML_CATA_PREFER_SYSTEM: 03551 xmlGenericError(xmlGenericErrorContext, 03552 "Setting catalog preference to SYSTEM\n"); 03553 break; 03554 case XML_CATA_PREFER_NONE: 03555 break; 03556 } 03557 } 03558 xmlCatalogDefaultPrefer = prefer; 03559 return(ret); 03560 } 03561 03571 int 03572 xmlCatalogSetDebug(int level) { 03573 int ret = xmlDebugCatalogs; 03574 03575 if (level <= 0) 03576 xmlDebugCatalogs = 0; 03577 else 03578 xmlDebugCatalogs = level; 03579 return(ret); 03580 } 03581 03582 /************************************************************************ 03583 * * 03584 * Minimal interfaces used for per-document catalogs by the parser * 03585 * * 03586 ************************************************************************/ 03587 03594 void 03595 xmlCatalogFreeLocal(void *catalogs) { 03596 xmlCatalogEntryPtr catal; 03597 03598 if (!xmlCatalogInitialized) 03599 xmlInitializeCatalog(); 03600 03601 catal = (xmlCatalogEntryPtr) catalogs; 03602 if (catal != NULL) 03603 xmlFreeCatalogEntryList(catal); 03604 } 03605 03606 03616 void * 03617 xmlCatalogAddLocal(void *catalogs, const xmlChar *URL) { 03618 xmlCatalogEntryPtr catal, add; 03619 03620 if (!xmlCatalogInitialized) 03621 xmlInitializeCatalog(); 03622 03623 if (URL == NULL) 03624 return(catalogs); 03625 03626 if (xmlDebugCatalogs) 03627 xmlGenericError(xmlGenericErrorContext, 03628 "Adding document catalog %s\n", URL); 03629 03630 add = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, URL, NULL, 03631 xmlCatalogDefaultPrefer, NULL); 03632 if (add == NULL) 03633 return(catalogs); 03634 03635 catal = (xmlCatalogEntryPtr) catalogs; 03636 if (catal == NULL) 03637 return((void *) add); 03638 03639 while (catal->next != NULL) 03640 catal = catal->next; 03641 catal->next = add; 03642 return(catalogs); 03643 } 03644 03657 xmlChar * 03658 xmlCatalogLocalResolve(void *catalogs, const xmlChar *pubID, 03659 const xmlChar *sysID) { 03660 xmlCatalogEntryPtr catal; 03661 xmlChar *ret; 03662 03663 if (!xmlCatalogInitialized) 03664 xmlInitializeCatalog(); 03665 03666 if ((pubID == NULL) && (sysID == NULL)) 03667 return(NULL); 03668 03669 if (xmlDebugCatalogs) { 03670 if ((pubID != NULL) && (sysID != NULL)) { 03671 xmlGenericError(xmlGenericErrorContext, 03672 "Local Resolve: pubID %s sysID %s\n", pubID, sysID); 03673 } else if (pubID != NULL) { 03674 xmlGenericError(xmlGenericErrorContext, 03675 "Local Resolve: pubID %s\n", pubID); 03676 } else { 03677 xmlGenericError(xmlGenericErrorContext, 03678 "Local Resolve: sysID %s\n", sysID); 03679 } 03680 } 03681 03682 catal = (xmlCatalogEntryPtr) catalogs; 03683 if (catal == NULL) 03684 return(NULL); 03685 ret = xmlCatalogListXMLResolve(catal, pubID, sysID); 03686 if ((ret != NULL) && (ret != XML_CATAL_BREAK)) 03687 return(ret); 03688 return(NULL); 03689 } 03690 03702 xmlChar * 03703 xmlCatalogLocalResolveURI(void *catalogs, const xmlChar *URI) { 03704 xmlCatalogEntryPtr catal; 03705 xmlChar *ret; 03706 03707 if (!xmlCatalogInitialized) 03708 xmlInitializeCatalog(); 03709 03710 if (URI == NULL) 03711 return(NULL); 03712 03713 if (xmlDebugCatalogs) 03714 xmlGenericError(xmlGenericErrorContext, 03715 "Resolve URI %s\n", URI); 03716 03717 catal = (xmlCatalogEntryPtr) catalogs; 03718 if (catal == NULL) 03719 return(NULL); 03720 ret = xmlCatalogListXMLResolveURI(catal, URI); 03721 if ((ret != NULL) && (ret != XML_CATAL_BREAK)) 03722 return(ret); 03723 return(NULL); 03724 } 03725 03726 /************************************************************************ 03727 * * 03728 * Deprecated interfaces * 03729 * * 03730 ************************************************************************/ 03740 const xmlChar * 03741 xmlCatalogGetSystem(const xmlChar *sysID) { 03742 xmlChar *ret; 03743 static xmlChar result[1000]; 03744 static int msg = 0; 03745 03746 if (!xmlCatalogInitialized) 03747 xmlInitializeCatalog(); 03748 03749 if (msg == 0) { 03750 xmlGenericError(xmlGenericErrorContext, 03751 "Use of deprecated xmlCatalogGetSystem() call\n"); 03752 msg++; 03753 } 03754 03755 if (sysID == NULL) 03756 return(NULL); 03757 03758 /* 03759 * Check first the XML catalogs 03760 */ 03761 if (xmlDefaultCatalog != NULL) { 03762 ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, NULL, sysID); 03763 if ((ret != NULL) && (ret != XML_CATAL_BREAK)) { 03764 snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret); 03765 result[sizeof(result) - 1] = 0; 03766 return(result); 03767 } 03768 } 03769 03770 if (xmlDefaultCatalog != NULL) 03771 return(xmlCatalogGetSGMLSystem(xmlDefaultCatalog->sgml, sysID)); 03772 return(NULL); 03773 } 03774 03784 const xmlChar * 03785 xmlCatalogGetPublic(const xmlChar *pubID) { 03786 xmlChar *ret; 03787 static xmlChar result[1000]; 03788 static int msg = 0; 03789 03790 if (!xmlCatalogInitialized) 03791 xmlInitializeCatalog(); 03792 03793 if (msg == 0) { 03794 xmlGenericError(xmlGenericErrorContext, 03795 "Use of deprecated xmlCatalogGetPublic() call\n"); 03796 msg++; 03797 } 03798 03799 if (pubID == NULL) 03800 return(NULL); 03801 03802 /* 03803 * Check first the XML catalogs 03804 */ 03805 if (xmlDefaultCatalog != NULL) { 03806 ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, pubID, NULL); 03807 if ((ret != NULL) && (ret != XML_CATAL_BREAK)) { 03808 snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret); 03809 result[sizeof(result) - 1] = 0; 03810 return(result); 03811 } 03812 } 03813 03814 if (xmlDefaultCatalog != NULL) 03815 return(xmlCatalogGetSGMLPublic(xmlDefaultCatalog->sgml, pubID)); 03816 return(NULL); 03817 } 03818 03819 #define bottom_catalog 03820 #include "elfgcchack.h" 03821 #endif /* LIBXML_CATALOG_ENABLED */ Generated on Sun May 27 2012 04:27:07 for ReactOS by
1.7.6.1
|