📄 catalog.c.svn-base
字号:
* a Catalog entry from it. * * Returns the new Catalog entry node or NULL in case of error. */static xmlCatalogEntryPtrxmlParseXMLCatalogOneNode(xmlNodePtr cur, xmlCatalogEntryType type, const xmlChar *name, const xmlChar *attrName, const xmlChar *uriAttrName, xmlCatalogPrefer prefer) { int ok = 1; xmlChar *uriValue; xmlChar *nameValue = NULL; xmlChar *base = NULL; xmlChar *URL = NULL; xmlCatalogEntryPtr ret = NULL; if (attrName != NULL) { nameValue = xmlGetProp(cur, attrName); if (nameValue == NULL) { xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR, "%s entry lacks '%s'\n", name, attrName, NULL); ok = 0; } } uriValue = xmlGetProp(cur, uriAttrName); if (uriValue == NULL) { xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR, "%s entry lacks '%s'\n", name, uriAttrName, NULL); ok = 0; } if (!ok) { if (nameValue != NULL) xmlFree(nameValue); if (uriValue != NULL) xmlFree(uriValue); return(NULL); } base = xmlNodeGetBase(cur->doc, cur); URL = xmlBuildURI(uriValue, base); if (URL != NULL) { if (xmlDebugCatalogs > 1) { if (nameValue != NULL) xmlGenericError(xmlGenericErrorContext, "Found %s: '%s' '%s'\n", name, nameValue, URL); else xmlGenericError(xmlGenericErrorContext, "Found %s: '%s'\n", name, URL); } ret = xmlNewCatalogEntry(type, nameValue, uriValue, URL, prefer); } else { xmlCatalogErr(ret, cur, XML_CATALOG_ENTRY_BROKEN, "%s entry '%s' broken ?: %s\n", name, uriAttrName, uriValue); } if (nameValue != NULL) xmlFree(nameValue); if (uriValue != NULL) xmlFree(uriValue); if (base != NULL) xmlFree(base); if (URL != NULL) xmlFree(URL); return(ret);}/** * xmlParseXMLCatalogNode: * @cur: the XML node * @prefer: the PUBLIC vs. SYSTEM current preference value * @parent: the parent Catalog entry * * Examines an XML tree node of a catalog and build * a Catalog entry from it adding it to its parent. The examination can * be recursive. */static voidxmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer, xmlCatalogEntryPtr parent){ xmlChar *uri = NULL; xmlChar *URL = NULL; xmlChar *base = NULL; xmlCatalogEntryPtr entry = NULL; if (cur == NULL) return; if (xmlStrEqual(cur->name, BAD_CAST "group")) { xmlChar *prop; prop = xmlGetProp(cur, BAD_CAST "prefer"); if (prop != NULL) { if (xmlStrEqual(prop, BAD_CAST "system")) { prefer = XML_CATA_PREFER_SYSTEM; } else if (xmlStrEqual(prop, BAD_CAST "public")) { prefer = XML_CATA_PREFER_PUBLIC; } else { xmlCatalogErr(parent, cur, XML_CATALOG_PREFER_VALUE, "Invalid value for prefer: '%s'\n", prop, NULL, NULL); } xmlFree(prop); } /* * Recurse to propagate prefer to the subtree * (xml:base handling is automated) */ xmlParseXMLCatalogNodeList(cur->children, prefer, parent); } else if (xmlStrEqual(cur->name, BAD_CAST "public")) { entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_PUBLIC, BAD_CAST "public", BAD_CAST "publicId", BAD_CAST "uri", prefer); } else if (xmlStrEqual(cur->name, BAD_CAST "system")) { entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_SYSTEM, BAD_CAST "system", BAD_CAST "systemId", BAD_CAST "uri", prefer); } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteSystem")) { entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_SYSTEM, BAD_CAST "rewriteSystem", BAD_CAST "systemIdStartString", BAD_CAST "rewritePrefix", prefer); } else if (xmlStrEqual(cur->name, BAD_CAST "delegatePublic")) { entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_PUBLIC, BAD_CAST "delegatePublic", BAD_CAST "publicIdStartString", BAD_CAST "catalog", prefer); } else if (xmlStrEqual(cur->name, BAD_CAST "delegateSystem")) { entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_SYSTEM, BAD_CAST "delegateSystem", BAD_CAST "systemIdStartString", BAD_CAST "catalog", prefer); } else if (xmlStrEqual(cur->name, BAD_CAST "uri")) { entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_URI, BAD_CAST "uri", BAD_CAST "name", BAD_CAST "uri", prefer); } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteURI")) { entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_URI, BAD_CAST "rewriteURI", BAD_CAST "uriStartString", BAD_CAST "rewritePrefix", prefer); } else if (xmlStrEqual(cur->name, BAD_CAST "delegateURI")) { entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_URI, BAD_CAST "delegateURI", BAD_CAST "uriStartString", BAD_CAST "catalog", prefer); } else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) { entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG, BAD_CAST "nextCatalog", NULL, BAD_CAST "catalog", prefer); } if ((entry != NULL) && (parent != NULL)) { entry->parent = parent; if (parent->children == NULL) parent->children = entry; else { xmlCatalogEntryPtr prev; prev = parent->children; while (prev->next != NULL) prev = prev->next; prev->next = entry; } } if (base != NULL) xmlFree(base); if (uri != NULL) xmlFree(uri); if (URL != NULL) xmlFree(URL);}/** * xmlParseXMLCatalogNodeList: * @cur: the XML node list of siblings * @prefer: the PUBLIC vs. SYSTEM current preference value * @parent: the parent Catalog entry * * Examines a list of XML sibling nodes of a catalog and build * a list of Catalog entry from it adding it to the parent. * The examination will recurse to examine node subtrees. */static voidxmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer, xmlCatalogEntryPtr parent) { while (cur != NULL) { if ((cur->ns != NULL) && (cur->ns->href != NULL) && (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) { xmlParseXMLCatalogNode(cur, prefer, parent); } cur = cur->next; } /* TODO: sort the list according to REWRITE lengths and prefer value */}/** * xmlParseXMLCatalogFile: * @prefer: the PUBLIC vs. SYSTEM current preference value * @filename: the filename for the catalog * * Parses the catalog file to extract the XML tree and then analyze the * tree to build a list of Catalog entries corresponding to this catalog * * Returns the resulting Catalog entries list */static xmlCatalogEntryPtrxmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename) { xmlDocPtr doc; xmlNodePtr cur; xmlChar *prop; xmlCatalogEntryPtr parent = NULL; if (filename == NULL) return(NULL); doc = xmlParseCatalogFile((const char *) filename); if (doc == NULL) { if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Failed to parse catalog %s\n", filename); return(NULL); } if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "%d Parsing catalog %s\n", xmlGetThreadId(), filename); cur = xmlDocGetRootElement(doc); if ((cur != NULL) && (xmlStrEqual(cur->name, BAD_CAST "catalog")) && (cur->ns != NULL) && (cur->ns->href != NULL) && (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) { parent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, (const xmlChar *)filename, NULL, prefer); if (parent == NULL) { xmlFreeDoc(doc); return(NULL); } prop = xmlGetProp(cur, BAD_CAST "prefer"); if (prop != NULL) { if (xmlStrEqual(prop, BAD_CAST "system")) { prefer = XML_CATA_PREFER_SYSTEM; } else if (xmlStrEqual(prop, BAD_CAST "public")) { prefer = XML_CATA_PREFER_PUBLIC; } else { xmlCatalogErr(NULL, cur, XML_CATALOG_PREFER_VALUE, "Invalid value for prefer: '%s'\n", prop, NULL, NULL); } xmlFree(prop); } cur = cur->children; xmlParseXMLCatalogNodeList(cur, prefer, parent); } else { xmlCatalogErr(NULL, (xmlNodePtr) doc, XML_CATALOG_NOT_CATALOG, "File %s is not an XML Catalog\n", filename, NULL, NULL); xmlFreeDoc(doc); return(NULL); } xmlFreeDoc(doc); return(parent);}/** * xmlFetchXMLCatalogFile: * @catal: an existing but incomplete catalog entry * * Fetch and parse the subcatalog referenced by an entry * * Returns 0 in case of success, -1 otherwise */static intxmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) { xmlCatalogEntryPtr doc; if (catal == NULL) return(-1); if (catal->URL == NULL) return(-1); if (catal->children != NULL) return(-1); /* * lock the whole catalog for modification */ xmlRMutexLock(xmlCatalogMutex); if (catal->children != NULL) { /* Okay someone else did it in the meantime */ xmlRMutexUnlock(xmlCatalogMutex); return(0); } if (xmlCatalogXMLFiles != NULL) { doc = (xmlCatalogEntryPtr) xmlHashLookup(xmlCatalogXMLFiles, catal->URL); if (doc != NULL) { if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Found %s in file hash\n", catal->URL); if (catal->type == XML_CATA_CATALOG) catal->children = doc->children; else catal->children = doc; catal->dealloc = 0; xmlRMutexUnlock(xmlCatalogMutex); return(0); } if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "%s not found in file hash\n", catal->URL); } /* * Fetch and parse. Note that xmlParseXMLCatalogFile does not * use the existing catalog, there is no recursion allowed at * that level. */ doc = xmlParseXMLCatalogFile(catal->prefer, catal->URL); if (doc == NULL) { catal->type = XML_CATA_BROKEN_CATALOG; xmlRMutexUnlock(xmlCatalogMutex); return(-1); } if (catal->type == XML_CATA_CATALOG) catal->children = doc->children; else catal->children = doc; doc->dealloc = 1; if (xmlCatalogXMLFiles == NULL) xmlCatalogXMLFiles = xmlHashCreate(10); if (xmlCatalogXMLFiles != NULL) { if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "%s added to file hash\n", catal->URL); xmlHashAddEntry(xmlCatalogXMLFiles, catal->URL, doc); } xmlRMutexUnlock(xmlCatalogMutex); return(0);}/************************************************************************ * * * XML Catalog handling * * * ************************************************************************//** * xmlAddXMLCatalog: * @catal: top of an XML catalog * @type: the type of record to add to the catalog * @orig: the system, public or prefix to match (or NULL) * @replace: the replacement value for the match * * Add an entry in the XML catalog, it may overwrite existing but * different entries. * * Returns 0 if successful, -1 otherwise */static intxmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type, const xmlChar *orig, const xmlChar *replace) { xmlCatalogEntryPtr cur; xmlCatalogEntryType typ; int doregister = 0; if ((catal == NULL) || ((catal->type != XML_CATA_CATALOG) && (catal->type != XML_CATA_BROKEN_CATALOG))) return(-1); if (catal->children == NULL) { xmlFetchXMLCatalogFile(catal); } if (catal->children == NULL) doregister = 1; typ = xmlGetXMLCatalogEntryType(type); if (typ == XML_CATA_NONE) { if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Failed to add unknown element %s to catalog\n", type); return(-1); } cur = catal->children; /* * Might be a simple "update in place" */ if (cur != NULL) { while (cur != NULL) { if ((orig != NULL) && (cur->type == typ) && (xmlStrEqual(orig, cur->name))) { if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Updating element %s to catalog\n", type); if (cur->value != NULL) xmlFree(cur->value); if (cur->URL != NULL) xmlFree(cur->URL); cur->value = xmlStrdup(replace); cur->URL = xmlStrdup(replace); return(0); } if (cur->next == NULL) break; cur = cur->next; } } if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Adding element %s to catalog\n", type); if (cur == NULL) catal->children = xmlNewCatalogEntry(typ, orig, replace, NULL, catal->prefer); else cur->next = xmlNewCatalogEntry(typ, orig, replace, NULL, catal->prefer); if (doregister) { cur = xmlHashLookup(xmlCatalogXMLFiles, catal->URL); if (cur != NULL) cur->children = catal->children; } return(0);}/** * xmlDelXMLCatalog: * @catal: top of an XML catalog * @value: the value to remove from the catalog * * Remove entries in the XML catalog where the value or the URI * is equal to @value * * Returns the number of entries removed if successful, -1 otherwise */static intxmlDelXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *value) { xmlCatalogEntryPtr cur; int ret = 0; if ((catal == NULL) || ((catal->type != XML_CATA_CATALOG) && (catal->type != XML_CATA_BROKEN_CATALOG))) return(-1); if (value == NULL) return(-1); if (catal->children == NULL) { xmlFetchXMLCatalogFile(catal); } /* * Scan the children */ cur = catal->children; while (cur != NULL) { if (((cur->name != NULL) && (xmlStrEqual(value, cur->name))) || (xmlStrEqual(value, cur->value))) { if (xmlDebugCatalogs) { if (cur->name != NULL) xmlGenericError(xmlGenericErrorContext, "Removing element %s from catalog\n", cur->name); else xmlGenericError(xmlGenericErrorContext, "Removing element %s from catalog\n", cur->value); } cur->type = XML_CATA_REMOVED; } cur = cur->next; } return(ret);}/** * xmlCatalogXMLResolve: * @catal: a catalog list * @pubID: the public ID string * @sysID: the system ID string * * Do a complete resolution lookup of an External Identifier for a * list of catalog entries. * * Implements (or tries to) 7.1. External Identifier Resolution * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html * * Returns the URI of the resource or NULL if not found */static xmlChar *xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, const xmlChar *sysID) { xmlChar *ret = NULL; xmlCatalogEntryPtr cur; int haveDelegate = 0; int haveNext = 0; /* * protection against loops */ if (catal->depth > MAX_CATAL_DEPTH) { xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION, "Detected recursion in catalog %s\n", catal->name, NULL, NULL); return(NULL); } catal->depth++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -