Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816/** * catalog.c: set of generic Catalog related routines * * Reference: SGML Open Technical Resolution TR9401:1997. * http://www.jclark.com/sp/catalog.htm * * XML Catalogs Working Draft 06 August 2001 * http://www.oasis-open.org/committees/entity/spec-2001-08-06.html * * See Copyright for the status of this software. * * Daniel.Veillard@imag.fr */
#define IN_LIBXML#include "libxml.h"
#ifdef LIBXML_CATALOG_ENABLED#include <stdlib.h>#include <string.h>#ifdef HAVE_SYS_STAT_H#include <sys/stat.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#elif defined (_WIN32)#include <io.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h>#endif#include <libxml/xmlmemory.h>#include <libxml/hash.h>#include <libxml/uri.h>#include <libxml/parserInternals.h>#include <libxml/catalog.h>#include <libxml/xmlerror.h>#include <libxml/threads.h>
#include "private/buf.h"#include "private/error.h"
#define MAX_DELEGATE 50#define MAX_CATAL_DEPTH 50
#ifdef _WIN32# define PATH_SEPARATOR ';'#else# define PATH_SEPARATOR ':'#endif
/** * TODO: * * macro to flag unimplemented blocks * XML_CATALOG_PREFER user env to select between system/public preferred * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk> *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with *> values "system" and "public". I have made the default be "system" to *> match yours. */#define TODO \ xmlGenericError(xmlGenericErrorContext, \ "Unimplemented block at %s:%d\n", \ __FILE__, __LINE__);
#define XML_URN_PUBID "urn:publicid:"#define XML_CATAL_BREAK ((xmlChar *) -1)#ifndef XML_XML_DEFAULT_CATALOG#define XML_XML_DEFAULT_CATALOG "file://" SYSCONFDIR "/xml/catalog"#endif#ifndef XML_SGML_DEFAULT_CATALOG#define XML_SGML_DEFAULT_CATALOG "file://" SYSCONFDIR "/sgml/catalog"#endif
#if defined(_WIN32) && defined(_MSC_VER)#undef XML_XML_DEFAULT_CATALOGstatic char XML_XML_DEFAULT_CATALOG[256] = "file://" SYSCONFDIR "/xml/catalog";#if !defined(_WINDOWS_)void* __stdcall GetModuleHandleA(const char*);unsigned long __stdcall GetModuleFileNameA(void*, char*, unsigned long);#endif#endif
static xmlChar *xmlCatalogNormalizePublic(const xmlChar *pubID);static int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename);
/************************************************************************ * * * Types, all private * * * ************************************************************************/
typedef enum { XML_CATA_REMOVED = -1, XML_CATA_NONE = 0, XML_CATA_CATALOG, XML_CATA_BROKEN_CATALOG, XML_CATA_NEXT_CATALOG, XML_CATA_GROUP, XML_CATA_PUBLIC, XML_CATA_SYSTEM, XML_CATA_REWRITE_SYSTEM, XML_CATA_DELEGATE_PUBLIC, XML_CATA_DELEGATE_SYSTEM, XML_CATA_URI, XML_CATA_REWRITE_URI, XML_CATA_DELEGATE_URI, SGML_CATA_SYSTEM, SGML_CATA_PUBLIC, SGML_CATA_ENTITY, SGML_CATA_PENTITY, SGML_CATA_DOCTYPE, SGML_CATA_LINKTYPE, SGML_CATA_NOTATION, SGML_CATA_DELEGATE, SGML_CATA_BASE, SGML_CATA_CATALOG, SGML_CATA_DOCUMENT, SGML_CATA_SGMLDECL} xmlCatalogEntryType;
typedef struct _xmlCatalogEntry xmlCatalogEntry;typedef xmlCatalogEntry *xmlCatalogEntryPtr;struct _xmlCatalogEntry { struct _xmlCatalogEntry *next; struct _xmlCatalogEntry *parent; struct _xmlCatalogEntry *children; xmlCatalogEntryType type; xmlChar *name; xmlChar *value; xmlChar *URL; /* The expanded URL using the base */ xmlCatalogPrefer prefer; int dealloc; int depth; struct _xmlCatalogEntry *group;};
typedef enum { XML_XML_CATALOG_TYPE = 1, XML_SGML_CATALOG_TYPE} xmlCatalogType;
#define XML_MAX_SGML_CATA_DEPTH 10struct _xmlCatalog { xmlCatalogType type; /* either XML or SGML */
/* * SGML Catalogs are stored as a simple hash table of catalog entries * Catalog stack to check against overflows when building the * SGML catalog */ char *catalTab[XML_MAX_SGML_CATA_DEPTH]; /* stack of catals */ int catalNr; /* Number of current catal streams */ int catalMax; /* Max number of catal streams */ xmlHashTablePtr sgml;
/* * XML Catalogs are stored as a tree of Catalog entries */ xmlCatalogPrefer prefer; xmlCatalogEntryPtr xml;};
/************************************************************************ * * * Global variables * * * ************************************************************************/
/* * Those are preferences */static int xmlDebugCatalogs = 0; /* used for debugging */static xmlCatalogAllow xmlCatalogDefaultAllow = XML_CATA_ALLOW_ALL;static xmlCatalogPrefer xmlCatalogDefaultPrefer = XML_CATA_PREFER_PUBLIC;
/* * Hash table containing all the trees of XML catalogs parsed by * the application. */static xmlHashTablePtr xmlCatalogXMLFiles = NULL;
/* * The default catalog in use by the application */static xmlCatalogPtr xmlDefaultCatalog = NULL;
/* * A mutex for modifying the shared global catalog(s) * xmlDefaultCatalog tree. * It also protects xmlCatalogXMLFiles * The core of this readers/writer scheme is in xmlFetchXMLCatalogFile() */static xmlRMutexPtr xmlCatalogMutex = NULL;
/* * Whether the catalog support was initialized. */static int xmlCatalogInitialized = 0;
/************************************************************************ * * * Catalog error handlers * * * ************************************************************************/
/** * xmlCatalogErrMemory: * @extra: extra information * * Handle an out of memory condition */static voidxmlCatalogErrMemory(const char *extra){ __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_CATALOG, XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, extra, NULL, NULL, 0, 0, "Memory allocation failed : %s\n", extra);}
/** * xmlCatalogErr: * @catal: the Catalog entry * @node: the context node * @msg: the error message * @extra: extra information * * Handle a catalog error */static void LIBXML_ATTR_FORMAT(4,0)xmlCatalogErr(xmlCatalogEntryPtr catal, xmlNodePtr node, int error, const char *msg, const xmlChar *str1, const xmlChar *str2, const xmlChar *str3){ __xmlRaiseError(NULL, NULL, NULL, catal, node, XML_FROM_CATALOG, error, XML_ERR_ERROR, NULL, 0, (const char *) str1, (const char *) str2, (const char *) str3, 0, 0, msg, str1, str2, str3);}
/************************************************************************ * * * Allocation and Freeing * * * ************************************************************************/
/** * xmlNewCatalogEntry: * @type: type of entry * @name: name of the entry * @value: value of the entry * @prefer: the PUBLIC vs. SYSTEM current preference value * @group: for members of a group, the group entry * * create a new Catalog entry, this type is shared both by XML and * SGML catalogs, but the acceptable types values differs. * * Returns the xmlCatalogEntryPtr or NULL in case of error */static xmlCatalogEntryPtrxmlNewCatalogEntry(xmlCatalogEntryType type, const xmlChar *name, const xmlChar *value, const xmlChar *URL, xmlCatalogPrefer prefer, xmlCatalogEntryPtr group) { xmlCatalogEntryPtr ret; xmlChar *normid = NULL;
ret = (xmlCatalogEntryPtr) xmlMalloc(sizeof(xmlCatalogEntry)); if (ret == NULL) { xmlCatalogErrMemory("allocating catalog entry"); return(NULL); } ret->next = NULL; ret->parent = NULL; ret->children = NULL; ret->type = type; if (type == XML_CATA_PUBLIC || type == XML_CATA_DELEGATE_PUBLIC) { normid = xmlCatalogNormalizePublic(name); if (normid != NULL) name = (*normid != 0 ? normid : NULL); } if (name != NULL) ret->name = xmlStrdup(name); else ret->name = NULL; if (normid != NULL) xmlFree(normid); if (value != NULL) ret->value = xmlStrdup(value); else ret->value = NULL; if (URL == NULL) URL = value; if (URL != NULL) ret->URL = xmlStrdup(URL); else ret->URL = NULL; ret->prefer = prefer; ret->dealloc = 0; ret->depth = 0; ret->group = group; return(ret);}
static voidxmlFreeCatalogEntryList(xmlCatalogEntryPtr ret);
/** * xmlFreeCatalogEntry: * @payload: a Catalog entry * * Free the memory allocated to a Catalog entry */static voidxmlFreeCatalogEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) { xmlCatalogEntryPtr ret = (xmlCatalogEntryPtr) payload; if (ret == NULL) return; /* * Entries stored in the file hash must be deallocated * only by the file hash cleaner ! */ if (ret->dealloc == 1) return;
if (xmlDebugCatalogs) { if (ret->name != NULL) xmlGenericError(xmlGenericErrorContext, "Free catalog entry %s\n", ret->name); else if (ret->value != NULL) xmlGenericError(xmlGenericErrorContext, "Free catalog entry %s\n", ret->value); else xmlGenericError(xmlGenericErrorContext, "Free catalog entry\n"); }
if (ret->name != NULL) xmlFree(ret->name); if (ret->value != NULL) xmlFree(ret->value); if (ret->URL != NULL) xmlFree(ret->URL); xmlFree(ret);}
/** * xmlFreeCatalogEntryList: * @ret: a Catalog entry list * * Free the memory allocated to a full chained list of Catalog entries */static voidxmlFreeCatalogEntryList(xmlCatalogEntryPtr ret) { xmlCatalogEntryPtr next;
while (ret != NULL) { next = ret->next; xmlFreeCatalogEntry(ret, NULL); ret = next; }}
/** * xmlFreeCatalogHashEntryList: * @payload: a Catalog entry list * * Free the memory allocated to list of Catalog entries from the * catalog file hash. */static voidxmlFreeCatalogHashEntryList(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) { xmlCatalogEntryPtr catal = (xmlCatalogEntryPtr) payload; xmlCatalogEntryPtr children, next;
if (catal == NULL) return;
children = catal->children; while (children != NULL) { next = children->next; children->dealloc = 0; children->children = NULL; xmlFreeCatalogEntry(children, NULL); children = next; } catal->dealloc = 0; xmlFreeCatalogEntry(catal, NULL);}
/** * xmlCreateNewCatalog: * @type: type of catalog * @prefer: the PUBLIC vs. SYSTEM current preference value * * create a new Catalog, this type is shared both by XML and * SGML catalogs, but the acceptable types values differs. * * Returns the xmlCatalogPtr or NULL in case of error */static xmlCatalogPtrxmlCreateNewCatalog(xmlCatalogType type, xmlCatalogPrefer prefer) { xmlCatalogPtr ret;
ret = (xmlCatalogPtr) xmlMalloc(sizeof(xmlCatalog)); if (ret == NULL) { xmlCatalogErrMemory("allocating catalog"); return(NULL); } memset(ret, 0, sizeof(xmlCatalog)); ret->type = type; ret->catalNr = 0; ret->catalMax = XML_MAX_SGML_CATA_DEPTH; ret->prefer = prefer; if (ret->type == XML_SGML_CATALOG_TYPE) ret->sgml = xmlHashCreate(10); return(ret);}
/** * xmlFreeCatalog: * @catal: a Catalog * * Free the memory allocated to a Catalog */voidxmlFreeCatalog(xmlCatalogPtr catal) { if (catal == NULL) return; if (catal->xml != NULL) xmlFreeCatalogEntryList(catal->xml); if (catal->sgml != NULL) xmlHashFree(catal->sgml, xmlFreeCatalogEntry); xmlFree(catal);}
/************************************************************************ * * * Serializing Catalogs * * * ************************************************************************/
#ifdef LIBXML_OUTPUT_ENABLED/** * xmlCatalogDumpEntry: * @entry: the catalog entry * @out: the file. * * Serialize an SGML Catalog entry */static voidxmlCatalogDumpEntry(void *payload, void *data, const xmlChar *name ATTRIBUTE_UNUSED) { xmlCatalogEntryPtr entry = (xmlCatalogEntryPtr) payload; FILE *out = (FILE *) data; if ((entry == NULL) || (out == NULL)) return; switch (entry->type) { case SGML_CATA_ENTITY: fprintf(out, "ENTITY "); break; case SGML_CATA_PENTITY: fprintf(out, "ENTITY %%"); break; case SGML_CATA_DOCTYPE: fprintf(out, "DOCTYPE "); break; case SGML_CATA_LINKTYPE: fprintf(out, "LINKTYPE "); break; case SGML_CATA_NOTATION: fprintf(out, "NOTATION "); break; case SGML_CATA_PUBLIC: fprintf(out, "PUBLIC "); break; case SGML_CATA_SYSTEM: fprintf(out, "SYSTEM "); break; case SGML_CATA_DELEGATE: fprintf(out, "DELEGATE "); break; case SGML_CATA_BASE: fprintf(out, "BASE "); break; case SGML_CATA_CATALOG: fprintf(out, "CATALOG "); break; case SGML_CATA_DOCUMENT: fprintf(out, "DOCUMENT "); break; case SGML_CATA_SGMLDECL: fprintf(out, "SGMLDECL "); break; default: return; } switch (entry->type) { case SGML_CATA_ENTITY: case SGML_CATA_PENTITY: case SGML_CATA_DOCTYPE: case SGML_CATA_LINKTYPE: case SGML_CATA_NOTATION: fprintf(out, "%s", (const char *) entry->name); break; case SGML_CATA_PUBLIC: case SGML_CATA_SYSTEM: case SGML_CATA_SGMLDECL: case SGML_CATA_DOCUMENT: case SGML_CATA_CATALOG: case SGML_CATA_BASE: case SGML_CATA_DELEGATE: fprintf(out, "\"%s\"", entry->name); break; default: break; } switch (entry->type) { case SGML_CATA_ENTITY: case SGML_CATA_PENTITY: case SGML_CATA_DOCTYPE: case SGML_CATA_LINKTYPE: case SGML_CATA_NOTATION: case SGML_CATA_PUBLIC: case SGML_CATA_SYSTEM: case SGML_CATA_DELEGATE: fprintf(out, " \"%s\"", entry->value); break; default: break; } fprintf(out, "\n");}
/** * xmlDumpXMLCatalogNode: * @catal: top catalog entry * @catalog: pointer to the xml tree * @doc: the containing document * @ns: the current namespace * @cgroup: group node for group members * * Serializes a Catalog entry, called by xmlDumpXMLCatalog and recursively * for group entries */static void xmlDumpXMLCatalogNode(xmlCatalogEntryPtr catal, xmlNodePtr catalog, xmlDocPtr doc, xmlNsPtr ns, xmlCatalogEntryPtr cgroup) { xmlNodePtr node; xmlCatalogEntryPtr cur; /* * add all the catalog entries */ cur = catal; while (cur != NULL) { if (cur->group == cgroup) { switch (cur->type) { case XML_CATA_REMOVED: break; case XML_CATA_BROKEN_CATALOG: case XML_CATA_CATALOG: if (cur == catal) { cur = cur->children; continue; } break; case XML_CATA_NEXT_CATALOG: node = xmlNewDocNode(doc, ns, BAD_CAST "nextCatalog", NULL); xmlSetProp(node, BAD_CAST "catalog", cur->value); xmlAddChild(catalog, node); break; case XML_CATA_NONE: break; case XML_CATA_GROUP: node = xmlNewDocNode(doc, ns, BAD_CAST "group", NULL); xmlSetProp(node, BAD_CAST "id", cur->name); if (cur->value != NULL) { xmlNsPtr xns; xns = xmlSearchNsByHref(doc, node, XML_XML_NAMESPACE); if (xns != NULL) xmlSetNsProp(node, xns, BAD_CAST "base", cur->value); } switch (cur->prefer) { case XML_CATA_PREFER_NONE: break; case XML_CATA_PREFER_PUBLIC: xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "public"); break; case XML_CATA_PREFER_SYSTEM: xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "system"); break; } xmlDumpXMLCatalogNode(cur->next, node, doc, ns, cur); xmlAddChild(catalog, node); break; case XML_CATA_PUBLIC: node = xmlNewDocNode(doc, ns, BAD_CAST "public", NULL); xmlSetProp(node, BAD_CAST "publicId", cur->name); xmlSetProp(node, BAD_CAST "uri", cur->value); xmlAddChild(catalog, node); break; case XML_CATA_SYSTEM: node = xmlNewDocNode(doc, ns, BAD_CAST "system", NULL); xmlSetProp(node, BAD_CAST "systemId", cur->name); xmlSetProp(node, BAD_CAST "uri", cur->value); xmlAddChild(catalog, node); break; case XML_CATA_REWRITE_SYSTEM: node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteSystem", NULL); xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name); xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value); xmlAddChild(catalog, node); break; case XML_CATA_DELEGATE_PUBLIC: node = xmlNewDocNode(doc, ns, BAD_CAST "delegatePublic", NULL); xmlSetProp(node, BAD_CAST "publicIdStartString", cur->name); xmlSetProp(node, BAD_CAST "catalog", cur->value); xmlAddChild(catalog, node); break; case XML_CATA_DELEGATE_SYSTEM: node = xmlNewDocNode(doc, ns, BAD_CAST "delegateSystem", NULL); xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name); xmlSetProp(node, BAD_CAST "catalog", cur->value); xmlAddChild(catalog, node); break; case XML_CATA_URI: node = xmlNewDocNode(doc, ns, BAD_CAST "uri", NULL); xmlSetProp(node, BAD_CAST "name", cur->name); xmlSetProp(node, BAD_CAST "uri", cur->value); xmlAddChild(catalog, node); break; case XML_CATA_REWRITE_URI: node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteURI", NULL); xmlSetProp(node, BAD_CAST "uriStartString", cur->name); xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value); xmlAddChild(catalog, node); break; case XML_CATA_DELEGATE_URI: node = xmlNewDocNode(doc, ns, BAD_CAST "delegateURI", NULL); xmlSetProp(node, BAD_CAST "uriStartString", cur->name); xmlSetProp(node, BAD_CAST "catalog", cur->value); xmlAddChild(catalog, node); break; case SGML_CATA_SYSTEM: case SGML_CATA_PUBLIC: case SGML_CATA_ENTITY: case SGML_CATA_PENTITY: case SGML_CATA_DOCTYPE: case SGML_CATA_LINKTYPE: case SGML_CATA_NOTATION: case SGML_CATA_DELEGATE: case SGML_CATA_BASE: case SGML_CATA_CATALOG: case SGML_CATA_DOCUMENT: case SGML_CATA_SGMLDECL: break; } } cur = cur->next; }}
static intxmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) { int ret; xmlDocPtr doc; xmlNsPtr ns; xmlDtdPtr dtd; xmlNodePtr catalog; xmlOutputBufferPtr buf;
/* * Rebuild a catalog */ doc = xmlNewDoc(NULL); if (doc == NULL) return(-1); dtd = xmlNewDtd(doc, BAD_CAST "catalog", BAD_CAST "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN",BAD_CAST "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd");
xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd);
ns = xmlNewNs(NULL, XML_CATALOGS_NAMESPACE, NULL); if (ns == NULL) { xmlFreeDoc(doc); return(-1); } catalog = xmlNewDocNode(doc, ns, BAD_CAST "catalog", NULL); if (catalog == NULL) { xmlFreeNs(ns); xmlFreeDoc(doc); return(-1); } catalog->nsDef = ns; xmlAddChild((xmlNodePtr) doc, catalog);
xmlDumpXMLCatalogNode(catal, catalog, doc, ns, NULL);
/* * reserialize it */ buf = xmlOutputBufferCreateFile(out, NULL); if (buf == NULL) { xmlFreeDoc(doc); return(-1); } ret = xmlSaveFormatFileTo(buf, doc, NULL, 1);
/* * Free it */ xmlFreeDoc(doc);
return(ret);}#endif /* LIBXML_OUTPUT_ENABLED */
/************************************************************************ * * * Converting SGML Catalogs to XML * * * ************************************************************************/
/** * xmlCatalogConvertEntry: * @entry: the entry * @catal: pointer to the catalog being converted * * Convert one entry from the catalog */static voidxmlCatalogConvertEntry(void *payload, void *data, const xmlChar *name ATTRIBUTE_UNUSED) { xmlCatalogEntryPtr entry = (xmlCatalogEntryPtr) payload; xmlCatalogPtr catal = (xmlCatalogPtr) data; if ((entry == NULL) || (catal == NULL) || (catal->sgml == NULL) || (catal->xml == NULL)) return; switch (entry->type) { case SGML_CATA_ENTITY: entry->type = XML_CATA_PUBLIC; break; case SGML_CATA_PENTITY: entry->type = XML_CATA_PUBLIC; break; case SGML_CATA_DOCTYPE: entry->type = XML_CATA_PUBLIC; break; case SGML_CATA_LINKTYPE: entry->type = XML_CATA_PUBLIC; break; case SGML_CATA_NOTATION: entry->type = XML_CATA_PUBLIC; break; case SGML_CATA_PUBLIC: entry->type = XML_CATA_PUBLIC; break; case SGML_CATA_SYSTEM: entry->type = XML_CATA_SYSTEM; break; case SGML_CATA_DELEGATE: entry->type = XML_CATA_DELEGATE_PUBLIC; break; case SGML_CATA_CATALOG: entry->type = XML_CATA_CATALOG; break; default: xmlHashRemoveEntry(catal->sgml, entry->name, xmlFreeCatalogEntry); return; } /* * Conversion successful, remove from the SGML catalog * and add it to the default XML one */ xmlHashRemoveEntry(catal->sgml, entry->name, NULL); entry->parent = catal->xml; entry->next = NULL; if (catal->xml->children == NULL) catal->xml->children = entry; else { xmlCatalogEntryPtr prev;
prev = catal->xml->children; while (prev->next != NULL) prev = prev->next; prev->next = entry; }}
/** * xmlConvertSGMLCatalog: * @catal: the catalog * * Convert all the SGML catalog entries as XML ones * * Returns the number of entries converted if successful, -1 otherwise */intxmlConvertSGMLCatalog(xmlCatalogPtr catal) {
if ((catal == NULL) || (catal->type != XML_SGML_CATALOG_TYPE)) return(-1);
if (xmlDebugCatalogs) { xmlGenericError(xmlGenericErrorContext, "Converting SGML catalog to XML\n"); } xmlHashScan(catal->sgml, xmlCatalogConvertEntry, &catal); return(0);}
/************************************************************************ * * * Helper function * * * ************************************************************************/
/** * xmlCatalogUnWrapURN: * @urn: an "urn:publicid:" to unwrap * * Expand the URN into the equivalent Public Identifier * * Returns the new identifier or NULL, the string must be deallocated * by the caller. */static xmlChar *xmlCatalogUnWrapURN(const xmlChar *urn) { xmlChar result[2000]; unsigned int i = 0;
if (xmlStrncmp(urn, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) return(NULL); urn += sizeof(XML_URN_PUBID) - 1;
while (*urn != 0) { if (i > sizeof(result) - 4) break; if (*urn == '+') { result[i++] = ' '; urn++; } else if (*urn == ':') { result[i++] = '/'; result[i++] = '/'; urn++; } else if (*urn == ';') { result[i++] = ':'; result[i++] = ':'; urn++; } else if (*urn == '%') { if ((urn[1] == '2') && (urn[2] == 'B')) result[i++] = '+'; else if ((urn[1] == '3') && (urn[2] == 'A')) result[i++] = ':'; else if ((urn[1] == '2') && (urn[2] == 'F')) result[i++] = '/'; else if ((urn[1] == '3') && (urn[2] == 'B')) result[i++] = ';'; else if ((urn[1] == '2') && (urn[2] == '7')) result[i++] = '\''; else if ((urn[1] == '3') && (urn[2] == 'F')) result[i++] = '?'; else if ((urn[1] == '2') && (urn[2] == '3')) result[i++] = '#'; else if ((urn[1] == '2') && (urn[2] == '5')) result[i++] = '%'; else { result[i++] = *urn; urn++; continue; } urn += 3; } else { result[i++] = *urn; urn++; } } result[i] = 0;
return(xmlStrdup(result));}
/** * xmlParseCatalogFile: * @filename: the filename * * parse an XML file and build a tree. It's like xmlParseFile() * except it bypass all catalog lookups. * * Returns the resulting document tree or NULL in case of error */
xmlDocPtrxmlParseCatalogFile(const char *filename) { xmlDocPtr ret; xmlParserCtxtPtr ctxt; char *directory = NULL; xmlParserInputPtr inputStream; xmlParserInputBufferPtr buf;
ctxt = xmlNewParserCtxt(); if (ctxt == NULL) { xmlCatalogErrMemory("allocating parser context"); return(NULL); }
buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE); if (buf == NULL) { xmlFreeParserCtxt(ctxt); return(NULL); }
inputStream = xmlNewInputStream(ctxt); if (inputStream == NULL) { xmlFreeParserInputBuffer(buf); xmlFreeParserCtxt(ctxt); return(NULL); }
inputStream->filename = (char *) xmlCanonicPath((const xmlChar *)filename); inputStream->buf = buf; xmlBufResetInput(buf->buffer, inputStream);
inputPush(ctxt, inputStream); if (ctxt->directory == NULL) directory = xmlParserGetDirectory(filename); if ((ctxt->directory == NULL) && (directory != NULL)) ctxt->directory = directory; ctxt->valid = 0; ctxt->validate = 0; ctxt->loadsubset = 0; ctxt->pedantic = 0; ctxt->dictNames = 1;
xmlParseDocument(ctxt);
if (ctxt->wellFormed) ret = ctxt->myDoc; else { ret = NULL; xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL; } xmlFreeParserCtxt(ctxt);
return(ret);}
/** * xmlLoadFileContent: * @filename: a file path * * Load a file content into memory. * * Returns a pointer to the 0 terminated string or NULL in case of error */static xmlChar *xmlLoadFileContent(const char *filename){#ifdef HAVE_STAT int fd;#else FILE *fd;#endif int len; long size;
#ifdef HAVE_STAT struct stat info;#endif xmlChar *content;
if (filename == NULL) return (NULL);
#ifdef HAVE_STAT if (stat(filename, &info) < 0) return (NULL);#endif
#ifdef HAVE_STAT if ((fd = open(filename, O_RDONLY)) < 0)#else if ((fd = fopen(filename, "rb")) == NULL)#endif { return (NULL); }#ifdef HAVE_STAT size = info.st_size;#else if (fseek(fd, 0, SEEK_END) || (size = ftell(fd)) == EOF || fseek(fd, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */ fclose(fd); return (NULL); }#endif content = (xmlChar*)xmlMallocAtomic(size + 10); if (content == NULL) { xmlCatalogErrMemory("allocating catalog data");#ifdef HAVE_STAT close(fd);#else fclose(fd);#endif return (NULL); }#ifdef HAVE_STAT len = read(fd, content, size); close(fd);#else len = fread(content, 1, size, fd); fclose(fd);#endif if (len < 0) { xmlFree(content); return (NULL); } content[len] = 0;
return(content);}
/** * xmlCatalogNormalizePublic: * @pubID: the public ID string * * Normalizes the Public Identifier * * Implements 6.2. Public Identifier Normalization * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html * * Returns the new string or NULL, the string must be deallocated * by the caller. */static xmlChar *xmlCatalogNormalizePublic(const xmlChar *pubID){ int ok = 1; int white; const xmlChar *p; xmlChar *ret; xmlChar *q;
if (pubID == NULL) return(NULL);
white = 1; for (p = pubID;*p != 0 && ok;p++) { if (!xmlIsBlank_ch(*p)) white = 0; else if (*p == 0x20 && !white) white = 1; else ok = 0; } if (ok && !white) /* is normalized */ return(NULL);
ret = xmlStrdup(pubID); q = ret; white = 0; for (p = pubID;*p != 0;p++) { if (xmlIsBlank_ch(*p)) { if (q != ret) white = 1; } else { if (white) { *(q++) = 0x20; white = 0; } *(q++) = *p; } } *q = 0; return(ret);}
/************************************************************************ * * * The XML Catalog parser * * * ************************************************************************/
static xmlCatalogEntryPtrxmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename);static voidxmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer, xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup);static xmlChar *xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, const xmlChar *sysID);static xmlChar *xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI);
/** * xmlGetXMLCatalogEntryType: * @name: the name * * lookup the internal type associated to an XML catalog entry name * * Returns the type associated with that name */static xmlCatalogEntryTypexmlGetXMLCatalogEntryType(const xmlChar *name) { xmlCatalogEntryType type = XML_CATA_NONE; if (xmlStrEqual(name, (const xmlChar *) "system")) type = XML_CATA_SYSTEM; else if (xmlStrEqual(name, (const xmlChar *) "public")) type = XML_CATA_PUBLIC; else if (xmlStrEqual(name, (const xmlChar *) "rewriteSystem")) type = XML_CATA_REWRITE_SYSTEM; else if (xmlStrEqual(name, (const xmlChar *) "delegatePublic")) type = XML_CATA_DELEGATE_PUBLIC; else if (xmlStrEqual(name, (const xmlChar *) "delegateSystem")) type = XML_CATA_DELEGATE_SYSTEM; else if (xmlStrEqual(name, (const xmlChar *) "uri")) type = XML_CATA_URI; else if (xmlStrEqual(name, (const xmlChar *) "rewriteURI")) type = XML_CATA_REWRITE_URI; else if (xmlStrEqual(name, (const xmlChar *) "delegateURI")) type = XML_CATA_DELEGATE_URI; else if (xmlStrEqual(name, (const xmlChar *) "nextCatalog")) type = XML_CATA_NEXT_CATALOG; else if (xmlStrEqual(name, (const xmlChar *) "catalog")) type = XML_CATA_CATALOG; return(type);}
/** * xmlParseXMLCatalogOneNode: * @cur: the XML node * @type: the type of Catalog entry * @name: the name of the node * @attrName: the attribute holding the value * @uriAttrName: the attribute holding the URI-Reference * @prefer: the PUBLIC vs. SYSTEM current preference value * @cgroup: the group which includes this node * * Finishes the examination of an XML tree node of a catalog and build * 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, xmlCatalogEntryPtr cgroup) { 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, cgroup); } 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 * @cgroup: the group which includes this node * * 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, xmlCatalogEntryPtr cgroup){ xmlChar *base = NULL; xmlCatalogEntryPtr entry = NULL;
if (cur == NULL) return; if (xmlStrEqual(cur->name, BAD_CAST "group")) { xmlChar *prop; xmlCatalogPrefer pref = XML_CATA_PREFER_NONE;
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); pref = prefer; } prop = xmlGetProp(cur, BAD_CAST "id"); base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE); entry = xmlNewCatalogEntry(XML_CATA_GROUP, prop, base, NULL, pref, cgroup); xmlFree(prop); } else if (xmlStrEqual(cur->name, BAD_CAST "public")) { entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_PUBLIC, BAD_CAST "public", BAD_CAST "publicId", BAD_CAST "uri", prefer, cgroup); } else if (xmlStrEqual(cur->name, BAD_CAST "system")) { entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_SYSTEM, BAD_CAST "system", BAD_CAST "systemId", BAD_CAST "uri", prefer, cgroup); } 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, cgroup); } 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, cgroup); } 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, cgroup); } else if (xmlStrEqual(cur->name, BAD_CAST "uri")) { entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_URI, BAD_CAST "uri", BAD_CAST "name", BAD_CAST "uri", prefer, cgroup); } 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, cgroup); } 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, cgroup); } else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) { entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG, BAD_CAST "nextCatalog", NULL, BAD_CAST "catalog", prefer, cgroup); } if (entry != NULL) { if (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 (entry->type == XML_CATA_GROUP) { /* * Recurse to propagate prefer to the subtree * (xml:base handling is automated) */ xmlParseXMLCatalogNodeList(cur->children, prefer, parent, entry); } } if (base != NULL) xmlFree(base);}
/** * xmlParseXMLCatalogNodeList: * @cur: the XML node list of siblings * @prefer: the PUBLIC vs. SYSTEM current preference value * @parent: the parent Catalog entry * @cgroup: the group which includes this list * * 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, xmlCatalogEntryPtr cgroup) { while (cur != NULL) { if ((cur->ns != NULL) && (cur->ns->href != NULL) && (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) { xmlParseXMLCatalogNode(cur, prefer, parent, cgroup); } 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, NULL); 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, NULL); } 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);
/* * 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, NULL); else cur->next = xmlNewCatalogEntry(typ, orig, replace, NULL, catal->prefer, NULL); if (doregister) { catal->type = XML_CATA_CATALOG; cur = (xmlCatalogEntryPtr)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++;
/* * First tries steps 2/ 3/ 4/ if a system ID is provided. */ if (sysID != NULL) { xmlCatalogEntryPtr rewrite = NULL; int lenrewrite = 0, len; cur = catal; haveDelegate = 0; while (cur != NULL) { switch (cur->type) { case XML_CATA_SYSTEM: if (xmlStrEqual(sysID, cur->name)) { if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Found system match %s, using %s\n", cur->name, cur->URL); catal->depth--; return(xmlStrdup(cur->URL)); } break; case XML_CATA_REWRITE_SYSTEM: len = xmlStrlen(cur->name); if ((len > lenrewrite) && (!xmlStrncmp(sysID, cur->name, len))) { lenrewrite = len; rewrite = cur; } break; case XML_CATA_DELEGATE_SYSTEM: if (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name))) haveDelegate++; break; case XML_CATA_NEXT_CATALOG: haveNext++; break; default: break; } cur = cur->next; } if (rewrite != NULL) { if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Using rewriting rule %s\n", rewrite->name); ret = xmlStrdup(rewrite->URL); if (ret != NULL) ret = xmlStrcat(ret, &sysID[lenrewrite]); catal->depth--; return(ret); } if (haveDelegate) { const xmlChar *delegates[MAX_DELEGATE]; int nbList = 0, i;
/* * Assume the entries have been sorted by decreasing substring * matches when the list was produced. */ cur = catal; while (cur != NULL) { if ((cur->type == XML_CATA_DELEGATE_SYSTEM) && (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))) { for (i = 0;i < nbList;i++) if (xmlStrEqual(cur->URL, delegates[i])) break; if (i < nbList) { cur = cur->next; continue; } if (nbList < MAX_DELEGATE) delegates[nbList++] = cur->URL;
if (cur->children == NULL) { xmlFetchXMLCatalogFile(cur); } if (cur->children != NULL) { if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Trying system delegate %s\n", cur->URL); ret = xmlCatalogListXMLResolve( cur->children, NULL, sysID); if (ret != NULL) { catal->depth--; return(ret); } } } cur = cur->next; } /* * Apply the cut algorithm explained in 4/ */ catal->depth--; return(XML_CATAL_BREAK); } } /* * Then tries 5/ 6/ if a public ID is provided */ if (pubID != NULL) { cur = catal; haveDelegate = 0; while (cur != NULL) { switch (cur->type) { case XML_CATA_PUBLIC: if (xmlStrEqual(pubID, cur->name)) { if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Found public match %s\n", cur->name); catal->depth--; return(xmlStrdup(cur->URL)); } break; case XML_CATA_DELEGATE_PUBLIC: if (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)) && (cur->prefer == XML_CATA_PREFER_PUBLIC)) haveDelegate++; break; case XML_CATA_NEXT_CATALOG: if (sysID == NULL) haveNext++; break; default: break; } cur = cur->next; } if (haveDelegate) { const xmlChar *delegates[MAX_DELEGATE]; int nbList = 0, i;
/* * Assume the entries have been sorted by decreasing substring * matches when the list was produced. */ cur = catal; while (cur != NULL) { if ((cur->type == XML_CATA_DELEGATE_PUBLIC) && (cur->prefer == XML_CATA_PREFER_PUBLIC) && (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)))) {
for (i = 0;i < nbList;i++) if (xmlStrEqual(cur->URL, delegates[i])) break; if (i < nbList) { cur = cur->next; continue; } if (nbList < MAX_DELEGATE) delegates[nbList++] = cur->URL;
if (cur->children == NULL) { xmlFetchXMLCatalogFile(cur); } if (cur->children != NULL) { if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Trying public delegate %s\n", cur->URL); ret = xmlCatalogListXMLResolve( cur->children, pubID, NULL); if (ret != NULL) { catal->depth--; return(ret); } } } cur = cur->next; } /* * Apply the cut algorithm explained in 4/ */ catal->depth--; return(XML_CATAL_BREAK); } } if (haveNext) { cur = catal; while (cur != NULL) { if (cur->type == XML_CATA_NEXT_CATALOG) { if (cur->children == NULL) { xmlFetchXMLCatalogFile(cur); } if (cur->children != NULL) { ret = xmlCatalogListXMLResolve(cur->children, pubID, sysID); if (ret != NULL) { catal->depth--; return(ret); } else if (catal->depth > MAX_CATAL_DEPTH) { return(NULL); } } } cur = cur->next; } }
catal->depth--; return(NULL);}
/** * xmlCatalogXMLResolveURI: * @catal: a catalog list * @URI: the URI * @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.2.2. URI 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 *xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) { xmlChar *ret = NULL; xmlCatalogEntryPtr cur; int haveDelegate = 0; int haveNext = 0; xmlCatalogEntryPtr rewrite = NULL; int lenrewrite = 0, len;
if (catal == NULL) return(NULL);
if (URI == NULL) return(NULL);
if (catal->depth > MAX_CATAL_DEPTH) { xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION, "Detected recursion in catalog %s\n", catal->name, NULL, NULL); return(NULL); }
/* * First tries steps 2/ 3/ 4/ if a system ID is provided. */ cur = catal; haveDelegate = 0; while (cur != NULL) { switch (cur->type) { case XML_CATA_URI: if (xmlStrEqual(URI, cur->name)) { if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Found URI match %s\n", cur->name); return(xmlStrdup(cur->URL)); } break; case XML_CATA_REWRITE_URI: len = xmlStrlen(cur->name); if ((len > lenrewrite) && (!xmlStrncmp(URI, cur->name, len))) { lenrewrite = len; rewrite = cur; } break; case XML_CATA_DELEGATE_URI: if (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name))) haveDelegate++; break; case XML_CATA_NEXT_CATALOG: haveNext++; break; default: break; } cur = cur->next; } if (rewrite != NULL) { if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Using rewriting rule %s\n", rewrite->name); ret = xmlStrdup(rewrite->URL); if (ret != NULL) ret = xmlStrcat(ret, &URI[lenrewrite]); return(ret); } if (haveDelegate) { const xmlChar *delegates[MAX_DELEGATE]; int nbList = 0, i;
/* * Assume the entries have been sorted by decreasing substring * matches when the list was produced. */ cur = catal; while (cur != NULL) { if (((cur->type == XML_CATA_DELEGATE_SYSTEM) || (cur->type == XML_CATA_DELEGATE_URI)) && (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))) { for (i = 0;i < nbList;i++) if (xmlStrEqual(cur->URL, delegates[i])) break; if (i < nbList) { cur = cur->next; continue; } if (nbList < MAX_DELEGATE) delegates[nbList++] = cur->URL;
if (cur->children == NULL) { xmlFetchXMLCatalogFile(cur); } if (cur->children != NULL) { if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Trying URI delegate %s\n", cur->URL); ret = xmlCatalogListXMLResolveURI( cur->children, URI); if (ret != NULL) return(ret); } } cur = cur->next; } /* * Apply the cut algorithm explained in 4/ */ return(XML_CATAL_BREAK); } if (haveNext) { cur = catal; while (cur != NULL) { if (cur->type == XML_CATA_NEXT_CATALOG) { if (cur->children == NULL) { xmlFetchXMLCatalogFile(cur); } if (cur->children != NULL) { ret = xmlCatalogListXMLResolveURI(cur->children, URI); if (ret != NULL) return(ret); } } cur = cur->next; } }
return(NULL);}
/** * xmlCatalogListXMLResolve: * @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 catalogs * * 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 *xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, const xmlChar *sysID) { xmlChar *ret = NULL; xmlChar *urnID = NULL; xmlChar *normid;
if (catal == NULL) return(NULL); if ((pubID == NULL) && (sysID == NULL)) return(NULL);
normid = xmlCatalogNormalizePublic(pubID); if (normid != NULL) pubID = (*normid != 0 ? normid : NULL);
if (!xmlStrncmp(pubID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) { urnID = xmlCatalogUnWrapURN(pubID); if (xmlDebugCatalogs) { if (urnID == NULL) xmlGenericError(xmlGenericErrorContext, "Public URN ID %s expanded to NULL\n", pubID); else xmlGenericError(xmlGenericErrorContext, "Public URN ID expanded to %s\n", urnID); } ret = xmlCatalogListXMLResolve(catal, urnID, sysID); if (urnID != NULL) xmlFree(urnID); if (normid != NULL) xmlFree(normid); return(ret); } if (!xmlStrncmp(sysID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) { urnID = xmlCatalogUnWrapURN(sysID); if (xmlDebugCatalogs) { if (urnID == NULL) xmlGenericError(xmlGenericErrorContext, "System URN ID %s expanded to NULL\n", sysID); else xmlGenericError(xmlGenericErrorContext, "System URN ID expanded to %s\n", urnID); } if (pubID == NULL) ret = xmlCatalogListXMLResolve(catal, urnID, NULL); else if (xmlStrEqual(pubID, urnID)) ret = xmlCatalogListXMLResolve(catal, pubID, NULL); else { ret = xmlCatalogListXMLResolve(catal, pubID, urnID); } if (urnID != NULL) xmlFree(urnID); if (normid != NULL) xmlFree(normid); return(ret); } while (catal != NULL) { if (catal->type == XML_CATA_CATALOG) { if (catal->children == NULL) { xmlFetchXMLCatalogFile(catal); } if (catal->children != NULL) { ret = xmlCatalogXMLResolve(catal->children, pubID, sysID); if (ret != NULL) { break; } else if (catal->children->depth > MAX_CATAL_DEPTH) { ret = NULL; break; } } } catal = catal->next; } if (normid != NULL) xmlFree(normid); return(ret);}
/** * xmlCatalogListXMLResolveURI: * @catal: a catalog list * @URI: the URI * * Do a complete resolution lookup of an URI for a list of catalogs * * Implements (or tries to) 7.2. URI 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 *xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) { xmlChar *ret = NULL; xmlChar *urnID = NULL;
if (catal == NULL) return(NULL); if (URI == NULL) return(NULL);
if (!xmlStrncmp(URI, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) { urnID = xmlCatalogUnWrapURN(URI); if (xmlDebugCatalogs) { if (urnID == NULL) xmlGenericError(xmlGenericErrorContext, "URN ID %s expanded to NULL\n", URI); else xmlGenericError(xmlGenericErrorContext, "URN ID expanded to %s\n", urnID); } ret = xmlCatalogListXMLResolve(catal, urnID, NULL); if (urnID != NULL) xmlFree(urnID); return(ret); } while (catal != NULL) { if (catal->type == XML_CATA_CATALOG) { if (catal->children == NULL) { xmlFetchXMLCatalogFile(catal); } if (catal->children != NULL) { ret = xmlCatalogXMLResolveURI(catal->children, URI); if (ret != NULL) return(ret); } } catal = catal->next; } return(ret);}
/************************************************************************ * * * The SGML Catalog parser * * * ************************************************************************/
#define RAW *cur#define NEXT cur++;#define SKIP(x) cur += x;
#define SKIP_BLANKS while (IS_BLANK_CH(*cur)) NEXT;
/** * xmlParseSGMLCatalogComment: * @cur: the current character * * Skip a comment in an SGML catalog * * Returns new current character */static const xmlChar *xmlParseSGMLCatalogComment(const xmlChar *cur) { if ((cur[0] != '-') || (cur[1] != '-')) return(cur); SKIP(2); while ((cur[0] != 0) && ((cur[0] != '-') || ((cur[1] != '-')))) NEXT; if (cur[0] == 0) { return(NULL); } return(cur + 2);}
/** * xmlParseSGMLCatalogPubid: * @cur: the current character * @id: the return location * * Parse an SGML catalog ID * * Returns new current character and store the value in @id */static const xmlChar *xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) { xmlChar *buf = NULL, *tmp; int len = 0; int size = 50; xmlChar stop;
*id = NULL;
if (RAW == '"') { NEXT; stop = '"'; } else if (RAW == '\'') { NEXT; stop = '\''; } else { stop = ' '; } buf = (xmlChar *) xmlMallocAtomic(size); if (buf == NULL) { xmlCatalogErrMemory("allocating public ID"); return(NULL); } while (IS_PUBIDCHAR_CH(*cur) || (*cur == '?')) { if ((*cur == stop) && (stop != ' ')) break; if ((stop == ' ') && (IS_BLANK_CH(*cur))) break; if (len + 1 >= size) { size *= 2; tmp = (xmlChar *) xmlRealloc(buf, size); if (tmp == NULL) { xmlCatalogErrMemory("allocating public ID"); xmlFree(buf); return(NULL); } buf = tmp; } buf[len++] = *cur; NEXT; } buf[len] = 0; if (stop == ' ') { if (!IS_BLANK_CH(*cur)) { xmlFree(buf); return(NULL); } } else { if (*cur != stop) { xmlFree(buf); return(NULL); } NEXT; } *id = buf; return(cur);}
/** * xmlParseSGMLCatalogName: * @cur: the current character * @name: the return location * * Parse an SGML catalog name * * Returns new current character and store the value in @name */static const xmlChar *xmlParseSGMLCatalogName(const xmlChar *cur, xmlChar **name) { xmlChar buf[XML_MAX_NAMELEN + 5]; int len = 0; int c;
*name = NULL;
/* * Handler for more complex cases */ c = *cur; if ((!IS_LETTER(c) && (c != '_') && (c != ':'))) { return(NULL); }
while (((IS_LETTER(c)) || (IS_DIGIT(c)) || (c == '.') || (c == '-') || (c == '_') || (c == ':'))) { buf[len++] = c; cur++; c = *cur; if (len >= XML_MAX_NAMELEN) return(NULL); } *name = xmlStrndup(buf, len); return(cur);}
/** * xmlGetSGMLCatalogEntryType: * @name: the entry name * * Get the Catalog entry type for a given SGML Catalog name * * Returns Catalog entry type */static xmlCatalogEntryTypexmlGetSGMLCatalogEntryType(const xmlChar *name) { xmlCatalogEntryType type = XML_CATA_NONE; if (xmlStrEqual(name, (const xmlChar *) "SYSTEM")) type = SGML_CATA_SYSTEM; else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC")) type = SGML_CATA_PUBLIC; else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE")) type = SGML_CATA_DELEGATE; else if (xmlStrEqual(name, (const xmlChar *) "ENTITY")) type = SGML_CATA_ENTITY; else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE")) type = SGML_CATA_DOCTYPE; else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE")) type = SGML_CATA_LINKTYPE; else if (xmlStrEqual(name, (const xmlChar *) "NOTATION")) type = SGML_CATA_NOTATION; else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL")) type = SGML_CATA_SGMLDECL; else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT")) type = SGML_CATA_DOCUMENT; else if (xmlStrEqual(name, (const xmlChar *) "CATALOG")) type = SGML_CATA_CATALOG; else if (xmlStrEqual(name, (const xmlChar *) "BASE")) type = SGML_CATA_BASE; return(type);}
/** * xmlParseSGMLCatalog: * @catal: the SGML Catalog * @value: the content of the SGML Catalog serialization * @file: the filepath for the catalog * @super: should this be handled as a Super Catalog in which case * parsing is not recursive * * Parse an SGML catalog content and fill up the @catal hash table with * the new entries found. * * Returns 0 in case of success, -1 in case of error. */static intxmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value, const char *file, int super) { const xmlChar *cur = value; xmlChar *base = NULL; int res;
if ((cur == NULL) || (file == NULL)) return(-1); base = xmlStrdup((const xmlChar *) file);
while ((cur != NULL) && (cur[0] != 0)) { SKIP_BLANKS; if (cur[0] == 0) break; if ((cur[0] == '-') && (cur[1] == '-')) { cur = xmlParseSGMLCatalogComment(cur); if (cur == NULL) { /* error */ break; } } else { xmlChar *sysid = NULL; xmlChar *name = NULL; xmlCatalogEntryType type = XML_CATA_NONE;
cur = xmlParseSGMLCatalogName(cur, &name); if (cur == NULL || name == NULL) { /* error */ break; } if (!IS_BLANK_CH(*cur)) { /* error */ xmlFree(name); break; } SKIP_BLANKS; if (xmlStrEqual(name, (const xmlChar *) "SYSTEM")) type = SGML_CATA_SYSTEM; else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC")) type = SGML_CATA_PUBLIC; else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE")) type = SGML_CATA_DELEGATE; else if (xmlStrEqual(name, (const xmlChar *) "ENTITY")) type = SGML_CATA_ENTITY; else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE")) type = SGML_CATA_DOCTYPE; else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE")) type = SGML_CATA_LINKTYPE; else if (xmlStrEqual(name, (const xmlChar *) "NOTATION")) type = SGML_CATA_NOTATION; else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL")) type = SGML_CATA_SGMLDECL; else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT")) type = SGML_CATA_DOCUMENT; else if (xmlStrEqual(name, (const xmlChar *) "CATALOG")) type = SGML_CATA_CATALOG; else if (xmlStrEqual(name, (const xmlChar *) "BASE")) type = SGML_CATA_BASE; else if (xmlStrEqual(name, (const xmlChar *) "OVERRIDE")) { xmlFree(name); cur = xmlParseSGMLCatalogName(cur, &name); if (name == NULL) { /* error */ break; } xmlFree(name); continue; } xmlFree(name); name = NULL;
switch(type) { case SGML_CATA_ENTITY: if (*cur == '%') type = SGML_CATA_PENTITY; /* Falls through. */ case SGML_CATA_PENTITY: case SGML_CATA_DOCTYPE: case SGML_CATA_LINKTYPE: case SGML_CATA_NOTATION: cur = xmlParseSGMLCatalogName(cur, &name); if (cur == NULL) { /* error */ break; } if (!IS_BLANK_CH(*cur)) { /* error */ break; } SKIP_BLANKS; cur = xmlParseSGMLCatalogPubid(cur, &sysid); if (cur == NULL) { /* error */ break; } break; case SGML_CATA_PUBLIC: case SGML_CATA_SYSTEM: case SGML_CATA_DELEGATE: cur = xmlParseSGMLCatalogPubid(cur, &name); if (cur == NULL) { /* error */ break; } if (type != SGML_CATA_SYSTEM) { xmlChar *normid;
normid = xmlCatalogNormalizePublic(name); if (normid != NULL) { if (name != NULL) xmlFree(name); if (*normid != 0) name = normid; else { xmlFree(normid); name = NULL; } } } if (!IS_BLANK_CH(*cur)) { /* error */ break; } SKIP_BLANKS; cur = xmlParseSGMLCatalogPubid(cur, &sysid); if (cur == NULL) { /* error */ break; } break; case SGML_CATA_BASE: case SGML_CATA_CATALOG: case SGML_CATA_DOCUMENT: case SGML_CATA_SGMLDECL: cur = xmlParseSGMLCatalogPubid(cur, &sysid); if (cur == NULL) { /* error */ break; } break; default: break; } if (cur == NULL) { if (name != NULL) xmlFree(name); if (sysid != NULL) xmlFree(sysid); break; } else if (type == SGML_CATA_BASE) { if (base != NULL) xmlFree(base); base = xmlStrdup(sysid); } else if ((type == SGML_CATA_PUBLIC) || (type == SGML_CATA_SYSTEM)) { xmlChar *filename;
filename = xmlBuildURI(sysid, base); if (filename != NULL) { xmlCatalogEntryPtr entry;
entry = xmlNewCatalogEntry(type, name, filename, NULL, XML_CATA_PREFER_NONE, NULL); res = xmlHashAddEntry(catal->sgml, name, entry); if (res < 0) { xmlFreeCatalogEntry(entry, NULL); } xmlFree(filename); }
} else if (type == SGML_CATA_CATALOG) { if (super) { xmlCatalogEntryPtr entry;
entry = xmlNewCatalogEntry(type, sysid, NULL, NULL, XML_CATA_PREFER_NONE, NULL); res = xmlHashAddEntry(catal->sgml, sysid, entry); if (res < 0) { xmlFreeCatalogEntry(entry, NULL); } } else { xmlChar *filename;
filename = xmlBuildURI(sysid, base); if (filename != NULL) { xmlExpandCatalog(catal, (const char *)filename); xmlFree(filename); } } } /* * drop anything else we won't handle it */ if (name != NULL) xmlFree(name); if (sysid != NULL) xmlFree(sysid); } } if (base != NULL) xmlFree(base); if (cur == NULL) return(-1); return(0);}
/************************************************************************ * * * SGML Catalog handling * * * ************************************************************************/
/** * xmlCatalogGetSGMLPublic: * @catal: an SGML catalog hash * @pubID: the public ID string * * Try to lookup the catalog local reference associated to a public ID * * Returns the local resource if found or NULL otherwise. */static const xmlChar *xmlCatalogGetSGMLPublic(xmlHashTablePtr catal, const xmlChar *pubID) { xmlCatalogEntryPtr entry; xmlChar *normid;
if (catal == NULL) return(NULL);
normid = xmlCatalogNormalizePublic(pubID); if (normid != NULL) pubID = (*normid != 0 ? normid : NULL);
entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, pubID); if (entry == NULL) { if (normid != NULL) xmlFree(normid); return(NULL); } if (entry->type == SGML_CATA_PUBLIC) { if (normid != NULL) xmlFree(normid); return(entry->URL); } if (normid != NULL) xmlFree(normid); return(NULL);}
/** * xmlCatalogGetSGMLSystem: * @catal: an SGML catalog hash * @sysID: the system ID string * * Try to lookup the catalog local reference for a system ID * * Returns the local resource if found or NULL otherwise. */static const xmlChar *xmlCatalogGetSGMLSystem(xmlHashTablePtr catal, const xmlChar *sysID) { xmlCatalogEntryPtr entry;
if (catal == NULL) return(NULL);
entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, sysID); if (entry == NULL) return(NULL); if (entry->type == SGML_CATA_SYSTEM) return(entry->URL); return(NULL);}
/** * xmlCatalogSGMLResolve: * @catal: the SGML catalog * @pubID: the public ID string * @sysID: the system ID string * * Do a complete resolution lookup of an External Identifier * * Returns the URI of the resource or NULL if not found */static const xmlChar *xmlCatalogSGMLResolve(xmlCatalogPtr catal, const xmlChar *pubID, const xmlChar *sysID) { const xmlChar *ret = NULL;
if (catal->sgml == NULL) return(NULL);
if (pubID != NULL) ret = xmlCatalogGetSGMLPublic(catal->sgml, pubID); if (ret != NULL) return(ret); if (sysID != NULL) ret = xmlCatalogGetSGMLSystem(catal->sgml, sysID); if (ret != NULL) return(ret); return(NULL);}
/************************************************************************ * * * Specific Public interfaces * * * ************************************************************************/
/** * xmlLoadSGMLSuperCatalog: * @filename: a file path * * Load an SGML super catalog. It won't expand CATALOG or DELEGATE * references. This is only needed for manipulating SGML Super Catalogs * like adding and removing CATALOG or DELEGATE entries. * * Returns the catalog parsed or NULL in case of error */xmlCatalogPtrxmlLoadSGMLSuperCatalog(const char *filename){ xmlChar *content; xmlCatalogPtr catal; int ret;
content = xmlLoadFileContent(filename); if (content == NULL) return(NULL);
catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer); if (catal == NULL) { xmlFree(content); return(NULL); }
ret = xmlParseSGMLCatalog(catal, content, filename, 1); xmlFree(content); if (ret < 0) { xmlFreeCatalog(catal); return(NULL); } return (catal);}
/** * xmlLoadACatalog: * @filename: a file path * * Load the catalog and build the associated data structures. * This can be either an XML Catalog or an SGML Catalog * It will recurse in SGML CATALOG entries. On the other hand XML * Catalogs are not handled recursively. * * Returns the catalog parsed or NULL in case of error */xmlCatalogPtrxmlLoadACatalog(const char *filename){ xmlChar *content; xmlChar *first; xmlCatalogPtr catal; int ret;
content = xmlLoadFileContent(filename); if (content == NULL) return(NULL);
first = content;
while ((*first != 0) && (*first != '-') && (*first != '<') && (!(((*first >= 'A') && (*first <= 'Z')) || ((*first >= 'a') && (*first <= 'z'))))) first++;
if (*first != '<') { catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer); if (catal == NULL) { xmlFree(content); return(NULL); } ret = xmlParseSGMLCatalog(catal, content, filename, 0); if (ret < 0) { xmlFreeCatalog(catal); xmlFree(content); return(NULL); } } else { catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer); if (catal == NULL) { xmlFree(content); return(NULL); } catal->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL); } xmlFree(content); return (catal);}
/** * xmlExpandCatalog: * @catal: a catalog * @filename: a file path * * Load the catalog and expand the existing catal structure. * This can be either an XML Catalog or an SGML Catalog * * Returns 0 in case of success, -1 in case of error */static intxmlExpandCatalog(xmlCatalogPtr catal, const char *filename){ int ret;
if ((catal == NULL) || (filename == NULL)) return(-1);
if (catal->type == XML_SGML_CATALOG_TYPE) { xmlChar *content;
content = xmlLoadFileContent(filename); if (content == NULL) return(-1);
ret = xmlParseSGMLCatalog(catal, content, filename, 0); if (ret < 0) { xmlFree(content); return(-1); } xmlFree(content); } else { xmlCatalogEntryPtr tmp, cur; tmp = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL);
cur = catal->xml; if (cur == NULL) { catal->xml = tmp; } else { while (cur->next != NULL) cur = cur->next; cur->next = tmp; } } return (0);}
/** * xmlACatalogResolveSystem: * @catal: a Catalog * @sysID: the system ID string * * Try to lookup the catalog resource for a system ID * * Returns the resource if found or NULL otherwise, the value returned * must be freed by the caller. */xmlChar *xmlACatalogResolveSystem(xmlCatalogPtr catal, const xmlChar *sysID) { xmlChar *ret = NULL;
if ((sysID == NULL) || (catal == NULL)) return(NULL);
if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Resolve sysID %s\n", sysID);
if (catal->type == XML_XML_CATALOG_TYPE) { ret = xmlCatalogListXMLResolve(catal->xml, NULL, sysID); if (ret == XML_CATAL_BREAK) ret = NULL; } else { const xmlChar *sgml;
sgml = xmlCatalogGetSGMLSystem(catal->sgml, sysID); if (sgml != NULL) ret = xmlStrdup(sgml); } return(ret);}
/** * xmlACatalogResolvePublic: * @catal: a Catalog * @pubID: the public ID string * * Try to lookup the catalog local reference associated to a public ID in that catalog * * Returns the local resource if found or NULL otherwise, the value returned * must be freed by the caller. */xmlChar *xmlACatalogResolvePublic(xmlCatalogPtr catal, const xmlChar *pubID) { xmlChar *ret = NULL;
if ((pubID == NULL) || (catal == NULL)) return(NULL);
if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Resolve pubID %s\n", pubID);
if (catal->type == XML_XML_CATALOG_TYPE) { ret = xmlCatalogListXMLResolve(catal->xml, pubID, NULL); if (ret == XML_CATAL_BREAK) ret = NULL; } else { const xmlChar *sgml;
sgml = xmlCatalogGetSGMLPublic(catal->sgml, pubID); if (sgml != NULL) ret = xmlStrdup(sgml); } return(ret);}
/** * xmlACatalogResolve: * @catal: a Catalog * @pubID: the public ID string * @sysID: the system ID string * * Do a complete resolution lookup of an External Identifier * * Returns the URI of the resource or NULL if not found, it must be freed * by the caller. */xmlChar *xmlACatalogResolve(xmlCatalogPtr catal, const xmlChar * pubID, const xmlChar * sysID){ xmlChar *ret = NULL;
if (((pubID == NULL) && (sysID == NULL)) || (catal == NULL)) return (NULL);
if (xmlDebugCatalogs) { if ((pubID != NULL) && (sysID != NULL)) { xmlGenericError(xmlGenericErrorContext, "Resolve: pubID %s sysID %s\n", pubID, sysID); } else if (pubID != NULL) { xmlGenericError(xmlGenericErrorContext, "Resolve: pubID %s\n", pubID); } else { xmlGenericError(xmlGenericErrorContext, "Resolve: sysID %s\n", sysID); } }
if (catal->type == XML_XML_CATALOG_TYPE) { ret = xmlCatalogListXMLResolve(catal->xml, pubID, sysID); if (ret == XML_CATAL_BREAK) ret = NULL; } else { const xmlChar *sgml;
sgml = xmlCatalogSGMLResolve(catal, pubID, sysID); if (sgml != NULL) ret = xmlStrdup(sgml); } return (ret);}
/** * xmlACatalogResolveURI: * @catal: a Catalog * @URI: the URI * * Do a complete resolution lookup of an URI * * Returns the URI of the resource or NULL if not found, it must be freed * by the caller. */xmlChar *xmlACatalogResolveURI(xmlCatalogPtr catal, const xmlChar *URI) { xmlChar *ret = NULL;
if ((URI == NULL) || (catal == NULL)) return(NULL);
if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Resolve URI %s\n", URI);
if (catal->type == XML_XML_CATALOG_TYPE) { ret = xmlCatalogListXMLResolveURI(catal->xml, URI); if (ret == XML_CATAL_BREAK) ret = NULL; } else { const xmlChar *sgml;
sgml = xmlCatalogSGMLResolve(catal, NULL, URI); if (sgml != NULL) ret = xmlStrdup(sgml); } return(ret);}
#ifdef LIBXML_OUTPUT_ENABLED/** * xmlACatalogDump: * @catal: a Catalog * @out: the file. * * Dump the given catalog to the given file. */voidxmlACatalogDump(xmlCatalogPtr catal, FILE *out) { if ((out == NULL) || (catal == NULL)) return;
if (catal->type == XML_XML_CATALOG_TYPE) { xmlDumpXMLCatalog(out, catal->xml); } else { xmlHashScan(catal->sgml, xmlCatalogDumpEntry, out); }}#endif /* LIBXML_OUTPUT_ENABLED */
/** * xmlACatalogAdd: * @catal: a Catalog * @type: the type of record to add to the catalog * @orig: the system, public or prefix to match * @replace: the replacement value for the match * * Add an entry in the catalog, it may overwrite existing but * different entries. * * Returns 0 if successful, -1 otherwise */intxmlACatalogAdd(xmlCatalogPtr catal, const xmlChar * type, const xmlChar * orig, const xmlChar * replace){ int res = -1;
if (catal == NULL) return(-1);
if (catal->type == XML_XML_CATALOG_TYPE) { res = xmlAddXMLCatalog(catal->xml, type, orig, replace); } else { xmlCatalogEntryType cattype;
cattype = xmlGetSGMLCatalogEntryType(type); if (cattype != XML_CATA_NONE) { xmlCatalogEntryPtr entry;
entry = xmlNewCatalogEntry(cattype, orig, replace, NULL, XML_CATA_PREFER_NONE, NULL); if (catal->sgml == NULL) catal->sgml = xmlHashCreate(10); res = xmlHashAddEntry(catal->sgml, orig, entry); if (res < 0) xmlFreeCatalogEntry(entry, NULL); } } return (res);}
/** * xmlACatalogRemove: * @catal: a Catalog * @value: the value to remove * * Remove an entry from the catalog * * Returns the number of entries removed if successful, -1 otherwise */intxmlACatalogRemove(xmlCatalogPtr catal, const xmlChar *value) { int res = -1;
if ((catal == NULL) || (value == NULL)) return(-1);
if (catal->type == XML_XML_CATALOG_TYPE) { res = xmlDelXMLCatalog(catal->xml, value); } else { res = xmlHashRemoveEntry(catal->sgml, value, xmlFreeCatalogEntry); if (res == 0) res = 1; } return(res);}
/** * xmlNewCatalog: * @sgml: should this create an SGML catalog * * create a new Catalog. * * Returns the xmlCatalogPtr or NULL in case of error */xmlCatalogPtrxmlNewCatalog(int sgml) { xmlCatalogPtr catal = NULL;
if (sgml) { catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer); if ((catal != NULL) && (catal->sgml == NULL)) catal->sgml = xmlHashCreate(10); } else catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer); return(catal);}
/** * xmlCatalogIsEmpty: * @catal: should this create an SGML catalog * * Check is a catalog is empty * * Returns 1 if the catalog is empty, 0 if not, amd -1 in case of error. */intxmlCatalogIsEmpty(xmlCatalogPtr catal) { if (catal == NULL) return(-1);
if (catal->type == XML_XML_CATALOG_TYPE) { if (catal->xml == NULL) return(1); if ((catal->xml->type != XML_CATA_CATALOG) && (catal->xml->type != XML_CATA_BROKEN_CATALOG)) return(-1); if (catal->xml->children == NULL) return(1); return(0); } else { int res;
if (catal->sgml == NULL) return(1); res = xmlHashSize(catal->sgml); if (res == 0) return(1); if (res < 0) return(-1); } return(0);}
/************************************************************************ * * * Public interfaces manipulating the global shared default catalog * * * ************************************************************************/
/** * xmlInitializeCatalogData: * * Do the catalog initialization only of global data, doesn't try to load * any catalog actually. * this function is not thread safe, catalog initialization should * preferably be done once at startup */static voidxmlInitializeCatalogData(void) { if (xmlCatalogInitialized != 0) return;
if (getenv("XML_DEBUG_CATALOG")) xmlDebugCatalogs = 1; xmlCatalogMutex = xmlNewRMutex();
xmlCatalogInitialized = 1;}/** * xmlInitializeCatalog: * * Do the catalog initialization. * this function is not thread safe, catalog initialization should * preferably be done once at startup */voidxmlInitializeCatalog(void) { if (xmlCatalogInitialized != 0) return;
xmlInitializeCatalogData(); xmlRMutexLock(xmlCatalogMutex);
if (getenv("XML_DEBUG_CATALOG")) xmlDebugCatalogs = 1;
if (xmlDefaultCatalog == NULL) { const char *catalogs; char *path; const char *cur, *paths; xmlCatalogPtr catal; xmlCatalogEntryPtr *nextent;
catalogs = (const char *) getenv("XML_CATALOG_FILES"); if (catalogs == NULL)#if defined(_WIN32) && defined(_MSC_VER) { void* hmodule; hmodule = GetModuleHandleA("libxml2.dll"); if (hmodule == NULL) hmodule = GetModuleHandleA(NULL); if (hmodule != NULL) { char buf[256]; unsigned long len = GetModuleFileNameA(hmodule, buf, 255); if (len != 0) { char* p = &(buf[len]); while (*p != '\\' && p > buf) p--; if (p != buf) { xmlChar* uri; strncpy(p, "\\..\\etc\\catalog", 255 - (p - buf)); uri = xmlCanonicPath((const xmlChar*)buf); if (uri != NULL) { strncpy(XML_XML_DEFAULT_CATALOG, (char* )uri, 255); xmlFree(uri); } } } } catalogs = XML_XML_DEFAULT_CATALOG; }#else catalogs = XML_XML_DEFAULT_CATALOG;#endif
catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer); if (catal != NULL) { /* the XML_CATALOG_FILES envvar is allowed to contain a space-separated list of entries. */ cur = catalogs; nextent = &catal->xml; while (*cur != '\0') { while (xmlIsBlank_ch(*cur)) cur++; if (*cur != 0) { paths = cur; while ((*cur != 0) && (!xmlIsBlank_ch(*cur))) cur++; path = (char *) xmlStrndup((const xmlChar *)paths, cur - paths); if (path != NULL) { *nextent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, NULL, BAD_CAST path, xmlCatalogDefaultPrefer, NULL); if (*nextent != NULL) nextent = &((*nextent)->next); xmlFree(path); } } } xmlDefaultCatalog = catal; } }
xmlRMutexUnlock(xmlCatalogMutex);}
/** * xmlLoadCatalog: * @filename: a file path * * Load the catalog and makes its definitions effective for the default * external entity loader. It will recurse in SGML CATALOG entries. * this function is not thread safe, catalog initialization should * preferably be done once at startup * * Returns 0 in case of success -1 in case of error */intxmlLoadCatalog(const char *filename){ int ret; xmlCatalogPtr catal;
if (!xmlCatalogInitialized) xmlInitializeCatalogData();
xmlRMutexLock(xmlCatalogMutex);
if (xmlDefaultCatalog == NULL) { catal = xmlLoadACatalog(filename); if (catal == NULL) { xmlRMutexUnlock(xmlCatalogMutex); return(-1); }
xmlDefaultCatalog = catal; xmlRMutexUnlock(xmlCatalogMutex); return(0); }
ret = xmlExpandCatalog(xmlDefaultCatalog, filename); xmlRMutexUnlock(xmlCatalogMutex); return(ret);}
/** * xmlLoadCatalogs: * @pathss: a list of directories separated by a colon or a space. * * Load the catalogs and makes their definitions effective for the default * external entity loader. * this function is not thread safe, catalog initialization should * preferably be done once at startup */voidxmlLoadCatalogs(const char *pathss) { const char *cur; const char *paths; xmlChar *path;#ifdef _WIN32 int i, iLen;#endif
if (pathss == NULL) return;
cur = pathss; while (*cur != 0) { while (xmlIsBlank_ch(*cur)) cur++; if (*cur != 0) { paths = cur; while ((*cur != 0) && (*cur != PATH_SEPARATOR) && (!xmlIsBlank_ch(*cur))) cur++; path = xmlStrndup((const xmlChar *)paths, cur - paths); if (path != NULL) {#ifdef _WIN32 iLen = strlen((const char*)path); for(i = 0; i < iLen; i++) { if(path[i] == '\\') { path[i] = '/'; } }#endif xmlLoadCatalog((const char *) path); xmlFree(path); } } while (*cur == PATH_SEPARATOR) cur++; }}
/** * xmlCatalogCleanup: * * Free up all the memory associated with catalogs */voidxmlCatalogCleanup(void) { if (xmlCatalogInitialized == 0) return;
xmlRMutexLock(xmlCatalogMutex); if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Catalogs cleanup\n"); if (xmlCatalogXMLFiles != NULL) xmlHashFree(xmlCatalogXMLFiles, xmlFreeCatalogHashEntryList); xmlCatalogXMLFiles = NULL; if (xmlDefaultCatalog != NULL) xmlFreeCatalog(xmlDefaultCatalog); xmlDefaultCatalog = NULL; xmlDebugCatalogs = 0; xmlCatalogInitialized = 0; xmlRMutexUnlock(xmlCatalogMutex); xmlFreeRMutex(xmlCatalogMutex);}
/** * xmlCatalogResolveSystem: * @sysID: the system ID string * * Try to lookup the catalog resource for a system ID * * Returns the resource if found or NULL otherwise, the value returned * must be freed by the caller. */xmlChar *xmlCatalogResolveSystem(const xmlChar *sysID) { xmlChar *ret;
if (!xmlCatalogInitialized) xmlInitializeCatalog();
ret = xmlACatalogResolveSystem(xmlDefaultCatalog, sysID); return(ret);}
/** * xmlCatalogResolvePublic: * @pubID: the public ID string * * Try to lookup the catalog reference associated to a public ID * * Returns the resource if found or NULL otherwise, the value returned * must be freed by the caller. */xmlChar *xmlCatalogResolvePublic(const xmlChar *pubID) { xmlChar *ret;
if (!xmlCatalogInitialized) xmlInitializeCatalog();
ret = xmlACatalogResolvePublic(xmlDefaultCatalog, pubID); return(ret);}
/** * xmlCatalogResolve: * @pubID: the public ID string * @sysID: the system ID string * * Do a complete resolution lookup of an External Identifier * * Returns the URI of the resource or NULL if not found, it must be freed * by the caller. */xmlChar *xmlCatalogResolve(const xmlChar *pubID, const xmlChar *sysID) { xmlChar *ret;
if (!xmlCatalogInitialized) xmlInitializeCatalog();
ret = xmlACatalogResolve(xmlDefaultCatalog, pubID, sysID); return(ret);}
/** * xmlCatalogResolveURI: * @URI: the URI * * Do a complete resolution lookup of an URI * * Returns the URI of the resource or NULL if not found, it must be freed * by the caller. */xmlChar *xmlCatalogResolveURI(const xmlChar *URI) { xmlChar *ret;
if (!xmlCatalogInitialized) xmlInitializeCatalog();
ret = xmlACatalogResolveURI(xmlDefaultCatalog, URI); return(ret);}
#ifdef LIBXML_OUTPUT_ENABLED/** * xmlCatalogDump: * @out: the file. * * Dump all the global catalog content to the given file. */voidxmlCatalogDump(FILE *out) { if (out == NULL) return;
if (!xmlCatalogInitialized) xmlInitializeCatalog();
xmlACatalogDump(xmlDefaultCatalog, out);}#endif /* LIBXML_OUTPUT_ENABLED */
/** * xmlCatalogAdd: * @type: the type of record to add to the catalog * @orig: the system, public or prefix to match * @replace: the replacement value for the match * * Add an entry in the catalog, it may overwrite existing but * different entries. * If called before any other catalog routine, allows to override the * default shared catalog put in place by xmlInitializeCatalog(); * * Returns 0 if successful, -1 otherwise */intxmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace) { int res = -1;
if (!xmlCatalogInitialized) xmlInitializeCatalogData();
xmlRMutexLock(xmlCatalogMutex); /* * Specific case where one want to override the default catalog * put in place by xmlInitializeCatalog(); */ if ((xmlDefaultCatalog == NULL) && (xmlStrEqual(type, BAD_CAST "catalog"))) { xmlDefaultCatalog = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer); if (xmlDefaultCatalog != NULL) { xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, orig, NULL, xmlCatalogDefaultPrefer, NULL); } xmlRMutexUnlock(xmlCatalogMutex); return(0); }
res = xmlACatalogAdd(xmlDefaultCatalog, type, orig, replace); xmlRMutexUnlock(xmlCatalogMutex); return(res);}
/** * xmlCatalogRemove: * @value: the value to remove * * Remove an entry from the catalog * * Returns the number of entries removed if successful, -1 otherwise */intxmlCatalogRemove(const xmlChar *value) { int res;
if (!xmlCatalogInitialized) xmlInitializeCatalog();
xmlRMutexLock(xmlCatalogMutex); res = xmlACatalogRemove(xmlDefaultCatalog, value); xmlRMutexUnlock(xmlCatalogMutex); return(res);}
/** * xmlCatalogConvert: * * Convert all the SGML catalog entries as XML ones * * Returns the number of entries converted if successful, -1 otherwise */intxmlCatalogConvert(void) { int res = -1;
if (!xmlCatalogInitialized) xmlInitializeCatalog();
xmlRMutexLock(xmlCatalogMutex); res = xmlConvertSGMLCatalog(xmlDefaultCatalog); xmlRMutexUnlock(xmlCatalogMutex); return(res);}
/************************************************************************ * * * Public interface manipulating the common preferences * * * ************************************************************************/
/** * xmlCatalogGetDefaults: * * Used to get the user preference w.r.t. to what catalogs should * be accepted * * Returns the current xmlCatalogAllow value */xmlCatalogAllowxmlCatalogGetDefaults(void) { return(xmlCatalogDefaultAllow);}
/** * xmlCatalogSetDefaults: * @allow: what catalogs should be accepted * * Used to set the user preference w.r.t. to what catalogs should * be accepted */voidxmlCatalogSetDefaults(xmlCatalogAllow allow) { if (xmlDebugCatalogs) { switch (allow) { case XML_CATA_ALLOW_NONE: xmlGenericError(xmlGenericErrorContext, "Disabling catalog usage\n"); break; case XML_CATA_ALLOW_GLOBAL: xmlGenericError(xmlGenericErrorContext, "Allowing only global catalogs\n"); break; case XML_CATA_ALLOW_DOCUMENT: xmlGenericError(xmlGenericErrorContext, "Allowing only catalogs from the document\n"); break; case XML_CATA_ALLOW_ALL: xmlGenericError(xmlGenericErrorContext, "Allowing all catalogs\n"); break; } } xmlCatalogDefaultAllow = allow;}
/** * xmlCatalogSetDefaultPrefer: * @prefer: the default preference for delegation * * Allows to set the preference between public and system for deletion * in XML Catalog resolution. C.f. section 4.1.1 of the spec * Values accepted are XML_CATA_PREFER_PUBLIC or XML_CATA_PREFER_SYSTEM * * Returns the previous value of the default preference for delegation */xmlCatalogPreferxmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer) { xmlCatalogPrefer ret = xmlCatalogDefaultPrefer;
if (prefer == XML_CATA_PREFER_NONE) return(ret);
if (xmlDebugCatalogs) { switch (prefer) { case XML_CATA_PREFER_PUBLIC: xmlGenericError(xmlGenericErrorContext, "Setting catalog preference to PUBLIC\n"); break; case XML_CATA_PREFER_SYSTEM: xmlGenericError(xmlGenericErrorContext, "Setting catalog preference to SYSTEM\n"); break; default: return(ret); } } xmlCatalogDefaultPrefer = prefer; return(ret);}
/** * xmlCatalogSetDebug: * @level: the debug level of catalogs required * * Used to set the debug level for catalog operation, 0 disable * debugging, 1 enable it * * Returns the previous value of the catalog debugging level */intxmlCatalogSetDebug(int level) { int ret = xmlDebugCatalogs;
if (level <= 0) xmlDebugCatalogs = 0; else xmlDebugCatalogs = level; return(ret);}
/************************************************************************ * * * Minimal interfaces used for per-document catalogs by the parser * * * ************************************************************************/
/** * xmlCatalogFreeLocal: * @catalogs: a document's list of catalogs * * Free up the memory associated to the catalog list */voidxmlCatalogFreeLocal(void *catalogs) { xmlCatalogEntryPtr catal;
if (!xmlCatalogInitialized) xmlInitializeCatalog();
catal = (xmlCatalogEntryPtr) catalogs; if (catal != NULL) xmlFreeCatalogEntryList(catal);}
/** * xmlCatalogAddLocal: * @catalogs: a document's list of catalogs * @URL: the URL to a new local catalog * * Add the new entry to the catalog list * * Returns the updated list */void *xmlCatalogAddLocal(void *catalogs, const xmlChar *URL) { xmlCatalogEntryPtr catal, add;
if (!xmlCatalogInitialized) xmlInitializeCatalog();
if (URL == NULL) return(catalogs);
if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Adding document catalog %s\n", URL);
add = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, URL, NULL, xmlCatalogDefaultPrefer, NULL); if (add == NULL) return(catalogs);
catal = (xmlCatalogEntryPtr) catalogs; if (catal == NULL) return((void *) add);
while (catal->next != NULL) catal = catal->next; catal->next = add; return(catalogs);}
/** * xmlCatalogLocalResolve: * @catalogs: a document's list of catalogs * @pubID: the public ID string * @sysID: the system ID string * * Do a complete resolution lookup of an External Identifier using a * document's private catalog list * * Returns the URI of the resource or NULL if not found, it must be freed * by the caller. */xmlChar *xmlCatalogLocalResolve(void *catalogs, const xmlChar *pubID, const xmlChar *sysID) { xmlCatalogEntryPtr catal; xmlChar *ret;
if (!xmlCatalogInitialized) xmlInitializeCatalog();
if ((pubID == NULL) && (sysID == NULL)) return(NULL);
if (xmlDebugCatalogs) { if ((pubID != NULL) && (sysID != NULL)) { xmlGenericError(xmlGenericErrorContext, "Local Resolve: pubID %s sysID %s\n", pubID, sysID); } else if (pubID != NULL) { xmlGenericError(xmlGenericErrorContext, "Local Resolve: pubID %s\n", pubID); } else { xmlGenericError(xmlGenericErrorContext, "Local Resolve: sysID %s\n", sysID); } }
catal = (xmlCatalogEntryPtr) catalogs; if (catal == NULL) return(NULL); ret = xmlCatalogListXMLResolve(catal, pubID, sysID); if ((ret != NULL) && (ret != XML_CATAL_BREAK)) return(ret); return(NULL);}
/** * xmlCatalogLocalResolveURI: * @catalogs: a document's list of catalogs * @URI: the URI * * Do a complete resolution lookup of an URI using a * document's private catalog list * * Returns the URI of the resource or NULL if not found, it must be freed * by the caller. */xmlChar *xmlCatalogLocalResolveURI(void *catalogs, const xmlChar *URI) { xmlCatalogEntryPtr catal; xmlChar *ret;
if (!xmlCatalogInitialized) xmlInitializeCatalog();
if (URI == NULL) return(NULL);
if (xmlDebugCatalogs) xmlGenericError(xmlGenericErrorContext, "Resolve URI %s\n", URI);
catal = (xmlCatalogEntryPtr) catalogs; if (catal == NULL) return(NULL); ret = xmlCatalogListXMLResolveURI(catal, URI); if ((ret != NULL) && (ret != XML_CATAL_BREAK)) return(ret); return(NULL);}
/************************************************************************ * * * Deprecated interfaces * * * ************************************************************************//** * xmlCatalogGetSystem: * @sysID: the system ID string * * Try to lookup the catalog reference associated to a system ID * DEPRECATED, use xmlCatalogResolveSystem() * * Returns the resource if found or NULL otherwise. */const xmlChar *xmlCatalogGetSystem(const xmlChar *sysID) { xmlChar *ret; static xmlChar result[1000]; static int msg = 0;
if (!xmlCatalogInitialized) xmlInitializeCatalog();
if (msg == 0) { xmlGenericError(xmlGenericErrorContext, "Use of deprecated xmlCatalogGetSystem() call\n"); msg++; }
if (sysID == NULL) return(NULL);
/* * Check first the XML catalogs */ if (xmlDefaultCatalog != NULL) { ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, NULL, sysID); if ((ret != NULL) && (ret != XML_CATAL_BREAK)) { snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret); result[sizeof(result) - 1] = 0; return(result); } }
if (xmlDefaultCatalog != NULL) return(xmlCatalogGetSGMLSystem(xmlDefaultCatalog->sgml, sysID)); return(NULL);}
/** * xmlCatalogGetPublic: * @pubID: the public ID string * * Try to lookup the catalog reference associated to a public ID * DEPRECATED, use xmlCatalogResolvePublic() * * Returns the resource if found or NULL otherwise. */const xmlChar *xmlCatalogGetPublic(const xmlChar *pubID) { xmlChar *ret; static xmlChar result[1000]; static int msg = 0;
if (!xmlCatalogInitialized) xmlInitializeCatalog();
if (msg == 0) { xmlGenericError(xmlGenericErrorContext, "Use of deprecated xmlCatalogGetPublic() call\n"); msg++; }
if (pubID == NULL) return(NULL);
/* * Check first the XML catalogs */ if (xmlDefaultCatalog != NULL) { ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, pubID, NULL); if ((ret != NULL) && (ret != XML_CATAL_BREAK)) { snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret); result[sizeof(result) - 1] = 0; return(result); } }
if (xmlDefaultCatalog != NULL) return(xmlCatalogGetSGMLPublic(xmlDefaultCatalog->sgml, pubID)); return(NULL);}
#endif /* LIBXML_CATALOG_ENABLED */