valid.c 185 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960
  1. /*
  2. * valid.c : part of the code use to do the DTD handling and the validity
  3. * checking
  4. *
  5. * See Copyright for the status of this software.
  6. *
  7. * daniel@veillard.com
  8. */
  9. #define IN_LIBXML
  10. #include "libxml.h"
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <libxml/xmlmemory.h>
  14. #include <libxml/hash.h>
  15. #include <libxml/uri.h>
  16. #include <libxml/valid.h>
  17. #include <libxml/parser.h>
  18. #include <libxml/parserInternals.h>
  19. #include <libxml/xmlerror.h>
  20. #include <libxml/list.h>
  21. #include "private/error.h"
  22. #include "private/parser.h"
  23. static xmlElementPtr
  24. xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
  25. int create);
  26. #define TODO \
  27. xmlGenericError(xmlGenericErrorContext, \
  28. "Unimplemented block at %s:%d\n", \
  29. __FILE__, __LINE__);
  30. #ifdef LIBXML_VALID_ENABLED
  31. static int
  32. xmlValidateAttributeValueInternal(xmlDocPtr doc, xmlAttributeType type,
  33. const xmlChar *value);
  34. #endif
  35. /************************************************************************
  36. * *
  37. * Error handling routines *
  38. * *
  39. ************************************************************************/
  40. /**
  41. * xmlVErrMemory:
  42. * @ctxt: an XML validation parser context
  43. * @extra: extra information
  44. *
  45. * Handle an out of memory error
  46. */
  47. static void
  48. xmlVErrMemory(xmlValidCtxtPtr ctxt, const char *extra)
  49. {
  50. xmlGenericErrorFunc channel = NULL;
  51. xmlParserCtxtPtr pctxt = NULL;
  52. void *data = NULL;
  53. if (ctxt != NULL) {
  54. channel = ctxt->error;
  55. data = ctxt->userData;
  56. /* Look up flag to detect if it is part of a parsing
  57. context */
  58. if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
  59. pctxt = ctxt->userData;
  60. }
  61. }
  62. if (extra)
  63. __xmlRaiseError(NULL, channel, data,
  64. pctxt, NULL, XML_FROM_VALID, XML_ERR_NO_MEMORY,
  65. XML_ERR_FATAL, NULL, 0, extra, NULL, NULL, 0, 0,
  66. "Memory allocation failed : %s\n", extra);
  67. else
  68. __xmlRaiseError(NULL, channel, data,
  69. pctxt, NULL, XML_FROM_VALID, XML_ERR_NO_MEMORY,
  70. XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0,
  71. "Memory allocation failed\n");
  72. }
  73. /**
  74. * xmlErrValid:
  75. * @ctxt: an XML validation parser context
  76. * @error: the error number
  77. * @extra: extra information
  78. *
  79. * Handle a validation error
  80. */
  81. static void LIBXML_ATTR_FORMAT(3,0)
  82. xmlErrValid(xmlValidCtxtPtr ctxt, xmlParserErrors error,
  83. const char *msg, const char *extra)
  84. {
  85. xmlGenericErrorFunc channel = NULL;
  86. xmlParserCtxtPtr pctxt = NULL;
  87. void *data = NULL;
  88. if (ctxt != NULL) {
  89. channel = ctxt->error;
  90. data = ctxt->userData;
  91. /* Look up flag to detect if it is part of a parsing
  92. context */
  93. if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
  94. pctxt = ctxt->userData;
  95. }
  96. }
  97. if (extra)
  98. __xmlRaiseError(NULL, channel, data,
  99. pctxt, NULL, XML_FROM_VALID, error,
  100. XML_ERR_ERROR, NULL, 0, extra, NULL, NULL, 0, 0,
  101. msg, extra);
  102. else
  103. __xmlRaiseError(NULL, channel, data,
  104. pctxt, NULL, XML_FROM_VALID, error,
  105. XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
  106. "%s", msg);
  107. }
  108. #if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
  109. /**
  110. * xmlErrValidNode:
  111. * @ctxt: an XML validation parser context
  112. * @node: the node raising the error
  113. * @error: the error number
  114. * @str1: extra information
  115. * @str2: extra information
  116. * @str3: extra information
  117. *
  118. * Handle a validation error, provide contextual information
  119. */
  120. static void LIBXML_ATTR_FORMAT(4,0)
  121. xmlErrValidNode(xmlValidCtxtPtr ctxt,
  122. xmlNodePtr node, xmlParserErrors error,
  123. const char *msg, const xmlChar * str1,
  124. const xmlChar * str2, const xmlChar * str3)
  125. {
  126. xmlStructuredErrorFunc schannel = NULL;
  127. xmlGenericErrorFunc channel = NULL;
  128. xmlParserCtxtPtr pctxt = NULL;
  129. void *data = NULL;
  130. if (ctxt != NULL) {
  131. channel = ctxt->error;
  132. data = ctxt->userData;
  133. /* Look up flag to detect if it is part of a parsing
  134. context */
  135. if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
  136. pctxt = ctxt->userData;
  137. }
  138. }
  139. __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error,
  140. XML_ERR_ERROR, NULL, 0,
  141. (const char *) str1,
  142. (const char *) str2,
  143. (const char *) str3, 0, 0, msg, str1, str2, str3);
  144. }
  145. #endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */
  146. #ifdef LIBXML_VALID_ENABLED
  147. /**
  148. * xmlErrValidNodeNr:
  149. * @ctxt: an XML validation parser context
  150. * @node: the node raising the error
  151. * @error: the error number
  152. * @str1: extra information
  153. * @int2: extra information
  154. * @str3: extra information
  155. *
  156. * Handle a validation error, provide contextual information
  157. */
  158. static void LIBXML_ATTR_FORMAT(4,0)
  159. xmlErrValidNodeNr(xmlValidCtxtPtr ctxt,
  160. xmlNodePtr node, xmlParserErrors error,
  161. const char *msg, const xmlChar * str1,
  162. int int2, const xmlChar * str3)
  163. {
  164. xmlStructuredErrorFunc schannel = NULL;
  165. xmlGenericErrorFunc channel = NULL;
  166. xmlParserCtxtPtr pctxt = NULL;
  167. void *data = NULL;
  168. if (ctxt != NULL) {
  169. channel = ctxt->error;
  170. data = ctxt->userData;
  171. /* Look up flag to detect if it is part of a parsing
  172. context */
  173. if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
  174. pctxt = ctxt->userData;
  175. }
  176. }
  177. __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error,
  178. XML_ERR_ERROR, NULL, 0,
  179. (const char *) str1,
  180. (const char *) str3,
  181. NULL, int2, 0, msg, str1, int2, str3);
  182. }
  183. /**
  184. * xmlErrValidWarning:
  185. * @ctxt: an XML validation parser context
  186. * @node: the node raising the error
  187. * @error: the error number
  188. * @str1: extra information
  189. * @str2: extra information
  190. * @str3: extra information
  191. *
  192. * Handle a validation error, provide contextual information
  193. */
  194. static void LIBXML_ATTR_FORMAT(4,0)
  195. xmlErrValidWarning(xmlValidCtxtPtr ctxt,
  196. xmlNodePtr node, xmlParserErrors error,
  197. const char *msg, const xmlChar * str1,
  198. const xmlChar * str2, const xmlChar * str3)
  199. {
  200. xmlStructuredErrorFunc schannel = NULL;
  201. xmlGenericErrorFunc channel = NULL;
  202. xmlParserCtxtPtr pctxt = NULL;
  203. void *data = NULL;
  204. if (ctxt != NULL) {
  205. channel = ctxt->warning;
  206. data = ctxt->userData;
  207. /* Look up flag to detect if it is part of a parsing
  208. context */
  209. if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
  210. pctxt = ctxt->userData;
  211. }
  212. }
  213. __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error,
  214. XML_ERR_WARNING, NULL, 0,
  215. (const char *) str1,
  216. (const char *) str2,
  217. (const char *) str3, 0, 0, msg, str1, str2, str3);
  218. }
  219. #ifdef LIBXML_REGEXP_ENABLED
  220. /*
  221. * If regexp are enabled we can do continuous validation without the
  222. * need of a tree to validate the content model. this is done in each
  223. * callbacks.
  224. * Each xmlValidState represent the validation state associated to the
  225. * set of nodes currently open from the document root to the current element.
  226. */
  227. typedef struct _xmlValidState {
  228. xmlElementPtr elemDecl; /* pointer to the content model */
  229. xmlNodePtr node; /* pointer to the current node */
  230. xmlRegExecCtxtPtr exec; /* regexp runtime */
  231. } _xmlValidState;
  232. static int
  233. vstateVPush(xmlValidCtxtPtr ctxt, xmlElementPtr elemDecl, xmlNodePtr node) {
  234. if ((ctxt->vstateMax == 0) || (ctxt->vstateTab == NULL)) {
  235. ctxt->vstateMax = 10;
  236. ctxt->vstateTab = (xmlValidState *) xmlMalloc(ctxt->vstateMax *
  237. sizeof(ctxt->vstateTab[0]));
  238. if (ctxt->vstateTab == NULL) {
  239. xmlVErrMemory(ctxt, "malloc failed");
  240. return(-1);
  241. }
  242. }
  243. if (ctxt->vstateNr >= ctxt->vstateMax) {
  244. xmlValidState *tmp;
  245. tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
  246. 2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
  247. if (tmp == NULL) {
  248. xmlVErrMemory(ctxt, "realloc failed");
  249. return(-1);
  250. }
  251. ctxt->vstateMax *= 2;
  252. ctxt->vstateTab = tmp;
  253. }
  254. ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr];
  255. ctxt->vstateTab[ctxt->vstateNr].elemDecl = elemDecl;
  256. ctxt->vstateTab[ctxt->vstateNr].node = node;
  257. if ((elemDecl != NULL) && (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT)) {
  258. if (elemDecl->contModel == NULL)
  259. xmlValidBuildContentModel(ctxt, elemDecl);
  260. if (elemDecl->contModel != NULL) {
  261. ctxt->vstateTab[ctxt->vstateNr].exec =
  262. xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL);
  263. } else {
  264. ctxt->vstateTab[ctxt->vstateNr].exec = NULL;
  265. xmlErrValidNode(ctxt, (xmlNodePtr) elemDecl,
  266. XML_ERR_INTERNAL_ERROR,
  267. "Failed to build content model regexp for %s\n",
  268. node->name, NULL, NULL);
  269. }
  270. }
  271. return(ctxt->vstateNr++);
  272. }
  273. static int
  274. vstateVPop(xmlValidCtxtPtr ctxt) {
  275. xmlElementPtr elemDecl;
  276. if (ctxt->vstateNr < 1) return(-1);
  277. ctxt->vstateNr--;
  278. elemDecl = ctxt->vstateTab[ctxt->vstateNr].elemDecl;
  279. ctxt->vstateTab[ctxt->vstateNr].elemDecl = NULL;
  280. ctxt->vstateTab[ctxt->vstateNr].node = NULL;
  281. if ((elemDecl != NULL) && (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT)) {
  282. xmlRegFreeExecCtxt(ctxt->vstateTab[ctxt->vstateNr].exec);
  283. }
  284. ctxt->vstateTab[ctxt->vstateNr].exec = NULL;
  285. if (ctxt->vstateNr >= 1)
  286. ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr - 1];
  287. else
  288. ctxt->vstate = NULL;
  289. return(ctxt->vstateNr);
  290. }
  291. #else /* not LIBXML_REGEXP_ENABLED */
  292. /*
  293. * If regexp are not enabled, it uses a home made algorithm less
  294. * complex and easier to
  295. * debug/maintain than a generic NFA -> DFA state based algo. The
  296. * only restriction is on the deepness of the tree limited by the
  297. * size of the occurs bitfield
  298. *
  299. * this is the content of a saved state for rollbacks
  300. */
  301. #define ROLLBACK_OR 0
  302. #define ROLLBACK_PARENT 1
  303. typedef struct _xmlValidState {
  304. xmlElementContentPtr cont; /* pointer to the content model subtree */
  305. xmlNodePtr node; /* pointer to the current node in the list */
  306. long occurs;/* bitfield for multiple occurrences */
  307. unsigned char depth; /* current depth in the overall tree */
  308. unsigned char state; /* ROLLBACK_XXX */
  309. } _xmlValidState;
  310. #define MAX_RECURSE 25000
  311. #define MAX_DEPTH ((sizeof(_xmlValidState.occurs)) * 8)
  312. #define CONT ctxt->vstate->cont
  313. #define NODE ctxt->vstate->node
  314. #define DEPTH ctxt->vstate->depth
  315. #define OCCURS ctxt->vstate->occurs
  316. #define STATE ctxt->vstate->state
  317. #define OCCURRENCE (ctxt->vstate->occurs & (1 << DEPTH))
  318. #define PARENT_OCCURRENCE (ctxt->vstate->occurs & ((1 << DEPTH) - 1))
  319. #define SET_OCCURRENCE ctxt->vstate->occurs |= (1 << DEPTH)
  320. #define RESET_OCCURRENCE ctxt->vstate->occurs &= ((1 << DEPTH) - 1)
  321. static int
  322. vstateVPush(xmlValidCtxtPtr ctxt, xmlElementContentPtr cont,
  323. xmlNodePtr node, unsigned char depth, long occurs,
  324. unsigned char state) {
  325. int i = ctxt->vstateNr - 1;
  326. if (ctxt->vstateNr > MAX_RECURSE) {
  327. return(-1);
  328. }
  329. if (ctxt->vstateTab == NULL) {
  330. ctxt->vstateMax = 8;
  331. ctxt->vstateTab = (xmlValidState *) xmlMalloc(
  332. ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
  333. if (ctxt->vstateTab == NULL) {
  334. xmlVErrMemory(ctxt, "malloc failed");
  335. return(-1);
  336. }
  337. }
  338. if (ctxt->vstateNr >= ctxt->vstateMax) {
  339. xmlValidState *tmp;
  340. tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
  341. 2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
  342. if (tmp == NULL) {
  343. xmlVErrMemory(ctxt, "malloc failed");
  344. return(-1);
  345. }
  346. ctxt->vstateMax *= 2;
  347. ctxt->vstateTab = tmp;
  348. ctxt->vstate = &ctxt->vstateTab[0];
  349. }
  350. /*
  351. * Don't push on the stack a state already here
  352. */
  353. if ((i >= 0) && (ctxt->vstateTab[i].cont == cont) &&
  354. (ctxt->vstateTab[i].node == node) &&
  355. (ctxt->vstateTab[i].depth == depth) &&
  356. (ctxt->vstateTab[i].occurs == occurs) &&
  357. (ctxt->vstateTab[i].state == state))
  358. return(ctxt->vstateNr);
  359. ctxt->vstateTab[ctxt->vstateNr].cont = cont;
  360. ctxt->vstateTab[ctxt->vstateNr].node = node;
  361. ctxt->vstateTab[ctxt->vstateNr].depth = depth;
  362. ctxt->vstateTab[ctxt->vstateNr].occurs = occurs;
  363. ctxt->vstateTab[ctxt->vstateNr].state = state;
  364. return(ctxt->vstateNr++);
  365. }
  366. static int
  367. vstateVPop(xmlValidCtxtPtr ctxt) {
  368. if (ctxt->vstateNr <= 1) return(-1);
  369. ctxt->vstateNr--;
  370. ctxt->vstate = &ctxt->vstateTab[0];
  371. ctxt->vstate->cont = ctxt->vstateTab[ctxt->vstateNr].cont;
  372. ctxt->vstate->node = ctxt->vstateTab[ctxt->vstateNr].node;
  373. ctxt->vstate->depth = ctxt->vstateTab[ctxt->vstateNr].depth;
  374. ctxt->vstate->occurs = ctxt->vstateTab[ctxt->vstateNr].occurs;
  375. ctxt->vstate->state = ctxt->vstateTab[ctxt->vstateNr].state;
  376. return(ctxt->vstateNr);
  377. }
  378. #endif /* LIBXML_REGEXP_ENABLED */
  379. static int
  380. nodeVPush(xmlValidCtxtPtr ctxt, xmlNodePtr value)
  381. {
  382. if (ctxt->nodeMax <= 0) {
  383. ctxt->nodeMax = 4;
  384. ctxt->nodeTab =
  385. (xmlNodePtr *) xmlMalloc(ctxt->nodeMax *
  386. sizeof(ctxt->nodeTab[0]));
  387. if (ctxt->nodeTab == NULL) {
  388. xmlVErrMemory(ctxt, "malloc failed");
  389. ctxt->nodeMax = 0;
  390. return (0);
  391. }
  392. }
  393. if (ctxt->nodeNr >= ctxt->nodeMax) {
  394. xmlNodePtr *tmp;
  395. tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
  396. ctxt->nodeMax * 2 * sizeof(ctxt->nodeTab[0]));
  397. if (tmp == NULL) {
  398. xmlVErrMemory(ctxt, "realloc failed");
  399. return (0);
  400. }
  401. ctxt->nodeMax *= 2;
  402. ctxt->nodeTab = tmp;
  403. }
  404. ctxt->nodeTab[ctxt->nodeNr] = value;
  405. ctxt->node = value;
  406. return (ctxt->nodeNr++);
  407. }
  408. static xmlNodePtr
  409. nodeVPop(xmlValidCtxtPtr ctxt)
  410. {
  411. xmlNodePtr ret;
  412. if (ctxt->nodeNr <= 0)
  413. return (NULL);
  414. ctxt->nodeNr--;
  415. if (ctxt->nodeNr > 0)
  416. ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
  417. else
  418. ctxt->node = NULL;
  419. ret = ctxt->nodeTab[ctxt->nodeNr];
  420. ctxt->nodeTab[ctxt->nodeNr] = NULL;
  421. return (ret);
  422. }
  423. /* TODO: use hash table for accesses to elem and attribute definitions */
  424. #define CHECK_DTD \
  425. if (doc == NULL) return(0); \
  426. else if ((doc->intSubset == NULL) && \
  427. (doc->extSubset == NULL)) return(0)
  428. #ifdef LIBXML_REGEXP_ENABLED
  429. /************************************************************************
  430. * *
  431. * Content model validation based on the regexps *
  432. * *
  433. ************************************************************************/
  434. /**
  435. * xmlValidBuildAContentModel:
  436. * @content: the content model
  437. * @ctxt: the schema parser context
  438. * @name: the element name whose content is being built
  439. *
  440. * Generate the automata sequence needed for that type
  441. *
  442. * Returns 1 if successful or 0 in case of error.
  443. */
  444. static int
  445. xmlValidBuildAContentModel(xmlElementContentPtr content,
  446. xmlValidCtxtPtr ctxt,
  447. const xmlChar *name) {
  448. if (content == NULL) {
  449. xmlErrValidNode(ctxt, NULL, XML_ERR_INTERNAL_ERROR,
  450. "Found NULL content in content model of %s\n",
  451. name, NULL, NULL);
  452. return(0);
  453. }
  454. switch (content->type) {
  455. case XML_ELEMENT_CONTENT_PCDATA:
  456. xmlErrValidNode(ctxt, NULL, XML_ERR_INTERNAL_ERROR,
  457. "Found PCDATA in content model of %s\n",
  458. name, NULL, NULL);
  459. return(0);
  460. break;
  461. case XML_ELEMENT_CONTENT_ELEMENT: {
  462. xmlAutomataStatePtr oldstate = ctxt->state;
  463. xmlChar fn[50];
  464. xmlChar *fullname;
  465. fullname = xmlBuildQName(content->name, content->prefix, fn, 50);
  466. if (fullname == NULL) {
  467. xmlVErrMemory(ctxt, "Building content model");
  468. return(0);
  469. }
  470. switch (content->ocur) {
  471. case XML_ELEMENT_CONTENT_ONCE:
  472. ctxt->state = xmlAutomataNewTransition(ctxt->am,
  473. ctxt->state, NULL, fullname, NULL);
  474. break;
  475. case XML_ELEMENT_CONTENT_OPT:
  476. ctxt->state = xmlAutomataNewTransition(ctxt->am,
  477. ctxt->state, NULL, fullname, NULL);
  478. xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
  479. break;
  480. case XML_ELEMENT_CONTENT_PLUS:
  481. ctxt->state = xmlAutomataNewTransition(ctxt->am,
  482. ctxt->state, NULL, fullname, NULL);
  483. xmlAutomataNewTransition(ctxt->am, ctxt->state,
  484. ctxt->state, fullname, NULL);
  485. break;
  486. case XML_ELEMENT_CONTENT_MULT:
  487. ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
  488. ctxt->state, NULL);
  489. xmlAutomataNewTransition(ctxt->am,
  490. ctxt->state, ctxt->state, fullname, NULL);
  491. break;
  492. }
  493. if ((fullname != fn) && (fullname != content->name))
  494. xmlFree(fullname);
  495. break;
  496. }
  497. case XML_ELEMENT_CONTENT_SEQ: {
  498. xmlAutomataStatePtr oldstate, oldend;
  499. xmlElementContentOccur ocur;
  500. /*
  501. * Simply iterate over the content
  502. */
  503. oldstate = ctxt->state;
  504. ocur = content->ocur;
  505. if (ocur != XML_ELEMENT_CONTENT_ONCE) {
  506. ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
  507. oldstate = ctxt->state;
  508. }
  509. do {
  510. xmlValidBuildAContentModel(content->c1, ctxt, name);
  511. content = content->c2;
  512. } while ((content->type == XML_ELEMENT_CONTENT_SEQ) &&
  513. (content->ocur == XML_ELEMENT_CONTENT_ONCE));
  514. xmlValidBuildAContentModel(content, ctxt, name);
  515. oldend = ctxt->state;
  516. ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL);
  517. switch (ocur) {
  518. case XML_ELEMENT_CONTENT_ONCE:
  519. break;
  520. case XML_ELEMENT_CONTENT_OPT:
  521. xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
  522. break;
  523. case XML_ELEMENT_CONTENT_MULT:
  524. xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
  525. xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
  526. break;
  527. case XML_ELEMENT_CONTENT_PLUS:
  528. xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
  529. break;
  530. }
  531. break;
  532. }
  533. case XML_ELEMENT_CONTENT_OR: {
  534. xmlAutomataStatePtr oldstate, oldend;
  535. xmlElementContentOccur ocur;
  536. ocur = content->ocur;
  537. if ((ocur == XML_ELEMENT_CONTENT_PLUS) ||
  538. (ocur == XML_ELEMENT_CONTENT_MULT)) {
  539. ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
  540. ctxt->state, NULL);
  541. }
  542. oldstate = ctxt->state;
  543. oldend = xmlAutomataNewState(ctxt->am);
  544. /*
  545. * iterate over the subtypes and remerge the end with an
  546. * epsilon transition
  547. */
  548. do {
  549. ctxt->state = oldstate;
  550. xmlValidBuildAContentModel(content->c1, ctxt, name);
  551. xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend);
  552. content = content->c2;
  553. } while ((content->type == XML_ELEMENT_CONTENT_OR) &&
  554. (content->ocur == XML_ELEMENT_CONTENT_ONCE));
  555. ctxt->state = oldstate;
  556. xmlValidBuildAContentModel(content, ctxt, name);
  557. xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend);
  558. ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL);
  559. switch (ocur) {
  560. case XML_ELEMENT_CONTENT_ONCE:
  561. break;
  562. case XML_ELEMENT_CONTENT_OPT:
  563. xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
  564. break;
  565. case XML_ELEMENT_CONTENT_MULT:
  566. xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
  567. xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
  568. break;
  569. case XML_ELEMENT_CONTENT_PLUS:
  570. xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
  571. break;
  572. }
  573. break;
  574. }
  575. default:
  576. xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
  577. "ContentModel broken for element %s\n",
  578. (const char *) name);
  579. return(0);
  580. }
  581. return(1);
  582. }
  583. /**
  584. * xmlValidBuildContentModel:
  585. * @ctxt: a validation context
  586. * @elem: an element declaration node
  587. *
  588. * (Re)Build the automata associated to the content model of this
  589. * element
  590. *
  591. * Returns 1 in case of success, 0 in case of error
  592. */
  593. int
  594. xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) {
  595. if ((ctxt == NULL) || (elem == NULL))
  596. return(0);
  597. if (elem->type != XML_ELEMENT_DECL)
  598. return(0);
  599. if (elem->etype != XML_ELEMENT_TYPE_ELEMENT)
  600. return(1);
  601. /* TODO: should we rebuild in this case ? */
  602. if (elem->contModel != NULL) {
  603. if (!xmlRegexpIsDeterminist(elem->contModel)) {
  604. ctxt->valid = 0;
  605. return(0);
  606. }
  607. return(1);
  608. }
  609. ctxt->am = xmlNewAutomata();
  610. if (ctxt->am == NULL) {
  611. xmlErrValidNode(ctxt, (xmlNodePtr) elem,
  612. XML_ERR_INTERNAL_ERROR,
  613. "Cannot create automata for element %s\n",
  614. elem->name, NULL, NULL);
  615. return(0);
  616. }
  617. ctxt->state = xmlAutomataGetInitState(ctxt->am);
  618. xmlValidBuildAContentModel(elem->content, ctxt, elem->name);
  619. xmlAutomataSetFinalState(ctxt->am, ctxt->state);
  620. elem->contModel = xmlAutomataCompile(ctxt->am);
  621. if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
  622. char expr[5000];
  623. expr[0] = 0;
  624. xmlSnprintfElementContent(expr, 5000, elem->content, 1);
  625. xmlErrValidNode(ctxt, (xmlNodePtr) elem,
  626. XML_DTD_CONTENT_NOT_DETERMINIST,
  627. "Content model of %s is not deterministic: %s\n",
  628. elem->name, BAD_CAST expr, NULL);
  629. ctxt->valid = 0;
  630. ctxt->state = NULL;
  631. xmlFreeAutomata(ctxt->am);
  632. ctxt->am = NULL;
  633. return(0);
  634. }
  635. ctxt->state = NULL;
  636. xmlFreeAutomata(ctxt->am);
  637. ctxt->am = NULL;
  638. return(1);
  639. }
  640. #endif /* LIBXML_REGEXP_ENABLED */
  641. /****************************************************************
  642. * *
  643. * Util functions for data allocation/deallocation *
  644. * *
  645. ****************************************************************/
  646. /**
  647. * xmlNewValidCtxt:
  648. *
  649. * Allocate a validation context structure.
  650. *
  651. * Returns NULL if not, otherwise the new validation context structure
  652. */
  653. xmlValidCtxtPtr xmlNewValidCtxt(void) {
  654. xmlValidCtxtPtr ret;
  655. if ((ret = xmlMalloc(sizeof (xmlValidCtxt))) == NULL) {
  656. xmlVErrMemory(NULL, "malloc failed");
  657. return (NULL);
  658. }
  659. (void) memset(ret, 0, sizeof (xmlValidCtxt));
  660. return (ret);
  661. }
  662. /**
  663. * xmlFreeValidCtxt:
  664. * @cur: the validation context to free
  665. *
  666. * Free a validation context structure.
  667. */
  668. void
  669. xmlFreeValidCtxt(xmlValidCtxtPtr cur) {
  670. if (cur == NULL)
  671. return;
  672. if (cur->vstateTab != NULL)
  673. xmlFree(cur->vstateTab);
  674. if (cur->nodeTab != NULL)
  675. xmlFree(cur->nodeTab);
  676. xmlFree(cur);
  677. }
  678. #endif /* LIBXML_VALID_ENABLED */
  679. /**
  680. * xmlNewDocElementContent:
  681. * @doc: the document
  682. * @name: the subelement name or NULL
  683. * @type: the type of element content decl
  684. *
  685. * Allocate an element content structure for the document.
  686. *
  687. * Returns NULL if not, otherwise the new element content structure
  688. */
  689. xmlElementContentPtr
  690. xmlNewDocElementContent(xmlDocPtr doc, const xmlChar *name,
  691. xmlElementContentType type) {
  692. xmlElementContentPtr ret;
  693. xmlDictPtr dict = NULL;
  694. if (doc != NULL)
  695. dict = doc->dict;
  696. switch(type) {
  697. case XML_ELEMENT_CONTENT_ELEMENT:
  698. if (name == NULL) {
  699. xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
  700. "xmlNewElementContent : name == NULL !\n",
  701. NULL);
  702. }
  703. break;
  704. case XML_ELEMENT_CONTENT_PCDATA:
  705. case XML_ELEMENT_CONTENT_SEQ:
  706. case XML_ELEMENT_CONTENT_OR:
  707. if (name != NULL) {
  708. xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
  709. "xmlNewElementContent : name != NULL !\n",
  710. NULL);
  711. }
  712. break;
  713. default:
  714. xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
  715. "Internal: ELEMENT content corrupted invalid type\n",
  716. NULL);
  717. return(NULL);
  718. }
  719. ret = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent));
  720. if (ret == NULL) {
  721. xmlVErrMemory(NULL, "malloc failed");
  722. return(NULL);
  723. }
  724. memset(ret, 0, sizeof(xmlElementContent));
  725. ret->type = type;
  726. ret->ocur = XML_ELEMENT_CONTENT_ONCE;
  727. if (name != NULL) {
  728. int l;
  729. const xmlChar *tmp;
  730. tmp = xmlSplitQName3(name, &l);
  731. if (tmp == NULL) {
  732. if (dict == NULL)
  733. ret->name = xmlStrdup(name);
  734. else
  735. ret->name = xmlDictLookup(dict, name, -1);
  736. } else {
  737. if (dict == NULL) {
  738. ret->prefix = xmlStrndup(name, l);
  739. ret->name = xmlStrdup(tmp);
  740. } else {
  741. ret->prefix = xmlDictLookup(dict, name, l);
  742. ret->name = xmlDictLookup(dict, tmp, -1);
  743. }
  744. }
  745. }
  746. return(ret);
  747. }
  748. /**
  749. * xmlNewElementContent:
  750. * @name: the subelement name or NULL
  751. * @type: the type of element content decl
  752. *
  753. * Allocate an element content structure.
  754. * Deprecated in favor of xmlNewDocElementContent
  755. *
  756. * Returns NULL if not, otherwise the new element content structure
  757. */
  758. xmlElementContentPtr
  759. xmlNewElementContent(const xmlChar *name, xmlElementContentType type) {
  760. return(xmlNewDocElementContent(NULL, name, type));
  761. }
  762. /**
  763. * xmlCopyDocElementContent:
  764. * @doc: the document owning the element declaration
  765. * @cur: An element content pointer.
  766. *
  767. * Build a copy of an element content description.
  768. *
  769. * Returns the new xmlElementContentPtr or NULL in case of error.
  770. */
  771. xmlElementContentPtr
  772. xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) {
  773. xmlElementContentPtr ret = NULL, prev = NULL, tmp;
  774. xmlDictPtr dict = NULL;
  775. if (cur == NULL) return(NULL);
  776. if (doc != NULL)
  777. dict = doc->dict;
  778. ret = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent));
  779. if (ret == NULL) {
  780. xmlVErrMemory(NULL, "malloc failed");
  781. return(NULL);
  782. }
  783. memset(ret, 0, sizeof(xmlElementContent));
  784. ret->type = cur->type;
  785. ret->ocur = cur->ocur;
  786. if (cur->name != NULL) {
  787. if (dict)
  788. ret->name = xmlDictLookup(dict, cur->name, -1);
  789. else
  790. ret->name = xmlStrdup(cur->name);
  791. }
  792. if (cur->prefix != NULL) {
  793. if (dict)
  794. ret->prefix = xmlDictLookup(dict, cur->prefix, -1);
  795. else
  796. ret->prefix = xmlStrdup(cur->prefix);
  797. }
  798. if (cur->c1 != NULL)
  799. ret->c1 = xmlCopyDocElementContent(doc, cur->c1);
  800. if (ret->c1 != NULL)
  801. ret->c1->parent = ret;
  802. if (cur->c2 != NULL) {
  803. prev = ret;
  804. cur = cur->c2;
  805. while (cur != NULL) {
  806. tmp = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent));
  807. if (tmp == NULL) {
  808. xmlVErrMemory(NULL, "malloc failed");
  809. return(ret);
  810. }
  811. memset(tmp, 0, sizeof(xmlElementContent));
  812. tmp->type = cur->type;
  813. tmp->ocur = cur->ocur;
  814. prev->c2 = tmp;
  815. tmp->parent = prev;
  816. if (cur->name != NULL) {
  817. if (dict)
  818. tmp->name = xmlDictLookup(dict, cur->name, -1);
  819. else
  820. tmp->name = xmlStrdup(cur->name);
  821. }
  822. if (cur->prefix != NULL) {
  823. if (dict)
  824. tmp->prefix = xmlDictLookup(dict, cur->prefix, -1);
  825. else
  826. tmp->prefix = xmlStrdup(cur->prefix);
  827. }
  828. if (cur->c1 != NULL)
  829. tmp->c1 = xmlCopyDocElementContent(doc,cur->c1);
  830. if (tmp->c1 != NULL)
  831. tmp->c1->parent = tmp;
  832. prev = tmp;
  833. cur = cur->c2;
  834. }
  835. }
  836. return(ret);
  837. }
  838. /**
  839. * xmlCopyElementContent:
  840. * @cur: An element content pointer.
  841. *
  842. * Build a copy of an element content description.
  843. * Deprecated, use xmlCopyDocElementContent instead
  844. *
  845. * Returns the new xmlElementContentPtr or NULL in case of error.
  846. */
  847. xmlElementContentPtr
  848. xmlCopyElementContent(xmlElementContentPtr cur) {
  849. return(xmlCopyDocElementContent(NULL, cur));
  850. }
  851. /**
  852. * xmlFreeDocElementContent:
  853. * @doc: the document owning the element declaration
  854. * @cur: the element content tree to free
  855. *
  856. * Free an element content structure. The whole subtree is removed.
  857. */
  858. void
  859. xmlFreeDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) {
  860. xmlDictPtr dict = NULL;
  861. size_t depth = 0;
  862. if (cur == NULL)
  863. return;
  864. if (doc != NULL)
  865. dict = doc->dict;
  866. while (1) {
  867. xmlElementContentPtr parent;
  868. while ((cur->c1 != NULL) || (cur->c2 != NULL)) {
  869. cur = (cur->c1 != NULL) ? cur->c1 : cur->c2;
  870. depth += 1;
  871. }
  872. switch (cur->type) {
  873. case XML_ELEMENT_CONTENT_PCDATA:
  874. case XML_ELEMENT_CONTENT_ELEMENT:
  875. case XML_ELEMENT_CONTENT_SEQ:
  876. case XML_ELEMENT_CONTENT_OR:
  877. break;
  878. default:
  879. xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
  880. "Internal: ELEMENT content corrupted invalid type\n",
  881. NULL);
  882. return;
  883. }
  884. if (dict) {
  885. if ((cur->name != NULL) && (!xmlDictOwns(dict, cur->name)))
  886. xmlFree((xmlChar *) cur->name);
  887. if ((cur->prefix != NULL) && (!xmlDictOwns(dict, cur->prefix)))
  888. xmlFree((xmlChar *) cur->prefix);
  889. } else {
  890. if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
  891. if (cur->prefix != NULL) xmlFree((xmlChar *) cur->prefix);
  892. }
  893. parent = cur->parent;
  894. if ((depth == 0) || (parent == NULL)) {
  895. xmlFree(cur);
  896. break;
  897. }
  898. if (cur == parent->c1)
  899. parent->c1 = NULL;
  900. else
  901. parent->c2 = NULL;
  902. xmlFree(cur);
  903. if (parent->c2 != NULL) {
  904. cur = parent->c2;
  905. } else {
  906. depth -= 1;
  907. cur = parent;
  908. }
  909. }
  910. }
  911. /**
  912. * xmlFreeElementContent:
  913. * @cur: the element content tree to free
  914. *
  915. * Free an element content structure. The whole subtree is removed.
  916. * Deprecated, use xmlFreeDocElementContent instead
  917. */
  918. void
  919. xmlFreeElementContent(xmlElementContentPtr cur) {
  920. xmlFreeDocElementContent(NULL, cur);
  921. }
  922. #ifdef LIBXML_OUTPUT_ENABLED
  923. /**
  924. * xmlDumpElementOccur:
  925. * @buf: An XML buffer
  926. * @cur: An element table
  927. *
  928. * Dump the occurrence operator of an element.
  929. */
  930. static void
  931. xmlDumpElementOccur(xmlBufferPtr buf, xmlElementContentPtr cur) {
  932. switch (cur->ocur) {
  933. case XML_ELEMENT_CONTENT_ONCE:
  934. break;
  935. case XML_ELEMENT_CONTENT_OPT:
  936. xmlBufferWriteChar(buf, "?");
  937. break;
  938. case XML_ELEMENT_CONTENT_MULT:
  939. xmlBufferWriteChar(buf, "*");
  940. break;
  941. case XML_ELEMENT_CONTENT_PLUS:
  942. xmlBufferWriteChar(buf, "+");
  943. break;
  944. }
  945. }
  946. /**
  947. * xmlDumpElementContent:
  948. * @buf: An XML buffer
  949. * @content: An element table
  950. *
  951. * This will dump the content of the element table as an XML DTD definition
  952. */
  953. static void
  954. xmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content) {
  955. xmlElementContentPtr cur;
  956. if (content == NULL) return;
  957. xmlBufferWriteChar(buf, "(");
  958. cur = content;
  959. do {
  960. if (cur == NULL) return;
  961. switch (cur->type) {
  962. case XML_ELEMENT_CONTENT_PCDATA:
  963. xmlBufferWriteChar(buf, "#PCDATA");
  964. break;
  965. case XML_ELEMENT_CONTENT_ELEMENT:
  966. if (cur->prefix != NULL) {
  967. xmlBufferWriteCHAR(buf, cur->prefix);
  968. xmlBufferWriteChar(buf, ":");
  969. }
  970. xmlBufferWriteCHAR(buf, cur->name);
  971. break;
  972. case XML_ELEMENT_CONTENT_SEQ:
  973. case XML_ELEMENT_CONTENT_OR:
  974. if ((cur != content) &&
  975. (cur->parent != NULL) &&
  976. ((cur->type != cur->parent->type) ||
  977. (cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
  978. xmlBufferWriteChar(buf, "(");
  979. cur = cur->c1;
  980. continue;
  981. default:
  982. xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
  983. "Internal: ELEMENT cur corrupted invalid type\n",
  984. NULL);
  985. }
  986. while (cur != content) {
  987. xmlElementContentPtr parent = cur->parent;
  988. if (parent == NULL) return;
  989. if (((cur->type == XML_ELEMENT_CONTENT_OR) ||
  990. (cur->type == XML_ELEMENT_CONTENT_SEQ)) &&
  991. ((cur->type != parent->type) ||
  992. (cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
  993. xmlBufferWriteChar(buf, ")");
  994. xmlDumpElementOccur(buf, cur);
  995. if (cur == parent->c1) {
  996. if (parent->type == XML_ELEMENT_CONTENT_SEQ)
  997. xmlBufferWriteChar(buf, " , ");
  998. else if (parent->type == XML_ELEMENT_CONTENT_OR)
  999. xmlBufferWriteChar(buf, " | ");
  1000. cur = parent->c2;
  1001. break;
  1002. }
  1003. cur = parent;
  1004. }
  1005. } while (cur != content);
  1006. xmlBufferWriteChar(buf, ")");
  1007. xmlDumpElementOccur(buf, content);
  1008. }
  1009. /**
  1010. * xmlSprintfElementContent:
  1011. * @buf: an output buffer
  1012. * @content: An element table
  1013. * @englob: 1 if one must print the englobing parenthesis, 0 otherwise
  1014. *
  1015. * Deprecated, unsafe, use xmlSnprintfElementContent
  1016. */
  1017. void
  1018. xmlSprintfElementContent(char *buf ATTRIBUTE_UNUSED,
  1019. xmlElementContentPtr content ATTRIBUTE_UNUSED,
  1020. int englob ATTRIBUTE_UNUSED) {
  1021. }
  1022. #endif /* LIBXML_OUTPUT_ENABLED */
  1023. /**
  1024. * xmlSnprintfElementContent:
  1025. * @buf: an output buffer
  1026. * @size: the buffer size
  1027. * @content: An element table
  1028. * @englob: 1 if one must print the englobing parenthesis, 0 otherwise
  1029. *
  1030. * This will dump the content of the element content definition
  1031. * Intended just for the debug routine
  1032. */
  1033. void
  1034. xmlSnprintfElementContent(char *buf, int size, xmlElementContentPtr content, int englob) {
  1035. int len;
  1036. if (content == NULL) return;
  1037. len = strlen(buf);
  1038. if (size - len < 50) {
  1039. if ((size - len > 4) && (buf[len - 1] != '.'))
  1040. strcat(buf, " ...");
  1041. return;
  1042. }
  1043. if (englob) strcat(buf, "(");
  1044. switch (content->type) {
  1045. case XML_ELEMENT_CONTENT_PCDATA:
  1046. strcat(buf, "#PCDATA");
  1047. break;
  1048. case XML_ELEMENT_CONTENT_ELEMENT: {
  1049. int qnameLen = xmlStrlen(content->name);
  1050. if (content->prefix != NULL)
  1051. qnameLen += xmlStrlen(content->prefix) + 1;
  1052. if (size - len < qnameLen + 10) {
  1053. strcat(buf, " ...");
  1054. return;
  1055. }
  1056. if (content->prefix != NULL) {
  1057. strcat(buf, (char *) content->prefix);
  1058. strcat(buf, ":");
  1059. }
  1060. if (content->name != NULL)
  1061. strcat(buf, (char *) content->name);
  1062. break;
  1063. }
  1064. case XML_ELEMENT_CONTENT_SEQ:
  1065. if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
  1066. (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
  1067. xmlSnprintfElementContent(buf, size, content->c1, 1);
  1068. else
  1069. xmlSnprintfElementContent(buf, size, content->c1, 0);
  1070. len = strlen(buf);
  1071. if (size - len < 50) {
  1072. if ((size - len > 4) && (buf[len - 1] != '.'))
  1073. strcat(buf, " ...");
  1074. return;
  1075. }
  1076. strcat(buf, " , ");
  1077. if (((content->c2->type == XML_ELEMENT_CONTENT_OR) ||
  1078. (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE)) &&
  1079. (content->c2->type != XML_ELEMENT_CONTENT_ELEMENT))
  1080. xmlSnprintfElementContent(buf, size, content->c2, 1);
  1081. else
  1082. xmlSnprintfElementContent(buf, size, content->c2, 0);
  1083. break;
  1084. case XML_ELEMENT_CONTENT_OR:
  1085. if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
  1086. (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
  1087. xmlSnprintfElementContent(buf, size, content->c1, 1);
  1088. else
  1089. xmlSnprintfElementContent(buf, size, content->c1, 0);
  1090. len = strlen(buf);
  1091. if (size - len < 50) {
  1092. if ((size - len > 4) && (buf[len - 1] != '.'))
  1093. strcat(buf, " ...");
  1094. return;
  1095. }
  1096. strcat(buf, " | ");
  1097. if (((content->c2->type == XML_ELEMENT_CONTENT_SEQ) ||
  1098. (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE)) &&
  1099. (content->c2->type != XML_ELEMENT_CONTENT_ELEMENT))
  1100. xmlSnprintfElementContent(buf, size, content->c2, 1);
  1101. else
  1102. xmlSnprintfElementContent(buf, size, content->c2, 0);
  1103. break;
  1104. }
  1105. if (size - strlen(buf) <= 2) return;
  1106. if (englob)
  1107. strcat(buf, ")");
  1108. switch (content->ocur) {
  1109. case XML_ELEMENT_CONTENT_ONCE:
  1110. break;
  1111. case XML_ELEMENT_CONTENT_OPT:
  1112. strcat(buf, "?");
  1113. break;
  1114. case XML_ELEMENT_CONTENT_MULT:
  1115. strcat(buf, "*");
  1116. break;
  1117. case XML_ELEMENT_CONTENT_PLUS:
  1118. strcat(buf, "+");
  1119. break;
  1120. }
  1121. }
  1122. /****************************************************************
  1123. * *
  1124. * Registration of DTD declarations *
  1125. * *
  1126. ****************************************************************/
  1127. /**
  1128. * xmlFreeElement:
  1129. * @elem: An element
  1130. *
  1131. * Deallocate the memory used by an element definition
  1132. */
  1133. static void
  1134. xmlFreeElement(xmlElementPtr elem) {
  1135. if (elem == NULL) return;
  1136. xmlUnlinkNode((xmlNodePtr) elem);
  1137. xmlFreeDocElementContent(elem->doc, elem->content);
  1138. if (elem->name != NULL)
  1139. xmlFree((xmlChar *) elem->name);
  1140. if (elem->prefix != NULL)
  1141. xmlFree((xmlChar *) elem->prefix);
  1142. #ifdef LIBXML_REGEXP_ENABLED
  1143. if (elem->contModel != NULL)
  1144. xmlRegFreeRegexp(elem->contModel);
  1145. #endif
  1146. xmlFree(elem);
  1147. }
  1148. /**
  1149. * xmlAddElementDecl:
  1150. * @ctxt: the validation context
  1151. * @dtd: pointer to the DTD
  1152. * @name: the entity name
  1153. * @type: the element type
  1154. * @content: the element content tree or NULL
  1155. *
  1156. * Register a new element declaration
  1157. *
  1158. * Returns NULL if not, otherwise the entity
  1159. */
  1160. xmlElementPtr
  1161. xmlAddElementDecl(xmlValidCtxtPtr ctxt,
  1162. xmlDtdPtr dtd, const xmlChar *name,
  1163. xmlElementTypeVal type,
  1164. xmlElementContentPtr content) {
  1165. xmlElementPtr ret;
  1166. xmlElementTablePtr table;
  1167. xmlAttributePtr oldAttributes = NULL;
  1168. xmlChar *ns, *uqname;
  1169. if (dtd == NULL) {
  1170. return(NULL);
  1171. }
  1172. if (name == NULL) {
  1173. return(NULL);
  1174. }
  1175. switch (type) {
  1176. case XML_ELEMENT_TYPE_EMPTY:
  1177. if (content != NULL) {
  1178. xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
  1179. "xmlAddElementDecl: content != NULL for EMPTY\n",
  1180. NULL);
  1181. return(NULL);
  1182. }
  1183. break;
  1184. case XML_ELEMENT_TYPE_ANY:
  1185. if (content != NULL) {
  1186. xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
  1187. "xmlAddElementDecl: content != NULL for ANY\n",
  1188. NULL);
  1189. return(NULL);
  1190. }
  1191. break;
  1192. case XML_ELEMENT_TYPE_MIXED:
  1193. if (content == NULL) {
  1194. xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
  1195. "xmlAddElementDecl: content == NULL for MIXED\n",
  1196. NULL);
  1197. return(NULL);
  1198. }
  1199. break;
  1200. case XML_ELEMENT_TYPE_ELEMENT:
  1201. if (content == NULL) {
  1202. xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
  1203. "xmlAddElementDecl: content == NULL for ELEMENT\n",
  1204. NULL);
  1205. return(NULL);
  1206. }
  1207. break;
  1208. default:
  1209. xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
  1210. "Internal: ELEMENT decl corrupted invalid type\n",
  1211. NULL);
  1212. return(NULL);
  1213. }
  1214. /*
  1215. * check if name is a QName
  1216. */
  1217. uqname = xmlSplitQName2(name, &ns);
  1218. if (uqname != NULL)
  1219. name = uqname;
  1220. /*
  1221. * Create the Element table if needed.
  1222. */
  1223. table = (xmlElementTablePtr) dtd->elements;
  1224. if (table == NULL) {
  1225. xmlDictPtr dict = NULL;
  1226. if (dtd->doc != NULL)
  1227. dict = dtd->doc->dict;
  1228. table = xmlHashCreateDict(0, dict);
  1229. dtd->elements = (void *) table;
  1230. }
  1231. if (table == NULL) {
  1232. xmlVErrMemory(ctxt,
  1233. "xmlAddElementDecl: Table creation failed!\n");
  1234. if (uqname != NULL)
  1235. xmlFree(uqname);
  1236. if (ns != NULL)
  1237. xmlFree(ns);
  1238. return(NULL);
  1239. }
  1240. /*
  1241. * lookup old attributes inserted on an undefined element in the
  1242. * internal subset.
  1243. */
  1244. if ((dtd->doc != NULL) && (dtd->doc->intSubset != NULL)) {
  1245. ret = xmlHashLookup2(dtd->doc->intSubset->elements, name, ns);
  1246. if ((ret != NULL) && (ret->etype == XML_ELEMENT_TYPE_UNDEFINED)) {
  1247. oldAttributes = ret->attributes;
  1248. ret->attributes = NULL;
  1249. xmlHashRemoveEntry2(dtd->doc->intSubset->elements, name, ns, NULL);
  1250. xmlFreeElement(ret);
  1251. }
  1252. }
  1253. /*
  1254. * The element may already be present if one of its attribute
  1255. * was registered first
  1256. */
  1257. ret = xmlHashLookup2(table, name, ns);
  1258. if (ret != NULL) {
  1259. if (ret->etype != XML_ELEMENT_TYPE_UNDEFINED) {
  1260. #ifdef LIBXML_VALID_ENABLED
  1261. /*
  1262. * The element is already defined in this DTD.
  1263. */
  1264. xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ELEM_REDEFINED,
  1265. "Redefinition of element %s\n",
  1266. name, NULL, NULL);
  1267. #endif /* LIBXML_VALID_ENABLED */
  1268. if (uqname != NULL)
  1269. xmlFree(uqname);
  1270. if (ns != NULL)
  1271. xmlFree(ns);
  1272. return(NULL);
  1273. }
  1274. if (ns != NULL) {
  1275. xmlFree(ns);
  1276. ns = NULL;
  1277. }
  1278. } else {
  1279. ret = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
  1280. if (ret == NULL) {
  1281. xmlVErrMemory(ctxt, "malloc failed");
  1282. if (uqname != NULL)
  1283. xmlFree(uqname);
  1284. if (ns != NULL)
  1285. xmlFree(ns);
  1286. return(NULL);
  1287. }
  1288. memset(ret, 0, sizeof(xmlElement));
  1289. ret->type = XML_ELEMENT_DECL;
  1290. /*
  1291. * fill the structure.
  1292. */
  1293. ret->name = xmlStrdup(name);
  1294. if (ret->name == NULL) {
  1295. xmlVErrMemory(ctxt, "malloc failed");
  1296. if (uqname != NULL)
  1297. xmlFree(uqname);
  1298. if (ns != NULL)
  1299. xmlFree(ns);
  1300. xmlFree(ret);
  1301. return(NULL);
  1302. }
  1303. ret->prefix = ns;
  1304. /*
  1305. * Validity Check:
  1306. * Insertion must not fail
  1307. */
  1308. if (xmlHashAddEntry2(table, name, ns, ret)) {
  1309. #ifdef LIBXML_VALID_ENABLED
  1310. /*
  1311. * The element is already defined in this DTD.
  1312. */
  1313. xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ELEM_REDEFINED,
  1314. "Redefinition of element %s\n",
  1315. name, NULL, NULL);
  1316. #endif /* LIBXML_VALID_ENABLED */
  1317. xmlFreeElement(ret);
  1318. if (uqname != NULL)
  1319. xmlFree(uqname);
  1320. return(NULL);
  1321. }
  1322. /*
  1323. * For new element, may have attributes from earlier
  1324. * definition in internal subset
  1325. */
  1326. ret->attributes = oldAttributes;
  1327. }
  1328. /*
  1329. * Finish to fill the structure.
  1330. */
  1331. ret->etype = type;
  1332. /*
  1333. * Avoid a stupid copy when called by the parser
  1334. * and flag it by setting a special parent value
  1335. * so the parser doesn't unallocate it.
  1336. */
  1337. if ((ctxt != NULL) && (ctxt->flags & XML_VCTXT_USE_PCTXT)) {
  1338. ret->content = content;
  1339. if (content != NULL)
  1340. content->parent = (xmlElementContentPtr) 1;
  1341. } else {
  1342. ret->content = xmlCopyDocElementContent(dtd->doc, content);
  1343. }
  1344. /*
  1345. * Link it to the DTD
  1346. */
  1347. ret->parent = dtd;
  1348. ret->doc = dtd->doc;
  1349. if (dtd->last == NULL) {
  1350. dtd->children = dtd->last = (xmlNodePtr) ret;
  1351. } else {
  1352. dtd->last->next = (xmlNodePtr) ret;
  1353. ret->prev = dtd->last;
  1354. dtd->last = (xmlNodePtr) ret;
  1355. }
  1356. if (uqname != NULL)
  1357. xmlFree(uqname);
  1358. return(ret);
  1359. }
  1360. static void
  1361. xmlFreeElementTableEntry(void *elem, const xmlChar *name ATTRIBUTE_UNUSED) {
  1362. xmlFreeElement((xmlElementPtr) elem);
  1363. }
  1364. /**
  1365. * xmlFreeElementTable:
  1366. * @table: An element table
  1367. *
  1368. * Deallocate the memory used by an element hash table.
  1369. */
  1370. void
  1371. xmlFreeElementTable(xmlElementTablePtr table) {
  1372. xmlHashFree(table, xmlFreeElementTableEntry);
  1373. }
  1374. #ifdef LIBXML_TREE_ENABLED
  1375. /**
  1376. * xmlCopyElement:
  1377. * @elem: An element
  1378. *
  1379. * Build a copy of an element.
  1380. *
  1381. * Returns the new xmlElementPtr or NULL in case of error.
  1382. */
  1383. static void *
  1384. xmlCopyElement(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
  1385. xmlElementPtr elem = (xmlElementPtr) payload;
  1386. xmlElementPtr cur;
  1387. cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
  1388. if (cur == NULL) {
  1389. xmlVErrMemory(NULL, "malloc failed");
  1390. return(NULL);
  1391. }
  1392. memset(cur, 0, sizeof(xmlElement));
  1393. cur->type = XML_ELEMENT_DECL;
  1394. cur->etype = elem->etype;
  1395. if (elem->name != NULL)
  1396. cur->name = xmlStrdup(elem->name);
  1397. else
  1398. cur->name = NULL;
  1399. if (elem->prefix != NULL)
  1400. cur->prefix = xmlStrdup(elem->prefix);
  1401. else
  1402. cur->prefix = NULL;
  1403. cur->content = xmlCopyElementContent(elem->content);
  1404. /* TODO : rebuild the attribute list on the copy */
  1405. cur->attributes = NULL;
  1406. return(cur);
  1407. }
  1408. /**
  1409. * xmlCopyElementTable:
  1410. * @table: An element table
  1411. *
  1412. * Build a copy of an element table.
  1413. *
  1414. * Returns the new xmlElementTablePtr or NULL in case of error.
  1415. */
  1416. xmlElementTablePtr
  1417. xmlCopyElementTable(xmlElementTablePtr table) {
  1418. return((xmlElementTablePtr) xmlHashCopy(table, xmlCopyElement));
  1419. }
  1420. #endif /* LIBXML_TREE_ENABLED */
  1421. #ifdef LIBXML_OUTPUT_ENABLED
  1422. /**
  1423. * xmlDumpElementDecl:
  1424. * @buf: the XML buffer output
  1425. * @elem: An element table
  1426. *
  1427. * This will dump the content of the element declaration as an XML
  1428. * DTD definition
  1429. */
  1430. void
  1431. xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) {
  1432. if ((buf == NULL) || (elem == NULL))
  1433. return;
  1434. switch (elem->etype) {
  1435. case XML_ELEMENT_TYPE_EMPTY:
  1436. xmlBufferWriteChar(buf, "<!ELEMENT ");
  1437. if (elem->prefix != NULL) {
  1438. xmlBufferWriteCHAR(buf, elem->prefix);
  1439. xmlBufferWriteChar(buf, ":");
  1440. }
  1441. xmlBufferWriteCHAR(buf, elem->name);
  1442. xmlBufferWriteChar(buf, " EMPTY>\n");
  1443. break;
  1444. case XML_ELEMENT_TYPE_ANY:
  1445. xmlBufferWriteChar(buf, "<!ELEMENT ");
  1446. if (elem->prefix != NULL) {
  1447. xmlBufferWriteCHAR(buf, elem->prefix);
  1448. xmlBufferWriteChar(buf, ":");
  1449. }
  1450. xmlBufferWriteCHAR(buf, elem->name);
  1451. xmlBufferWriteChar(buf, " ANY>\n");
  1452. break;
  1453. case XML_ELEMENT_TYPE_MIXED:
  1454. xmlBufferWriteChar(buf, "<!ELEMENT ");
  1455. if (elem->prefix != NULL) {
  1456. xmlBufferWriteCHAR(buf, elem->prefix);
  1457. xmlBufferWriteChar(buf, ":");
  1458. }
  1459. xmlBufferWriteCHAR(buf, elem->name);
  1460. xmlBufferWriteChar(buf, " ");
  1461. xmlDumpElementContent(buf, elem->content);
  1462. xmlBufferWriteChar(buf, ">\n");
  1463. break;
  1464. case XML_ELEMENT_TYPE_ELEMENT:
  1465. xmlBufferWriteChar(buf, "<!ELEMENT ");
  1466. if (elem->prefix != NULL) {
  1467. xmlBufferWriteCHAR(buf, elem->prefix);
  1468. xmlBufferWriteChar(buf, ":");
  1469. }
  1470. xmlBufferWriteCHAR(buf, elem->name);
  1471. xmlBufferWriteChar(buf, " ");
  1472. xmlDumpElementContent(buf, elem->content);
  1473. xmlBufferWriteChar(buf, ">\n");
  1474. break;
  1475. default:
  1476. xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
  1477. "Internal: ELEMENT struct corrupted invalid type\n",
  1478. NULL);
  1479. }
  1480. }
  1481. /**
  1482. * xmlDumpElementDeclScan:
  1483. * @elem: An element table
  1484. * @buf: the XML buffer output
  1485. *
  1486. * This routine is used by the hash scan function. It just reverses
  1487. * the arguments.
  1488. */
  1489. static void
  1490. xmlDumpElementDeclScan(void *elem, void *buf,
  1491. const xmlChar *name ATTRIBUTE_UNUSED) {
  1492. xmlDumpElementDecl((xmlBufferPtr) buf, (xmlElementPtr) elem);
  1493. }
  1494. /**
  1495. * xmlDumpElementTable:
  1496. * @buf: the XML buffer output
  1497. * @table: An element table
  1498. *
  1499. * This will dump the content of the element table as an XML DTD definition
  1500. */
  1501. void
  1502. xmlDumpElementTable(xmlBufferPtr buf, xmlElementTablePtr table) {
  1503. if ((buf == NULL) || (table == NULL))
  1504. return;
  1505. xmlHashScan(table, xmlDumpElementDeclScan, buf);
  1506. }
  1507. #endif /* LIBXML_OUTPUT_ENABLED */
  1508. /**
  1509. * xmlCreateEnumeration:
  1510. * @name: the enumeration name or NULL
  1511. *
  1512. * create and initialize an enumeration attribute node.
  1513. *
  1514. * Returns the xmlEnumerationPtr just created or NULL in case
  1515. * of error.
  1516. */
  1517. xmlEnumerationPtr
  1518. xmlCreateEnumeration(const xmlChar *name) {
  1519. xmlEnumerationPtr ret;
  1520. ret = (xmlEnumerationPtr) xmlMalloc(sizeof(xmlEnumeration));
  1521. if (ret == NULL) {
  1522. xmlVErrMemory(NULL, "malloc failed");
  1523. return(NULL);
  1524. }
  1525. memset(ret, 0, sizeof(xmlEnumeration));
  1526. if (name != NULL)
  1527. ret->name = xmlStrdup(name);
  1528. return(ret);
  1529. }
  1530. /**
  1531. * xmlFreeEnumeration:
  1532. * @cur: the tree to free.
  1533. *
  1534. * free an enumeration attribute node (recursive).
  1535. */
  1536. void
  1537. xmlFreeEnumeration(xmlEnumerationPtr cur) {
  1538. if (cur == NULL) return;
  1539. if (cur->next != NULL) xmlFreeEnumeration(cur->next);
  1540. if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
  1541. xmlFree(cur);
  1542. }
  1543. #ifdef LIBXML_TREE_ENABLED
  1544. /**
  1545. * xmlCopyEnumeration:
  1546. * @cur: the tree to copy.
  1547. *
  1548. * Copy an enumeration attribute node (recursive).
  1549. *
  1550. * Returns the xmlEnumerationPtr just created or NULL in case
  1551. * of error.
  1552. */
  1553. xmlEnumerationPtr
  1554. xmlCopyEnumeration(xmlEnumerationPtr cur) {
  1555. xmlEnumerationPtr ret;
  1556. if (cur == NULL) return(NULL);
  1557. ret = xmlCreateEnumeration((xmlChar *) cur->name);
  1558. if (ret == NULL) return(NULL);
  1559. if (cur->next != NULL) ret->next = xmlCopyEnumeration(cur->next);
  1560. else ret->next = NULL;
  1561. return(ret);
  1562. }
  1563. #endif /* LIBXML_TREE_ENABLED */
  1564. #ifdef LIBXML_OUTPUT_ENABLED
  1565. /**
  1566. * xmlDumpEnumeration:
  1567. * @buf: the XML buffer output
  1568. * @enum: An enumeration
  1569. *
  1570. * This will dump the content of the enumeration
  1571. */
  1572. static void
  1573. xmlDumpEnumeration(xmlBufferPtr buf, xmlEnumerationPtr cur) {
  1574. if ((buf == NULL) || (cur == NULL))
  1575. return;
  1576. xmlBufferWriteCHAR(buf, cur->name);
  1577. if (cur->next == NULL)
  1578. xmlBufferWriteChar(buf, ")");
  1579. else {
  1580. xmlBufferWriteChar(buf, " | ");
  1581. xmlDumpEnumeration(buf, cur->next);
  1582. }
  1583. }
  1584. #endif /* LIBXML_OUTPUT_ENABLED */
  1585. #ifdef LIBXML_VALID_ENABLED
  1586. /**
  1587. * xmlScanIDAttributeDecl:
  1588. * @ctxt: the validation context
  1589. * @elem: the element name
  1590. * @err: whether to raise errors here
  1591. *
  1592. * Verify that the element don't have too many ID attributes
  1593. * declared.
  1594. *
  1595. * Returns the number of ID attributes found.
  1596. */
  1597. static int
  1598. xmlScanIDAttributeDecl(xmlValidCtxtPtr ctxt, xmlElementPtr elem, int err) {
  1599. xmlAttributePtr cur;
  1600. int ret = 0;
  1601. if (elem == NULL) return(0);
  1602. cur = elem->attributes;
  1603. while (cur != NULL) {
  1604. if (cur->atype == XML_ATTRIBUTE_ID) {
  1605. ret ++;
  1606. if ((ret > 1) && (err))
  1607. xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_MULTIPLE_ID,
  1608. "Element %s has too many ID attributes defined : %s\n",
  1609. elem->name, cur->name, NULL);
  1610. }
  1611. cur = cur->nexth;
  1612. }
  1613. return(ret);
  1614. }
  1615. #endif /* LIBXML_VALID_ENABLED */
  1616. /**
  1617. * xmlFreeAttribute:
  1618. * @elem: An attribute
  1619. *
  1620. * Deallocate the memory used by an attribute definition
  1621. */
  1622. static void
  1623. xmlFreeAttribute(xmlAttributePtr attr) {
  1624. xmlDictPtr dict;
  1625. if (attr == NULL) return;
  1626. if (attr->doc != NULL)
  1627. dict = attr->doc->dict;
  1628. else
  1629. dict = NULL;
  1630. xmlUnlinkNode((xmlNodePtr) attr);
  1631. if (attr->tree != NULL)
  1632. xmlFreeEnumeration(attr->tree);
  1633. if (dict) {
  1634. if ((attr->elem != NULL) && (!xmlDictOwns(dict, attr->elem)))
  1635. xmlFree((xmlChar *) attr->elem);
  1636. if ((attr->name != NULL) && (!xmlDictOwns(dict, attr->name)))
  1637. xmlFree((xmlChar *) attr->name);
  1638. if ((attr->prefix != NULL) && (!xmlDictOwns(dict, attr->prefix)))
  1639. xmlFree((xmlChar *) attr->prefix);
  1640. if ((attr->defaultValue != NULL) &&
  1641. (!xmlDictOwns(dict, attr->defaultValue)))
  1642. xmlFree((xmlChar *) attr->defaultValue);
  1643. } else {
  1644. if (attr->elem != NULL)
  1645. xmlFree((xmlChar *) attr->elem);
  1646. if (attr->name != NULL)
  1647. xmlFree((xmlChar *) attr->name);
  1648. if (attr->defaultValue != NULL)
  1649. xmlFree((xmlChar *) attr->defaultValue);
  1650. if (attr->prefix != NULL)
  1651. xmlFree((xmlChar *) attr->prefix);
  1652. }
  1653. xmlFree(attr);
  1654. }
  1655. /**
  1656. * xmlAddAttributeDecl:
  1657. * @ctxt: the validation context
  1658. * @dtd: pointer to the DTD
  1659. * @elem: the element name
  1660. * @name: the attribute name
  1661. * @ns: the attribute namespace prefix
  1662. * @type: the attribute type
  1663. * @def: the attribute default type
  1664. * @defaultValue: the attribute default value
  1665. * @tree: if it's an enumeration, the associated list
  1666. *
  1667. * Register a new attribute declaration
  1668. * Note that @tree becomes the ownership of the DTD
  1669. *
  1670. * Returns NULL if not new, otherwise the attribute decl
  1671. */
  1672. xmlAttributePtr
  1673. xmlAddAttributeDecl(xmlValidCtxtPtr ctxt,
  1674. xmlDtdPtr dtd, const xmlChar *elem,
  1675. const xmlChar *name, const xmlChar *ns,
  1676. xmlAttributeType type, xmlAttributeDefault def,
  1677. const xmlChar *defaultValue, xmlEnumerationPtr tree) {
  1678. xmlAttributePtr ret;
  1679. xmlAttributeTablePtr table;
  1680. xmlElementPtr elemDef;
  1681. xmlDictPtr dict = NULL;
  1682. if (dtd == NULL) {
  1683. xmlFreeEnumeration(tree);
  1684. return(NULL);
  1685. }
  1686. if (name == NULL) {
  1687. xmlFreeEnumeration(tree);
  1688. return(NULL);
  1689. }
  1690. if (elem == NULL) {
  1691. xmlFreeEnumeration(tree);
  1692. return(NULL);
  1693. }
  1694. if (dtd->doc != NULL)
  1695. dict = dtd->doc->dict;
  1696. #ifdef LIBXML_VALID_ENABLED
  1697. /*
  1698. * Check the type and possibly the default value.
  1699. */
  1700. switch (type) {
  1701. case XML_ATTRIBUTE_CDATA:
  1702. break;
  1703. case XML_ATTRIBUTE_ID:
  1704. break;
  1705. case XML_ATTRIBUTE_IDREF:
  1706. break;
  1707. case XML_ATTRIBUTE_IDREFS:
  1708. break;
  1709. case XML_ATTRIBUTE_ENTITY:
  1710. break;
  1711. case XML_ATTRIBUTE_ENTITIES:
  1712. break;
  1713. case XML_ATTRIBUTE_NMTOKEN:
  1714. break;
  1715. case XML_ATTRIBUTE_NMTOKENS:
  1716. break;
  1717. case XML_ATTRIBUTE_ENUMERATION:
  1718. break;
  1719. case XML_ATTRIBUTE_NOTATION:
  1720. break;
  1721. default:
  1722. xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
  1723. "Internal: ATTRIBUTE struct corrupted invalid type\n",
  1724. NULL);
  1725. xmlFreeEnumeration(tree);
  1726. return(NULL);
  1727. }
  1728. if ((defaultValue != NULL) &&
  1729. (!xmlValidateAttributeValueInternal(dtd->doc, type, defaultValue))) {
  1730. xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ATTRIBUTE_DEFAULT,
  1731. "Attribute %s of %s: invalid default value\n",
  1732. elem, name, defaultValue);
  1733. defaultValue = NULL;
  1734. if (ctxt != NULL)
  1735. ctxt->valid = 0;
  1736. }
  1737. #endif /* LIBXML_VALID_ENABLED */
  1738. /*
  1739. * Check first that an attribute defined in the external subset wasn't
  1740. * already defined in the internal subset
  1741. */
  1742. if ((dtd->doc != NULL) && (dtd->doc->extSubset == dtd) &&
  1743. (dtd->doc->intSubset != NULL) &&
  1744. (dtd->doc->intSubset->attributes != NULL)) {
  1745. ret = xmlHashLookup3(dtd->doc->intSubset->attributes, name, ns, elem);
  1746. if (ret != NULL) {
  1747. xmlFreeEnumeration(tree);
  1748. return(NULL);
  1749. }
  1750. }
  1751. /*
  1752. * Create the Attribute table if needed.
  1753. */
  1754. table = (xmlAttributeTablePtr) dtd->attributes;
  1755. if (table == NULL) {
  1756. table = xmlHashCreateDict(0, dict);
  1757. dtd->attributes = (void *) table;
  1758. }
  1759. if (table == NULL) {
  1760. xmlVErrMemory(ctxt,
  1761. "xmlAddAttributeDecl: Table creation failed!\n");
  1762. xmlFreeEnumeration(tree);
  1763. return(NULL);
  1764. }
  1765. ret = (xmlAttributePtr) xmlMalloc(sizeof(xmlAttribute));
  1766. if (ret == NULL) {
  1767. xmlVErrMemory(ctxt, "malloc failed");
  1768. xmlFreeEnumeration(tree);
  1769. return(NULL);
  1770. }
  1771. memset(ret, 0, sizeof(xmlAttribute));
  1772. ret->type = XML_ATTRIBUTE_DECL;
  1773. /*
  1774. * fill the structure.
  1775. */
  1776. ret->atype = type;
  1777. /*
  1778. * doc must be set before possible error causes call
  1779. * to xmlFreeAttribute (because it's used to check on
  1780. * dict use)
  1781. */
  1782. ret->doc = dtd->doc;
  1783. if (dict) {
  1784. ret->name = xmlDictLookup(dict, name, -1);
  1785. ret->prefix = xmlDictLookup(dict, ns, -1);
  1786. ret->elem = xmlDictLookup(dict, elem, -1);
  1787. } else {
  1788. ret->name = xmlStrdup(name);
  1789. ret->prefix = xmlStrdup(ns);
  1790. ret->elem = xmlStrdup(elem);
  1791. }
  1792. ret->def = def;
  1793. ret->tree = tree;
  1794. if (defaultValue != NULL) {
  1795. if (dict)
  1796. ret->defaultValue = xmlDictLookup(dict, defaultValue, -1);
  1797. else
  1798. ret->defaultValue = xmlStrdup(defaultValue);
  1799. }
  1800. /*
  1801. * Validity Check:
  1802. * Search the DTD for previous declarations of the ATTLIST
  1803. */
  1804. if (xmlHashAddEntry3(table, ret->name, ret->prefix, ret->elem, ret) < 0) {
  1805. #ifdef LIBXML_VALID_ENABLED
  1806. /*
  1807. * The attribute is already defined in this DTD.
  1808. */
  1809. xmlErrValidWarning(ctxt, (xmlNodePtr) dtd, XML_DTD_ATTRIBUTE_REDEFINED,
  1810. "Attribute %s of element %s: already defined\n",
  1811. name, elem, NULL);
  1812. #endif /* LIBXML_VALID_ENABLED */
  1813. xmlFreeAttribute(ret);
  1814. return(NULL);
  1815. }
  1816. /*
  1817. * Validity Check:
  1818. * Multiple ID per element
  1819. */
  1820. elemDef = xmlGetDtdElementDesc2(ctxt, dtd, elem, 1);
  1821. if (elemDef != NULL) {
  1822. #ifdef LIBXML_VALID_ENABLED
  1823. if ((type == XML_ATTRIBUTE_ID) &&
  1824. (xmlScanIDAttributeDecl(NULL, elemDef, 1) != 0)) {
  1825. xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_MULTIPLE_ID,
  1826. "Element %s has too may ID attributes defined : %s\n",
  1827. elem, name, NULL);
  1828. if (ctxt != NULL)
  1829. ctxt->valid = 0;
  1830. }
  1831. #endif /* LIBXML_VALID_ENABLED */
  1832. /*
  1833. * Insert namespace default def first they need to be
  1834. * processed first.
  1835. */
  1836. if ((xmlStrEqual(ret->name, BAD_CAST "xmlns")) ||
  1837. ((ret->prefix != NULL &&
  1838. (xmlStrEqual(ret->prefix, BAD_CAST "xmlns"))))) {
  1839. ret->nexth = elemDef->attributes;
  1840. elemDef->attributes = ret;
  1841. } else {
  1842. xmlAttributePtr tmp = elemDef->attributes;
  1843. while ((tmp != NULL) &&
  1844. ((xmlStrEqual(tmp->name, BAD_CAST "xmlns")) ||
  1845. ((ret->prefix != NULL &&
  1846. (xmlStrEqual(ret->prefix, BAD_CAST "xmlns")))))) {
  1847. if (tmp->nexth == NULL)
  1848. break;
  1849. tmp = tmp->nexth;
  1850. }
  1851. if (tmp != NULL) {
  1852. ret->nexth = tmp->nexth;
  1853. tmp->nexth = ret;
  1854. } else {
  1855. ret->nexth = elemDef->attributes;
  1856. elemDef->attributes = ret;
  1857. }
  1858. }
  1859. }
  1860. /*
  1861. * Link it to the DTD
  1862. */
  1863. ret->parent = dtd;
  1864. if (dtd->last == NULL) {
  1865. dtd->children = dtd->last = (xmlNodePtr) ret;
  1866. } else {
  1867. dtd->last->next = (xmlNodePtr) ret;
  1868. ret->prev = dtd->last;
  1869. dtd->last = (xmlNodePtr) ret;
  1870. }
  1871. return(ret);
  1872. }
  1873. static void
  1874. xmlFreeAttributeTableEntry(void *attr, const xmlChar *name ATTRIBUTE_UNUSED) {
  1875. xmlFreeAttribute((xmlAttributePtr) attr);
  1876. }
  1877. /**
  1878. * xmlFreeAttributeTable:
  1879. * @table: An attribute table
  1880. *
  1881. * Deallocate the memory used by an entities hash table.
  1882. */
  1883. void
  1884. xmlFreeAttributeTable(xmlAttributeTablePtr table) {
  1885. xmlHashFree(table, xmlFreeAttributeTableEntry);
  1886. }
  1887. #ifdef LIBXML_TREE_ENABLED
  1888. /**
  1889. * xmlCopyAttribute:
  1890. * @attr: An attribute
  1891. *
  1892. * Build a copy of an attribute.
  1893. *
  1894. * Returns the new xmlAttributePtr or NULL in case of error.
  1895. */
  1896. static void *
  1897. xmlCopyAttribute(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
  1898. xmlAttributePtr attr = (xmlAttributePtr) payload;
  1899. xmlAttributePtr cur;
  1900. cur = (xmlAttributePtr) xmlMalloc(sizeof(xmlAttribute));
  1901. if (cur == NULL) {
  1902. xmlVErrMemory(NULL, "malloc failed");
  1903. return(NULL);
  1904. }
  1905. memset(cur, 0, sizeof(xmlAttribute));
  1906. cur->type = XML_ATTRIBUTE_DECL;
  1907. cur->atype = attr->atype;
  1908. cur->def = attr->def;
  1909. cur->tree = xmlCopyEnumeration(attr->tree);
  1910. if (attr->elem != NULL)
  1911. cur->elem = xmlStrdup(attr->elem);
  1912. if (attr->name != NULL)
  1913. cur->name = xmlStrdup(attr->name);
  1914. if (attr->prefix != NULL)
  1915. cur->prefix = xmlStrdup(attr->prefix);
  1916. if (attr->defaultValue != NULL)
  1917. cur->defaultValue = xmlStrdup(attr->defaultValue);
  1918. return(cur);
  1919. }
  1920. /**
  1921. * xmlCopyAttributeTable:
  1922. * @table: An attribute table
  1923. *
  1924. * Build a copy of an attribute table.
  1925. *
  1926. * Returns the new xmlAttributeTablePtr or NULL in case of error.
  1927. */
  1928. xmlAttributeTablePtr
  1929. xmlCopyAttributeTable(xmlAttributeTablePtr table) {
  1930. return((xmlAttributeTablePtr) xmlHashCopy(table, xmlCopyAttribute));
  1931. }
  1932. #endif /* LIBXML_TREE_ENABLED */
  1933. #ifdef LIBXML_OUTPUT_ENABLED
  1934. /**
  1935. * xmlDumpAttributeDecl:
  1936. * @buf: the XML buffer output
  1937. * @attr: An attribute declaration
  1938. *
  1939. * This will dump the content of the attribute declaration as an XML
  1940. * DTD definition
  1941. */
  1942. void
  1943. xmlDumpAttributeDecl(xmlBufferPtr buf, xmlAttributePtr attr) {
  1944. if ((buf == NULL) || (attr == NULL))
  1945. return;
  1946. xmlBufferWriteChar(buf, "<!ATTLIST ");
  1947. xmlBufferWriteCHAR(buf, attr->elem);
  1948. xmlBufferWriteChar(buf, " ");
  1949. if (attr->prefix != NULL) {
  1950. xmlBufferWriteCHAR(buf, attr->prefix);
  1951. xmlBufferWriteChar(buf, ":");
  1952. }
  1953. xmlBufferWriteCHAR(buf, attr->name);
  1954. switch (attr->atype) {
  1955. case XML_ATTRIBUTE_CDATA:
  1956. xmlBufferWriteChar(buf, " CDATA");
  1957. break;
  1958. case XML_ATTRIBUTE_ID:
  1959. xmlBufferWriteChar(buf, " ID");
  1960. break;
  1961. case XML_ATTRIBUTE_IDREF:
  1962. xmlBufferWriteChar(buf, " IDREF");
  1963. break;
  1964. case XML_ATTRIBUTE_IDREFS:
  1965. xmlBufferWriteChar(buf, " IDREFS");
  1966. break;
  1967. case XML_ATTRIBUTE_ENTITY:
  1968. xmlBufferWriteChar(buf, " ENTITY");
  1969. break;
  1970. case XML_ATTRIBUTE_ENTITIES:
  1971. xmlBufferWriteChar(buf, " ENTITIES");
  1972. break;
  1973. case XML_ATTRIBUTE_NMTOKEN:
  1974. xmlBufferWriteChar(buf, " NMTOKEN");
  1975. break;
  1976. case XML_ATTRIBUTE_NMTOKENS:
  1977. xmlBufferWriteChar(buf, " NMTOKENS");
  1978. break;
  1979. case XML_ATTRIBUTE_ENUMERATION:
  1980. xmlBufferWriteChar(buf, " (");
  1981. xmlDumpEnumeration(buf, attr->tree);
  1982. break;
  1983. case XML_ATTRIBUTE_NOTATION:
  1984. xmlBufferWriteChar(buf, " NOTATION (");
  1985. xmlDumpEnumeration(buf, attr->tree);
  1986. break;
  1987. default:
  1988. xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
  1989. "Internal: ATTRIBUTE struct corrupted invalid type\n",
  1990. NULL);
  1991. }
  1992. switch (attr->def) {
  1993. case XML_ATTRIBUTE_NONE:
  1994. break;
  1995. case XML_ATTRIBUTE_REQUIRED:
  1996. xmlBufferWriteChar(buf, " #REQUIRED");
  1997. break;
  1998. case XML_ATTRIBUTE_IMPLIED:
  1999. xmlBufferWriteChar(buf, " #IMPLIED");
  2000. break;
  2001. case XML_ATTRIBUTE_FIXED:
  2002. xmlBufferWriteChar(buf, " #FIXED");
  2003. break;
  2004. default:
  2005. xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
  2006. "Internal: ATTRIBUTE struct corrupted invalid def\n",
  2007. NULL);
  2008. }
  2009. if (attr->defaultValue != NULL) {
  2010. xmlBufferWriteChar(buf, " ");
  2011. xmlBufferWriteQuotedString(buf, attr->defaultValue);
  2012. }
  2013. xmlBufferWriteChar(buf, ">\n");
  2014. }
  2015. /**
  2016. * xmlDumpAttributeDeclScan:
  2017. * @attr: An attribute declaration
  2018. * @buf: the XML buffer output
  2019. *
  2020. * This is used with the hash scan function - just reverses arguments
  2021. */
  2022. static void
  2023. xmlDumpAttributeDeclScan(void *attr, void *buf,
  2024. const xmlChar *name ATTRIBUTE_UNUSED) {
  2025. xmlDumpAttributeDecl((xmlBufferPtr) buf, (xmlAttributePtr) attr);
  2026. }
  2027. /**
  2028. * xmlDumpAttributeTable:
  2029. * @buf: the XML buffer output
  2030. * @table: An attribute table
  2031. *
  2032. * This will dump the content of the attribute table as an XML DTD definition
  2033. */
  2034. void
  2035. xmlDumpAttributeTable(xmlBufferPtr buf, xmlAttributeTablePtr table) {
  2036. if ((buf == NULL) || (table == NULL))
  2037. return;
  2038. xmlHashScan(table, xmlDumpAttributeDeclScan, buf);
  2039. }
  2040. #endif /* LIBXML_OUTPUT_ENABLED */
  2041. /************************************************************************
  2042. * *
  2043. * NOTATIONs *
  2044. * *
  2045. ************************************************************************/
  2046. /**
  2047. * xmlFreeNotation:
  2048. * @not: A notation
  2049. *
  2050. * Deallocate the memory used by an notation definition
  2051. */
  2052. static void
  2053. xmlFreeNotation(xmlNotationPtr nota) {
  2054. if (nota == NULL) return;
  2055. if (nota->name != NULL)
  2056. xmlFree((xmlChar *) nota->name);
  2057. if (nota->PublicID != NULL)
  2058. xmlFree((xmlChar *) nota->PublicID);
  2059. if (nota->SystemID != NULL)
  2060. xmlFree((xmlChar *) nota->SystemID);
  2061. xmlFree(nota);
  2062. }
  2063. /**
  2064. * xmlAddNotationDecl:
  2065. * @dtd: pointer to the DTD
  2066. * @ctxt: the validation context
  2067. * @name: the entity name
  2068. * @PublicID: the public identifier or NULL
  2069. * @SystemID: the system identifier or NULL
  2070. *
  2071. * Register a new notation declaration
  2072. *
  2073. * Returns NULL if not, otherwise the entity
  2074. */
  2075. xmlNotationPtr
  2076. xmlAddNotationDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd,
  2077. const xmlChar *name,
  2078. const xmlChar *PublicID, const xmlChar *SystemID) {
  2079. xmlNotationPtr ret;
  2080. xmlNotationTablePtr table;
  2081. if (dtd == NULL) {
  2082. return(NULL);
  2083. }
  2084. if (name == NULL) {
  2085. return(NULL);
  2086. }
  2087. if ((PublicID == NULL) && (SystemID == NULL)) {
  2088. return(NULL);
  2089. }
  2090. /*
  2091. * Create the Notation table if needed.
  2092. */
  2093. table = (xmlNotationTablePtr) dtd->notations;
  2094. if (table == NULL) {
  2095. xmlDictPtr dict = NULL;
  2096. if (dtd->doc != NULL)
  2097. dict = dtd->doc->dict;
  2098. dtd->notations = table = xmlHashCreateDict(0, dict);
  2099. }
  2100. if (table == NULL) {
  2101. xmlVErrMemory(ctxt,
  2102. "xmlAddNotationDecl: Table creation failed!\n");
  2103. return(NULL);
  2104. }
  2105. ret = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation));
  2106. if (ret == NULL) {
  2107. xmlVErrMemory(ctxt, "malloc failed");
  2108. return(NULL);
  2109. }
  2110. memset(ret, 0, sizeof(xmlNotation));
  2111. /*
  2112. * fill the structure.
  2113. */
  2114. ret->name = xmlStrdup(name);
  2115. if (SystemID != NULL)
  2116. ret->SystemID = xmlStrdup(SystemID);
  2117. if (PublicID != NULL)
  2118. ret->PublicID = xmlStrdup(PublicID);
  2119. /*
  2120. * Validity Check:
  2121. * Check the DTD for previous declarations of the ATTLIST
  2122. */
  2123. if (xmlHashAddEntry(table, name, ret)) {
  2124. #ifdef LIBXML_VALID_ENABLED
  2125. xmlErrValid(NULL, XML_DTD_NOTATION_REDEFINED,
  2126. "xmlAddNotationDecl: %s already defined\n",
  2127. (const char *) name);
  2128. #endif /* LIBXML_VALID_ENABLED */
  2129. xmlFreeNotation(ret);
  2130. return(NULL);
  2131. }
  2132. return(ret);
  2133. }
  2134. static void
  2135. xmlFreeNotationTableEntry(void *nota, const xmlChar *name ATTRIBUTE_UNUSED) {
  2136. xmlFreeNotation((xmlNotationPtr) nota);
  2137. }
  2138. /**
  2139. * xmlFreeNotationTable:
  2140. * @table: An notation table
  2141. *
  2142. * Deallocate the memory used by an entities hash table.
  2143. */
  2144. void
  2145. xmlFreeNotationTable(xmlNotationTablePtr table) {
  2146. xmlHashFree(table, xmlFreeNotationTableEntry);
  2147. }
  2148. #ifdef LIBXML_TREE_ENABLED
  2149. /**
  2150. * xmlCopyNotation:
  2151. * @nota: A notation
  2152. *
  2153. * Build a copy of a notation.
  2154. *
  2155. * Returns the new xmlNotationPtr or NULL in case of error.
  2156. */
  2157. static void *
  2158. xmlCopyNotation(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
  2159. xmlNotationPtr nota = (xmlNotationPtr) payload;
  2160. xmlNotationPtr cur;
  2161. cur = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation));
  2162. if (cur == NULL) {
  2163. xmlVErrMemory(NULL, "malloc failed");
  2164. return(NULL);
  2165. }
  2166. if (nota->name != NULL)
  2167. cur->name = xmlStrdup(nota->name);
  2168. else
  2169. cur->name = NULL;
  2170. if (nota->PublicID != NULL)
  2171. cur->PublicID = xmlStrdup(nota->PublicID);
  2172. else
  2173. cur->PublicID = NULL;
  2174. if (nota->SystemID != NULL)
  2175. cur->SystemID = xmlStrdup(nota->SystemID);
  2176. else
  2177. cur->SystemID = NULL;
  2178. return(cur);
  2179. }
  2180. /**
  2181. * xmlCopyNotationTable:
  2182. * @table: A notation table
  2183. *
  2184. * Build a copy of a notation table.
  2185. *
  2186. * Returns the new xmlNotationTablePtr or NULL in case of error.
  2187. */
  2188. xmlNotationTablePtr
  2189. xmlCopyNotationTable(xmlNotationTablePtr table) {
  2190. return((xmlNotationTablePtr) xmlHashCopy(table, xmlCopyNotation));
  2191. }
  2192. #endif /* LIBXML_TREE_ENABLED */
  2193. #ifdef LIBXML_OUTPUT_ENABLED
  2194. /**
  2195. * xmlDumpNotationDecl:
  2196. * @buf: the XML buffer output
  2197. * @nota: A notation declaration
  2198. *
  2199. * This will dump the content the notation declaration as an XML DTD definition
  2200. */
  2201. void
  2202. xmlDumpNotationDecl(xmlBufferPtr buf, xmlNotationPtr nota) {
  2203. if ((buf == NULL) || (nota == NULL))
  2204. return;
  2205. xmlBufferWriteChar(buf, "<!NOTATION ");
  2206. xmlBufferWriteCHAR(buf, nota->name);
  2207. if (nota->PublicID != NULL) {
  2208. xmlBufferWriteChar(buf, " PUBLIC ");
  2209. xmlBufferWriteQuotedString(buf, nota->PublicID);
  2210. if (nota->SystemID != NULL) {
  2211. xmlBufferWriteChar(buf, " ");
  2212. xmlBufferWriteQuotedString(buf, nota->SystemID);
  2213. }
  2214. } else {
  2215. xmlBufferWriteChar(buf, " SYSTEM ");
  2216. xmlBufferWriteQuotedString(buf, nota->SystemID);
  2217. }
  2218. xmlBufferWriteChar(buf, " >\n");
  2219. }
  2220. /**
  2221. * xmlDumpNotationDeclScan:
  2222. * @nota: A notation declaration
  2223. * @buf: the XML buffer output
  2224. *
  2225. * This is called with the hash scan function, and just reverses args
  2226. */
  2227. static void
  2228. xmlDumpNotationDeclScan(void *nota, void *buf,
  2229. const xmlChar *name ATTRIBUTE_UNUSED) {
  2230. xmlDumpNotationDecl((xmlBufferPtr) buf, (xmlNotationPtr) nota);
  2231. }
  2232. /**
  2233. * xmlDumpNotationTable:
  2234. * @buf: the XML buffer output
  2235. * @table: A notation table
  2236. *
  2237. * This will dump the content of the notation table as an XML DTD definition
  2238. */
  2239. void
  2240. xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
  2241. if ((buf == NULL) || (table == NULL))
  2242. return;
  2243. xmlHashScan(table, xmlDumpNotationDeclScan, buf);
  2244. }
  2245. #endif /* LIBXML_OUTPUT_ENABLED */
  2246. /************************************************************************
  2247. * *
  2248. * IDs *
  2249. * *
  2250. ************************************************************************/
  2251. /**
  2252. * DICT_FREE:
  2253. * @str: a string
  2254. *
  2255. * Free a string if it is not owned by the "dict" dictionary in the
  2256. * current scope
  2257. */
  2258. #define DICT_FREE(str) \
  2259. if ((str) && ((!dict) || \
  2260. (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
  2261. xmlFree((char *)(str));
  2262. /**
  2263. * xmlValidNormalizeString:
  2264. * @str: a string
  2265. *
  2266. * Normalize a string in-place.
  2267. */
  2268. static void
  2269. xmlValidNormalizeString(xmlChar *str) {
  2270. xmlChar *dst;
  2271. const xmlChar *src;
  2272. if (str == NULL)
  2273. return;
  2274. src = str;
  2275. dst = str;
  2276. while (*src == 0x20) src++;
  2277. while (*src != 0) {
  2278. if (*src == 0x20) {
  2279. while (*src == 0x20) src++;
  2280. if (*src != 0)
  2281. *dst++ = 0x20;
  2282. } else {
  2283. *dst++ = *src++;
  2284. }
  2285. }
  2286. *dst = 0;
  2287. }
  2288. static int
  2289. xmlIsStreaming(xmlValidCtxtPtr ctxt) {
  2290. xmlParserCtxtPtr pctxt;
  2291. if (ctxt == NULL)
  2292. return(0);
  2293. if ((ctxt->flags & XML_VCTXT_USE_PCTXT) == 0)
  2294. return(0);
  2295. pctxt = ctxt->userData;
  2296. return(pctxt->parseMode == XML_PARSE_READER);
  2297. }
  2298. /**
  2299. * xmlFreeID:
  2300. * @not: A id
  2301. *
  2302. * Deallocate the memory used by an id definition
  2303. */
  2304. static void
  2305. xmlFreeID(xmlIDPtr id) {
  2306. xmlDictPtr dict = NULL;
  2307. if (id == NULL) return;
  2308. if (id->doc != NULL)
  2309. dict = id->doc->dict;
  2310. if (id->value != NULL)
  2311. DICT_FREE(id->value)
  2312. if (id->name != NULL)
  2313. DICT_FREE(id->name)
  2314. xmlFree(id);
  2315. }
  2316. /**
  2317. * xmlAddID:
  2318. * @ctxt: the validation context
  2319. * @doc: pointer to the document
  2320. * @value: the value name
  2321. * @attr: the attribute holding the ID
  2322. *
  2323. * Register a new id declaration
  2324. *
  2325. * Returns NULL if not, otherwise the new xmlIDPtr
  2326. */
  2327. xmlIDPtr
  2328. xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
  2329. xmlAttrPtr attr) {
  2330. xmlIDPtr ret;
  2331. xmlIDTablePtr table;
  2332. if (doc == NULL) {
  2333. return(NULL);
  2334. }
  2335. if ((value == NULL) || (value[0] == 0)) {
  2336. return(NULL);
  2337. }
  2338. if (attr == NULL) {
  2339. return(NULL);
  2340. }
  2341. /*
  2342. * Create the ID table if needed.
  2343. */
  2344. table = (xmlIDTablePtr) doc->ids;
  2345. if (table == NULL) {
  2346. doc->ids = table = xmlHashCreateDict(0, doc->dict);
  2347. }
  2348. if (table == NULL) {
  2349. xmlVErrMemory(ctxt,
  2350. "xmlAddID: Table creation failed!\n");
  2351. return(NULL);
  2352. }
  2353. ret = (xmlIDPtr) xmlMalloc(sizeof(xmlID));
  2354. if (ret == NULL) {
  2355. xmlVErrMemory(ctxt, "malloc failed");
  2356. return(NULL);
  2357. }
  2358. /*
  2359. * fill the structure.
  2360. */
  2361. ret->value = xmlStrdup(value);
  2362. ret->doc = doc;
  2363. if (xmlIsStreaming(ctxt)) {
  2364. /*
  2365. * Operating in streaming mode, attr is gonna disappear
  2366. */
  2367. if (doc->dict != NULL)
  2368. ret->name = xmlDictLookup(doc->dict, attr->name, -1);
  2369. else
  2370. ret->name = xmlStrdup(attr->name);
  2371. ret->attr = NULL;
  2372. } else {
  2373. ret->attr = attr;
  2374. ret->name = NULL;
  2375. }
  2376. ret->lineno = xmlGetLineNo(attr->parent);
  2377. if (xmlHashAddEntry(table, value, ret) < 0) {
  2378. #ifdef LIBXML_VALID_ENABLED
  2379. /*
  2380. * The id is already defined in this DTD.
  2381. */
  2382. if (ctxt != NULL) {
  2383. xmlErrValidNode(ctxt, attr->parent, XML_DTD_ID_REDEFINED,
  2384. "ID %s already defined\n", value, NULL, NULL);
  2385. }
  2386. #endif /* LIBXML_VALID_ENABLED */
  2387. xmlFreeID(ret);
  2388. return(NULL);
  2389. }
  2390. if (attr != NULL)
  2391. attr->atype = XML_ATTRIBUTE_ID;
  2392. return(ret);
  2393. }
  2394. static void
  2395. xmlFreeIDTableEntry(void *id, const xmlChar *name ATTRIBUTE_UNUSED) {
  2396. xmlFreeID((xmlIDPtr) id);
  2397. }
  2398. /**
  2399. * xmlFreeIDTable:
  2400. * @table: An id table
  2401. *
  2402. * Deallocate the memory used by an ID hash table.
  2403. */
  2404. void
  2405. xmlFreeIDTable(xmlIDTablePtr table) {
  2406. xmlHashFree(table, xmlFreeIDTableEntry);
  2407. }
  2408. /**
  2409. * xmlIsID:
  2410. * @doc: the document
  2411. * @elem: the element carrying the attribute
  2412. * @attr: the attribute
  2413. *
  2414. * Determine whether an attribute is of type ID. In case we have DTD(s)
  2415. * then this is done if DTD loading has been requested. In the case
  2416. * of HTML documents parsed with the HTML parser, then ID detection is
  2417. * done systematically.
  2418. *
  2419. * Returns 0 or 1 depending on the lookup result
  2420. */
  2421. int
  2422. xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
  2423. if ((attr == NULL) || (attr->name == NULL)) return(0);
  2424. if ((attr->ns != NULL) && (attr->ns->prefix != NULL) &&
  2425. (!strcmp((char *) attr->name, "id")) &&
  2426. (!strcmp((char *) attr->ns->prefix, "xml")))
  2427. return(1);
  2428. if (doc == NULL) return(0);
  2429. if ((doc->intSubset == NULL) && (doc->extSubset == NULL) &&
  2430. (doc->type != XML_HTML_DOCUMENT_NODE)) {
  2431. return(0);
  2432. } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
  2433. if ((xmlStrEqual(BAD_CAST "id", attr->name)) ||
  2434. ((xmlStrEqual(BAD_CAST "name", attr->name)) &&
  2435. ((elem == NULL) || (xmlStrEqual(elem->name, BAD_CAST "a")))))
  2436. return(1);
  2437. return(0);
  2438. } else if (elem == NULL) {
  2439. return(0);
  2440. } else {
  2441. xmlAttributePtr attrDecl = NULL;
  2442. xmlChar felem[50], fattr[50];
  2443. xmlChar *fullelemname, *fullattrname;
  2444. fullelemname = (elem->ns != NULL && elem->ns->prefix != NULL) ?
  2445. xmlBuildQName(elem->name, elem->ns->prefix, felem, 50) :
  2446. (xmlChar *)elem->name;
  2447. fullattrname = (attr->ns != NULL && attr->ns->prefix != NULL) ?
  2448. xmlBuildQName(attr->name, attr->ns->prefix, fattr, 50) :
  2449. (xmlChar *)attr->name;
  2450. if (fullelemname != NULL && fullattrname != NULL) {
  2451. attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullelemname,
  2452. fullattrname);
  2453. if ((attrDecl == NULL) && (doc->extSubset != NULL))
  2454. attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullelemname,
  2455. fullattrname);
  2456. }
  2457. if ((fullattrname != fattr) && (fullattrname != attr->name))
  2458. xmlFree(fullattrname);
  2459. if ((fullelemname != felem) && (fullelemname != elem->name))
  2460. xmlFree(fullelemname);
  2461. if ((attrDecl != NULL) && (attrDecl->atype == XML_ATTRIBUTE_ID))
  2462. return(1);
  2463. }
  2464. return(0);
  2465. }
  2466. /**
  2467. * xmlRemoveID:
  2468. * @doc: the document
  2469. * @attr: the attribute
  2470. *
  2471. * Remove the given attribute from the ID table maintained internally.
  2472. *
  2473. * Returns -1 if the lookup failed and 0 otherwise
  2474. */
  2475. int
  2476. xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
  2477. xmlIDTablePtr table;
  2478. xmlIDPtr id;
  2479. xmlChar *ID;
  2480. if (doc == NULL) return(-1);
  2481. if (attr == NULL) return(-1);
  2482. table = (xmlIDTablePtr) doc->ids;
  2483. if (table == NULL)
  2484. return(-1);
  2485. ID = xmlNodeListGetString(doc, attr->children, 1);
  2486. if (ID == NULL)
  2487. return(-1);
  2488. xmlValidNormalizeString(ID);
  2489. id = xmlHashLookup(table, ID);
  2490. if (id == NULL || id->attr != attr) {
  2491. xmlFree(ID);
  2492. return(-1);
  2493. }
  2494. xmlHashRemoveEntry(table, ID, xmlFreeIDTableEntry);
  2495. xmlFree(ID);
  2496. attr->atype = 0;
  2497. return(0);
  2498. }
  2499. /**
  2500. * xmlGetID:
  2501. * @doc: pointer to the document
  2502. * @ID: the ID value
  2503. *
  2504. * Search the attribute declaring the given ID
  2505. *
  2506. * Returns NULL if not found, otherwise the xmlAttrPtr defining the ID
  2507. */
  2508. xmlAttrPtr
  2509. xmlGetID(xmlDocPtr doc, const xmlChar *ID) {
  2510. xmlIDTablePtr table;
  2511. xmlIDPtr id;
  2512. if (doc == NULL) {
  2513. return(NULL);
  2514. }
  2515. if (ID == NULL) {
  2516. return(NULL);
  2517. }
  2518. table = (xmlIDTablePtr) doc->ids;
  2519. if (table == NULL)
  2520. return(NULL);
  2521. id = xmlHashLookup(table, ID);
  2522. if (id == NULL)
  2523. return(NULL);
  2524. if (id->attr == NULL) {
  2525. /*
  2526. * We are operating on a stream, return a well known reference
  2527. * since the attribute node doesn't exist anymore
  2528. */
  2529. return((xmlAttrPtr) doc);
  2530. }
  2531. return(id->attr);
  2532. }
  2533. /************************************************************************
  2534. * *
  2535. * Refs *
  2536. * *
  2537. ************************************************************************/
  2538. typedef struct xmlRemoveMemo_t
  2539. {
  2540. xmlListPtr l;
  2541. xmlAttrPtr ap;
  2542. } xmlRemoveMemo;
  2543. typedef xmlRemoveMemo *xmlRemoveMemoPtr;
  2544. typedef struct xmlValidateMemo_t
  2545. {
  2546. xmlValidCtxtPtr ctxt;
  2547. const xmlChar *name;
  2548. } xmlValidateMemo;
  2549. typedef xmlValidateMemo *xmlValidateMemoPtr;
  2550. /**
  2551. * xmlFreeRef:
  2552. * @lk: A list link
  2553. *
  2554. * Deallocate the memory used by a ref definition
  2555. */
  2556. static void
  2557. xmlFreeRef(xmlLinkPtr lk) {
  2558. xmlRefPtr ref = (xmlRefPtr)xmlLinkGetData(lk);
  2559. if (ref == NULL) return;
  2560. if (ref->value != NULL)
  2561. xmlFree((xmlChar *)ref->value);
  2562. if (ref->name != NULL)
  2563. xmlFree((xmlChar *)ref->name);
  2564. xmlFree(ref);
  2565. }
  2566. /**
  2567. * xmlFreeRefTableEntry:
  2568. * @list_ref: A list of references.
  2569. *
  2570. * Deallocate the memory used by a list of references
  2571. */
  2572. static void
  2573. xmlFreeRefTableEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
  2574. xmlListPtr list_ref = (xmlListPtr) payload;
  2575. if (list_ref == NULL) return;
  2576. xmlListDelete(list_ref);
  2577. }
  2578. /**
  2579. * xmlWalkRemoveRef:
  2580. * @data: Contents of current link
  2581. * @user: Value supplied by the user
  2582. *
  2583. * Returns 0 to abort the walk or 1 to continue
  2584. */
  2585. static int
  2586. xmlWalkRemoveRef(const void *data, void *user)
  2587. {
  2588. xmlAttrPtr attr0 = ((xmlRefPtr)data)->attr;
  2589. xmlAttrPtr attr1 = ((xmlRemoveMemoPtr)user)->ap;
  2590. xmlListPtr ref_list = ((xmlRemoveMemoPtr)user)->l;
  2591. if (attr0 == attr1) { /* Matched: remove and terminate walk */
  2592. xmlListRemoveFirst(ref_list, (void *)data);
  2593. return 0;
  2594. }
  2595. return 1;
  2596. }
  2597. /**
  2598. * xmlDummyCompare
  2599. * @data0: Value supplied by the user
  2600. * @data1: Value supplied by the user
  2601. *
  2602. * Do nothing, return 0. Used to create unordered lists.
  2603. */
  2604. static int
  2605. xmlDummyCompare(const void *data0 ATTRIBUTE_UNUSED,
  2606. const void *data1 ATTRIBUTE_UNUSED)
  2607. {
  2608. return (0);
  2609. }
  2610. /**
  2611. * xmlAddRef:
  2612. * @ctxt: the validation context
  2613. * @doc: pointer to the document
  2614. * @value: the value name
  2615. * @attr: the attribute holding the Ref
  2616. *
  2617. * DEPRECATED, do not use. This function will be removed from the public API.
  2618. *
  2619. * Register a new ref declaration
  2620. *
  2621. * Returns NULL if not, otherwise the new xmlRefPtr
  2622. */
  2623. xmlRefPtr
  2624. xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
  2625. xmlAttrPtr attr) {
  2626. xmlRefPtr ret;
  2627. xmlRefTablePtr table;
  2628. xmlListPtr ref_list;
  2629. if (doc == NULL) {
  2630. return(NULL);
  2631. }
  2632. if (value == NULL) {
  2633. return(NULL);
  2634. }
  2635. if (attr == NULL) {
  2636. return(NULL);
  2637. }
  2638. /*
  2639. * Create the Ref table if needed.
  2640. */
  2641. table = (xmlRefTablePtr) doc->refs;
  2642. if (table == NULL) {
  2643. doc->refs = table = xmlHashCreateDict(0, doc->dict);
  2644. }
  2645. if (table == NULL) {
  2646. xmlVErrMemory(ctxt,
  2647. "xmlAddRef: Table creation failed!\n");
  2648. return(NULL);
  2649. }
  2650. ret = (xmlRefPtr) xmlMalloc(sizeof(xmlRef));
  2651. if (ret == NULL) {
  2652. xmlVErrMemory(ctxt, "malloc failed");
  2653. return(NULL);
  2654. }
  2655. /*
  2656. * fill the structure.
  2657. */
  2658. ret->value = xmlStrdup(value);
  2659. if (xmlIsStreaming(ctxt)) {
  2660. /*
  2661. * Operating in streaming mode, attr is gonna disappear
  2662. */
  2663. ret->name = xmlStrdup(attr->name);
  2664. ret->attr = NULL;
  2665. } else {
  2666. ret->name = NULL;
  2667. ret->attr = attr;
  2668. }
  2669. ret->lineno = xmlGetLineNo(attr->parent);
  2670. /* To add a reference :-
  2671. * References are maintained as a list of references,
  2672. * Lookup the entry, if no entry create new nodelist
  2673. * Add the owning node to the NodeList
  2674. * Return the ref
  2675. */
  2676. if (NULL == (ref_list = xmlHashLookup(table, value))) {
  2677. if (NULL == (ref_list = xmlListCreate(xmlFreeRef, xmlDummyCompare))) {
  2678. xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
  2679. "xmlAddRef: Reference list creation failed!\n",
  2680. NULL);
  2681. goto failed;
  2682. }
  2683. if (xmlHashAddEntry(table, value, ref_list) < 0) {
  2684. xmlListDelete(ref_list);
  2685. xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
  2686. "xmlAddRef: Reference list insertion failed!\n",
  2687. NULL);
  2688. goto failed;
  2689. }
  2690. }
  2691. if (xmlListAppend(ref_list, ret) != 0) {
  2692. xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
  2693. "xmlAddRef: Reference list insertion failed!\n",
  2694. NULL);
  2695. goto failed;
  2696. }
  2697. return(ret);
  2698. failed:
  2699. if (ret != NULL) {
  2700. if (ret->value != NULL)
  2701. xmlFree((char *)ret->value);
  2702. if (ret->name != NULL)
  2703. xmlFree((char *)ret->name);
  2704. xmlFree(ret);
  2705. }
  2706. return(NULL);
  2707. }
  2708. /**
  2709. * xmlFreeRefTable:
  2710. * @table: An ref table
  2711. *
  2712. * DEPRECATED, do not use. This function will be removed from the public API.
  2713. *
  2714. * Deallocate the memory used by an Ref hash table.
  2715. */
  2716. void
  2717. xmlFreeRefTable(xmlRefTablePtr table) {
  2718. xmlHashFree(table, xmlFreeRefTableEntry);
  2719. }
  2720. /**
  2721. * xmlIsRef:
  2722. * @doc: the document
  2723. * @elem: the element carrying the attribute
  2724. * @attr: the attribute
  2725. *
  2726. * DEPRECATED, do not use. This function will be removed from the public API.
  2727. *
  2728. * Determine whether an attribute is of type Ref. In case we have DTD(s)
  2729. * then this is simple, otherwise we use an heuristic: name Ref (upper
  2730. * or lowercase).
  2731. *
  2732. * Returns 0 or 1 depending on the lookup result
  2733. */
  2734. int
  2735. xmlIsRef(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
  2736. if (attr == NULL)
  2737. return(0);
  2738. if (doc == NULL) {
  2739. doc = attr->doc;
  2740. if (doc == NULL) return(0);
  2741. }
  2742. if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) {
  2743. return(0);
  2744. } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
  2745. /* TODO @@@ */
  2746. return(0);
  2747. } else {
  2748. xmlAttributePtr attrDecl;
  2749. if (elem == NULL) return(0);
  2750. attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, attr->name);
  2751. if ((attrDecl == NULL) && (doc->extSubset != NULL))
  2752. attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
  2753. elem->name, attr->name);
  2754. if ((attrDecl != NULL) &&
  2755. (attrDecl->atype == XML_ATTRIBUTE_IDREF ||
  2756. attrDecl->atype == XML_ATTRIBUTE_IDREFS))
  2757. return(1);
  2758. }
  2759. return(0);
  2760. }
  2761. /**
  2762. * xmlRemoveRef:
  2763. * @doc: the document
  2764. * @attr: the attribute
  2765. *
  2766. * DEPRECATED, do not use. This function will be removed from the public API.
  2767. *
  2768. * Remove the given attribute from the Ref table maintained internally.
  2769. *
  2770. * Returns -1 if the lookup failed and 0 otherwise
  2771. */
  2772. int
  2773. xmlRemoveRef(xmlDocPtr doc, xmlAttrPtr attr) {
  2774. xmlListPtr ref_list;
  2775. xmlRefTablePtr table;
  2776. xmlChar *ID;
  2777. xmlRemoveMemo target;
  2778. if (doc == NULL) return(-1);
  2779. if (attr == NULL) return(-1);
  2780. table = (xmlRefTablePtr) doc->refs;
  2781. if (table == NULL)
  2782. return(-1);
  2783. ID = xmlNodeListGetString(doc, attr->children, 1);
  2784. if (ID == NULL)
  2785. return(-1);
  2786. ref_list = xmlHashLookup(table, ID);
  2787. if(ref_list == NULL) {
  2788. xmlFree(ID);
  2789. return (-1);
  2790. }
  2791. /* At this point, ref_list refers to a list of references which
  2792. * have the same key as the supplied attr. Our list of references
  2793. * is ordered by reference address and we don't have that information
  2794. * here to use when removing. We'll have to walk the list and
  2795. * check for a matching attribute, when we find one stop the walk
  2796. * and remove the entry.
  2797. * The list is ordered by reference, so that means we don't have the
  2798. * key. Passing the list and the reference to the walker means we
  2799. * will have enough data to be able to remove the entry.
  2800. */
  2801. target.l = ref_list;
  2802. target.ap = attr;
  2803. /* Remove the supplied attr from our list */
  2804. xmlListWalk(ref_list, xmlWalkRemoveRef, &target);
  2805. /*If the list is empty then remove the list entry in the hash */
  2806. if (xmlListEmpty(ref_list))
  2807. xmlHashUpdateEntry(table, ID, NULL, xmlFreeRefTableEntry);
  2808. xmlFree(ID);
  2809. return(0);
  2810. }
  2811. /**
  2812. * xmlGetRefs:
  2813. * @doc: pointer to the document
  2814. * @ID: the ID value
  2815. *
  2816. * DEPRECATED, do not use. This function will be removed from the public API.
  2817. *
  2818. * Find the set of references for the supplied ID.
  2819. *
  2820. * Returns NULL if not found, otherwise node set for the ID.
  2821. */
  2822. xmlListPtr
  2823. xmlGetRefs(xmlDocPtr doc, const xmlChar *ID) {
  2824. xmlRefTablePtr table;
  2825. if (doc == NULL) {
  2826. return(NULL);
  2827. }
  2828. if (ID == NULL) {
  2829. return(NULL);
  2830. }
  2831. table = (xmlRefTablePtr) doc->refs;
  2832. if (table == NULL)
  2833. return(NULL);
  2834. return (xmlHashLookup(table, ID));
  2835. }
  2836. /************************************************************************
  2837. * *
  2838. * Routines for validity checking *
  2839. * *
  2840. ************************************************************************/
  2841. /**
  2842. * xmlGetDtdElementDesc:
  2843. * @dtd: a pointer to the DtD to search
  2844. * @name: the element name
  2845. *
  2846. * Search the DTD for the description of this element
  2847. *
  2848. * returns the xmlElementPtr if found or NULL
  2849. */
  2850. xmlElementPtr
  2851. xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name) {
  2852. xmlElementTablePtr table;
  2853. xmlElementPtr cur;
  2854. xmlChar *uqname = NULL, *prefix = NULL;
  2855. if ((dtd == NULL) || (name == NULL)) return(NULL);
  2856. if (dtd->elements == NULL)
  2857. return(NULL);
  2858. table = (xmlElementTablePtr) dtd->elements;
  2859. uqname = xmlSplitQName2(name, &prefix);
  2860. if (uqname != NULL)
  2861. name = uqname;
  2862. cur = xmlHashLookup2(table, name, prefix);
  2863. if (prefix != NULL) xmlFree(prefix);
  2864. if (uqname != NULL) xmlFree(uqname);
  2865. return(cur);
  2866. }
  2867. /**
  2868. * xmlGetDtdElementDesc2:
  2869. * @dtd: a pointer to the DtD to search
  2870. * @name: the element name
  2871. * @create: create an empty description if not found
  2872. *
  2873. * Search the DTD for the description of this element
  2874. *
  2875. * returns the xmlElementPtr if found or NULL
  2876. */
  2877. static xmlElementPtr
  2878. xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
  2879. int create) {
  2880. xmlElementTablePtr table;
  2881. xmlElementPtr cur;
  2882. xmlChar *uqname = NULL, *prefix = NULL;
  2883. if (dtd == NULL) return(NULL);
  2884. if (dtd->elements == NULL) {
  2885. xmlDictPtr dict = NULL;
  2886. if (dtd->doc != NULL)
  2887. dict = dtd->doc->dict;
  2888. if (!create)
  2889. return(NULL);
  2890. /*
  2891. * Create the Element table if needed.
  2892. */
  2893. table = (xmlElementTablePtr) dtd->elements;
  2894. if (table == NULL) {
  2895. table = xmlHashCreateDict(0, dict);
  2896. dtd->elements = (void *) table;
  2897. }
  2898. if (table == NULL) {
  2899. xmlVErrMemory(ctxt, "element table allocation failed");
  2900. return(NULL);
  2901. }
  2902. }
  2903. table = (xmlElementTablePtr) dtd->elements;
  2904. uqname = xmlSplitQName2(name, &prefix);
  2905. if (uqname != NULL)
  2906. name = uqname;
  2907. cur = xmlHashLookup2(table, name, prefix);
  2908. if ((cur == NULL) && (create)) {
  2909. cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
  2910. if (cur == NULL) {
  2911. xmlVErrMemory(ctxt, "malloc failed");
  2912. goto error;
  2913. }
  2914. memset(cur, 0, sizeof(xmlElement));
  2915. cur->type = XML_ELEMENT_DECL;
  2916. /*
  2917. * fill the structure.
  2918. */
  2919. cur->name = xmlStrdup(name);
  2920. cur->prefix = xmlStrdup(prefix);
  2921. cur->etype = XML_ELEMENT_TYPE_UNDEFINED;
  2922. if (xmlHashAddEntry2(table, name, prefix, cur) < 0) {
  2923. xmlVErrMemory(ctxt, "adding entry failed");
  2924. xmlFreeElement(cur);
  2925. cur = NULL;
  2926. }
  2927. }
  2928. error:
  2929. if (prefix != NULL) xmlFree(prefix);
  2930. if (uqname != NULL) xmlFree(uqname);
  2931. return(cur);
  2932. }
  2933. /**
  2934. * xmlGetDtdQElementDesc:
  2935. * @dtd: a pointer to the DtD to search
  2936. * @name: the element name
  2937. * @prefix: the element namespace prefix
  2938. *
  2939. * Search the DTD for the description of this element
  2940. *
  2941. * returns the xmlElementPtr if found or NULL
  2942. */
  2943. xmlElementPtr
  2944. xmlGetDtdQElementDesc(xmlDtdPtr dtd, const xmlChar *name,
  2945. const xmlChar *prefix) {
  2946. xmlElementTablePtr table;
  2947. if (dtd == NULL) return(NULL);
  2948. if (dtd->elements == NULL) return(NULL);
  2949. table = (xmlElementTablePtr) dtd->elements;
  2950. return(xmlHashLookup2(table, name, prefix));
  2951. }
  2952. /**
  2953. * xmlGetDtdAttrDesc:
  2954. * @dtd: a pointer to the DtD to search
  2955. * @elem: the element name
  2956. * @name: the attribute name
  2957. *
  2958. * Search the DTD for the description of this attribute on
  2959. * this element.
  2960. *
  2961. * returns the xmlAttributePtr if found or NULL
  2962. */
  2963. xmlAttributePtr
  2964. xmlGetDtdAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name) {
  2965. xmlAttributeTablePtr table;
  2966. xmlAttributePtr cur;
  2967. xmlChar *uqname = NULL, *prefix = NULL;
  2968. if (dtd == NULL) return(NULL);
  2969. if (dtd->attributes == NULL) return(NULL);
  2970. table = (xmlAttributeTablePtr) dtd->attributes;
  2971. if (table == NULL)
  2972. return(NULL);
  2973. uqname = xmlSplitQName2(name, &prefix);
  2974. if (uqname != NULL) {
  2975. cur = xmlHashLookup3(table, uqname, prefix, elem);
  2976. if (prefix != NULL) xmlFree(prefix);
  2977. if (uqname != NULL) xmlFree(uqname);
  2978. } else
  2979. cur = xmlHashLookup3(table, name, NULL, elem);
  2980. return(cur);
  2981. }
  2982. /**
  2983. * xmlGetDtdQAttrDesc:
  2984. * @dtd: a pointer to the DtD to search
  2985. * @elem: the element name
  2986. * @name: the attribute name
  2987. * @prefix: the attribute namespace prefix
  2988. *
  2989. * Search the DTD for the description of this qualified attribute on
  2990. * this element.
  2991. *
  2992. * returns the xmlAttributePtr if found or NULL
  2993. */
  2994. xmlAttributePtr
  2995. xmlGetDtdQAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name,
  2996. const xmlChar *prefix) {
  2997. xmlAttributeTablePtr table;
  2998. if (dtd == NULL) return(NULL);
  2999. if (dtd->attributes == NULL) return(NULL);
  3000. table = (xmlAttributeTablePtr) dtd->attributes;
  3001. return(xmlHashLookup3(table, name, prefix, elem));
  3002. }
  3003. /**
  3004. * xmlGetDtdNotationDesc:
  3005. * @dtd: a pointer to the DtD to search
  3006. * @name: the notation name
  3007. *
  3008. * Search the DTD for the description of this notation
  3009. *
  3010. * returns the xmlNotationPtr if found or NULL
  3011. */
  3012. xmlNotationPtr
  3013. xmlGetDtdNotationDesc(xmlDtdPtr dtd, const xmlChar *name) {
  3014. xmlNotationTablePtr table;
  3015. if (dtd == NULL) return(NULL);
  3016. if (dtd->notations == NULL) return(NULL);
  3017. table = (xmlNotationTablePtr) dtd->notations;
  3018. return(xmlHashLookup(table, name));
  3019. }
  3020. #if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
  3021. /**
  3022. * xmlValidateNotationUse:
  3023. * @ctxt: the validation context
  3024. * @doc: the document
  3025. * @notationName: the notation name to check
  3026. *
  3027. * Validate that the given name match a notation declaration.
  3028. * - [ VC: Notation Declared ]
  3029. *
  3030. * returns 1 if valid or 0 otherwise
  3031. */
  3032. int
  3033. xmlValidateNotationUse(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  3034. const xmlChar *notationName) {
  3035. xmlNotationPtr notaDecl;
  3036. if ((doc == NULL) || (doc->intSubset == NULL) ||
  3037. (notationName == NULL)) return(-1);
  3038. notaDecl = xmlGetDtdNotationDesc(doc->intSubset, notationName);
  3039. if ((notaDecl == NULL) && (doc->extSubset != NULL))
  3040. notaDecl = xmlGetDtdNotationDesc(doc->extSubset, notationName);
  3041. if ((notaDecl == NULL) && (ctxt != NULL)) {
  3042. xmlErrValidNode(ctxt, (xmlNodePtr) doc, XML_DTD_UNKNOWN_NOTATION,
  3043. "NOTATION %s is not declared\n",
  3044. notationName, NULL, NULL);
  3045. return(0);
  3046. }
  3047. return(1);
  3048. }
  3049. #endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */
  3050. /**
  3051. * xmlIsMixedElement:
  3052. * @doc: the document
  3053. * @name: the element name
  3054. *
  3055. * Search in the DtDs whether an element accept Mixed content (or ANY)
  3056. * basically if it is supposed to accept text childs
  3057. *
  3058. * returns 0 if no, 1 if yes, and -1 if no element description is available
  3059. */
  3060. int
  3061. xmlIsMixedElement(xmlDocPtr doc, const xmlChar *name) {
  3062. xmlElementPtr elemDecl;
  3063. if ((doc == NULL) || (doc->intSubset == NULL)) return(-1);
  3064. elemDecl = xmlGetDtdElementDesc(doc->intSubset, name);
  3065. if ((elemDecl == NULL) && (doc->extSubset != NULL))
  3066. elemDecl = xmlGetDtdElementDesc(doc->extSubset, name);
  3067. if (elemDecl == NULL) return(-1);
  3068. switch (elemDecl->etype) {
  3069. case XML_ELEMENT_TYPE_UNDEFINED:
  3070. return(-1);
  3071. case XML_ELEMENT_TYPE_ELEMENT:
  3072. return(0);
  3073. case XML_ELEMENT_TYPE_EMPTY:
  3074. /*
  3075. * return 1 for EMPTY since we want VC error to pop up
  3076. * on <empty> </empty> for example
  3077. */
  3078. case XML_ELEMENT_TYPE_ANY:
  3079. case XML_ELEMENT_TYPE_MIXED:
  3080. return(1);
  3081. }
  3082. return(1);
  3083. }
  3084. #ifdef LIBXML_VALID_ENABLED
  3085. static int
  3086. xmlIsDocNameStartChar(xmlDocPtr doc, int c) {
  3087. if ((doc == NULL) || (doc->properties & XML_DOC_OLD10) == 0) {
  3088. /*
  3089. * Use the new checks of production [4] [4a] amd [5] of the
  3090. * Update 5 of XML-1.0
  3091. */
  3092. if (((c >= 'a') && (c <= 'z')) ||
  3093. ((c >= 'A') && (c <= 'Z')) ||
  3094. (c == '_') || (c == ':') ||
  3095. ((c >= 0xC0) && (c <= 0xD6)) ||
  3096. ((c >= 0xD8) && (c <= 0xF6)) ||
  3097. ((c >= 0xF8) && (c <= 0x2FF)) ||
  3098. ((c >= 0x370) && (c <= 0x37D)) ||
  3099. ((c >= 0x37F) && (c <= 0x1FFF)) ||
  3100. ((c >= 0x200C) && (c <= 0x200D)) ||
  3101. ((c >= 0x2070) && (c <= 0x218F)) ||
  3102. ((c >= 0x2C00) && (c <= 0x2FEF)) ||
  3103. ((c >= 0x3001) && (c <= 0xD7FF)) ||
  3104. ((c >= 0xF900) && (c <= 0xFDCF)) ||
  3105. ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
  3106. ((c >= 0x10000) && (c <= 0xEFFFF)))
  3107. return(1);
  3108. } else {
  3109. if (IS_LETTER(c) || (c == '_') || (c == ':'))
  3110. return(1);
  3111. }
  3112. return(0);
  3113. }
  3114. static int
  3115. xmlIsDocNameChar(xmlDocPtr doc, int c) {
  3116. if ((doc == NULL) || (doc->properties & XML_DOC_OLD10) == 0) {
  3117. /*
  3118. * Use the new checks of production [4] [4a] amd [5] of the
  3119. * Update 5 of XML-1.0
  3120. */
  3121. if (((c >= 'a') && (c <= 'z')) ||
  3122. ((c >= 'A') && (c <= 'Z')) ||
  3123. ((c >= '0') && (c <= '9')) || /* !start */
  3124. (c == '_') || (c == ':') ||
  3125. (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
  3126. ((c >= 0xC0) && (c <= 0xD6)) ||
  3127. ((c >= 0xD8) && (c <= 0xF6)) ||
  3128. ((c >= 0xF8) && (c <= 0x2FF)) ||
  3129. ((c >= 0x300) && (c <= 0x36F)) || /* !start */
  3130. ((c >= 0x370) && (c <= 0x37D)) ||
  3131. ((c >= 0x37F) && (c <= 0x1FFF)) ||
  3132. ((c >= 0x200C) && (c <= 0x200D)) ||
  3133. ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
  3134. ((c >= 0x2070) && (c <= 0x218F)) ||
  3135. ((c >= 0x2C00) && (c <= 0x2FEF)) ||
  3136. ((c >= 0x3001) && (c <= 0xD7FF)) ||
  3137. ((c >= 0xF900) && (c <= 0xFDCF)) ||
  3138. ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
  3139. ((c >= 0x10000) && (c <= 0xEFFFF)))
  3140. return(1);
  3141. } else {
  3142. if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
  3143. (c == '.') || (c == '-') ||
  3144. (c == '_') || (c == ':') ||
  3145. (IS_COMBINING(c)) ||
  3146. (IS_EXTENDER(c)))
  3147. return(1);
  3148. }
  3149. return(0);
  3150. }
  3151. /**
  3152. * xmlValidateNameValue:
  3153. * @doc: pointer to the document or NULL
  3154. * @value: an Name value
  3155. *
  3156. * Validate that the given value match Name production
  3157. *
  3158. * returns 1 if valid or 0 otherwise
  3159. */
  3160. static int
  3161. xmlValidateNameValueInternal(xmlDocPtr doc, const xmlChar *value) {
  3162. const xmlChar *cur;
  3163. int val, len;
  3164. if (value == NULL) return(0);
  3165. cur = value;
  3166. val = xmlStringCurrentChar(NULL, cur, &len);
  3167. cur += len;
  3168. if (!xmlIsDocNameStartChar(doc, val))
  3169. return(0);
  3170. val = xmlStringCurrentChar(NULL, cur, &len);
  3171. cur += len;
  3172. while (xmlIsDocNameChar(doc, val)) {
  3173. val = xmlStringCurrentChar(NULL, cur, &len);
  3174. cur += len;
  3175. }
  3176. if (val != 0) return(0);
  3177. return(1);
  3178. }
  3179. /**
  3180. * xmlValidateNameValue:
  3181. * @value: an Name value
  3182. *
  3183. * Validate that the given value match Name production
  3184. *
  3185. * returns 1 if valid or 0 otherwise
  3186. */
  3187. int
  3188. xmlValidateNameValue(const xmlChar *value) {
  3189. return(xmlValidateNameValueInternal(NULL, value));
  3190. }
  3191. /**
  3192. * xmlValidateNamesValueInternal:
  3193. * @doc: pointer to the document or NULL
  3194. * @value: an Names value
  3195. *
  3196. * Validate that the given value match Names production
  3197. *
  3198. * returns 1 if valid or 0 otherwise
  3199. */
  3200. static int
  3201. xmlValidateNamesValueInternal(xmlDocPtr doc, const xmlChar *value) {
  3202. const xmlChar *cur;
  3203. int val, len;
  3204. if (value == NULL) return(0);
  3205. cur = value;
  3206. val = xmlStringCurrentChar(NULL, cur, &len);
  3207. cur += len;
  3208. if (!xmlIsDocNameStartChar(doc, val))
  3209. return(0);
  3210. val = xmlStringCurrentChar(NULL, cur, &len);
  3211. cur += len;
  3212. while (xmlIsDocNameChar(doc, val)) {
  3213. val = xmlStringCurrentChar(NULL, cur, &len);
  3214. cur += len;
  3215. }
  3216. /* Should not test IS_BLANK(val) here -- see erratum E20*/
  3217. while (val == 0x20) {
  3218. while (val == 0x20) {
  3219. val = xmlStringCurrentChar(NULL, cur, &len);
  3220. cur += len;
  3221. }
  3222. if (!xmlIsDocNameStartChar(doc, val))
  3223. return(0);
  3224. val = xmlStringCurrentChar(NULL, cur, &len);
  3225. cur += len;
  3226. while (xmlIsDocNameChar(doc, val)) {
  3227. val = xmlStringCurrentChar(NULL, cur, &len);
  3228. cur += len;
  3229. }
  3230. }
  3231. if (val != 0) return(0);
  3232. return(1);
  3233. }
  3234. /**
  3235. * xmlValidateNamesValue:
  3236. * @value: an Names value
  3237. *
  3238. * Validate that the given value match Names production
  3239. *
  3240. * returns 1 if valid or 0 otherwise
  3241. */
  3242. int
  3243. xmlValidateNamesValue(const xmlChar *value) {
  3244. return(xmlValidateNamesValueInternal(NULL, value));
  3245. }
  3246. /**
  3247. * xmlValidateNmtokenValueInternal:
  3248. * @doc: pointer to the document or NULL
  3249. * @value: an Nmtoken value
  3250. *
  3251. * Validate that the given value match Nmtoken production
  3252. *
  3253. * [ VC: Name Token ]
  3254. *
  3255. * returns 1 if valid or 0 otherwise
  3256. */
  3257. static int
  3258. xmlValidateNmtokenValueInternal(xmlDocPtr doc, const xmlChar *value) {
  3259. const xmlChar *cur;
  3260. int val, len;
  3261. if (value == NULL) return(0);
  3262. cur = value;
  3263. val = xmlStringCurrentChar(NULL, cur, &len);
  3264. cur += len;
  3265. if (!xmlIsDocNameChar(doc, val))
  3266. return(0);
  3267. val = xmlStringCurrentChar(NULL, cur, &len);
  3268. cur += len;
  3269. while (xmlIsDocNameChar(doc, val)) {
  3270. val = xmlStringCurrentChar(NULL, cur, &len);
  3271. cur += len;
  3272. }
  3273. if (val != 0) return(0);
  3274. return(1);
  3275. }
  3276. /**
  3277. * xmlValidateNmtokenValue:
  3278. * @value: an Nmtoken value
  3279. *
  3280. * Validate that the given value match Nmtoken production
  3281. *
  3282. * [ VC: Name Token ]
  3283. *
  3284. * returns 1 if valid or 0 otherwise
  3285. */
  3286. int
  3287. xmlValidateNmtokenValue(const xmlChar *value) {
  3288. return(xmlValidateNmtokenValueInternal(NULL, value));
  3289. }
  3290. /**
  3291. * xmlValidateNmtokensValueInternal:
  3292. * @doc: pointer to the document or NULL
  3293. * @value: an Nmtokens value
  3294. *
  3295. * Validate that the given value match Nmtokens production
  3296. *
  3297. * [ VC: Name Token ]
  3298. *
  3299. * returns 1 if valid or 0 otherwise
  3300. */
  3301. static int
  3302. xmlValidateNmtokensValueInternal(xmlDocPtr doc, const xmlChar *value) {
  3303. const xmlChar *cur;
  3304. int val, len;
  3305. if (value == NULL) return(0);
  3306. cur = value;
  3307. val = xmlStringCurrentChar(NULL, cur, &len);
  3308. cur += len;
  3309. while (IS_BLANK(val)) {
  3310. val = xmlStringCurrentChar(NULL, cur, &len);
  3311. cur += len;
  3312. }
  3313. if (!xmlIsDocNameChar(doc, val))
  3314. return(0);
  3315. while (xmlIsDocNameChar(doc, val)) {
  3316. val = xmlStringCurrentChar(NULL, cur, &len);
  3317. cur += len;
  3318. }
  3319. /* Should not test IS_BLANK(val) here -- see erratum E20*/
  3320. while (val == 0x20) {
  3321. while (val == 0x20) {
  3322. val = xmlStringCurrentChar(NULL, cur, &len);
  3323. cur += len;
  3324. }
  3325. if (val == 0) return(1);
  3326. if (!xmlIsDocNameChar(doc, val))
  3327. return(0);
  3328. val = xmlStringCurrentChar(NULL, cur, &len);
  3329. cur += len;
  3330. while (xmlIsDocNameChar(doc, val)) {
  3331. val = xmlStringCurrentChar(NULL, cur, &len);
  3332. cur += len;
  3333. }
  3334. }
  3335. if (val != 0) return(0);
  3336. return(1);
  3337. }
  3338. /**
  3339. * xmlValidateNmtokensValue:
  3340. * @value: an Nmtokens value
  3341. *
  3342. * Validate that the given value match Nmtokens production
  3343. *
  3344. * [ VC: Name Token ]
  3345. *
  3346. * returns 1 if valid or 0 otherwise
  3347. */
  3348. int
  3349. xmlValidateNmtokensValue(const xmlChar *value) {
  3350. return(xmlValidateNmtokensValueInternal(NULL, value));
  3351. }
  3352. /**
  3353. * xmlValidateNotationDecl:
  3354. * @ctxt: the validation context
  3355. * @doc: a document instance
  3356. * @nota: a notation definition
  3357. *
  3358. * Try to validate a single notation definition
  3359. * basically it does the following checks as described by the
  3360. * XML-1.0 recommendation:
  3361. * - it seems that no validity constraint exists on notation declarations
  3362. * But this function get called anyway ...
  3363. *
  3364. * returns 1 if valid or 0 otherwise
  3365. */
  3366. int
  3367. xmlValidateNotationDecl(xmlValidCtxtPtr ctxt ATTRIBUTE_UNUSED, xmlDocPtr doc ATTRIBUTE_UNUSED,
  3368. xmlNotationPtr nota ATTRIBUTE_UNUSED) {
  3369. int ret = 1;
  3370. return(ret);
  3371. }
  3372. /**
  3373. * xmlValidateAttributeValueInternal:
  3374. * @doc: the document
  3375. * @type: an attribute type
  3376. * @value: an attribute value
  3377. *
  3378. * Validate that the given attribute value match the proper production
  3379. *
  3380. * returns 1 if valid or 0 otherwise
  3381. */
  3382. static int
  3383. xmlValidateAttributeValueInternal(xmlDocPtr doc, xmlAttributeType type,
  3384. const xmlChar *value) {
  3385. switch (type) {
  3386. case XML_ATTRIBUTE_ENTITIES:
  3387. case XML_ATTRIBUTE_IDREFS:
  3388. return(xmlValidateNamesValueInternal(doc, value));
  3389. case XML_ATTRIBUTE_ENTITY:
  3390. case XML_ATTRIBUTE_IDREF:
  3391. case XML_ATTRIBUTE_ID:
  3392. case XML_ATTRIBUTE_NOTATION:
  3393. return(xmlValidateNameValueInternal(doc, value));
  3394. case XML_ATTRIBUTE_NMTOKENS:
  3395. case XML_ATTRIBUTE_ENUMERATION:
  3396. return(xmlValidateNmtokensValueInternal(doc, value));
  3397. case XML_ATTRIBUTE_NMTOKEN:
  3398. return(xmlValidateNmtokenValueInternal(doc, value));
  3399. case XML_ATTRIBUTE_CDATA:
  3400. break;
  3401. }
  3402. return(1);
  3403. }
  3404. /**
  3405. * xmlValidateAttributeValue:
  3406. * @type: an attribute type
  3407. * @value: an attribute value
  3408. *
  3409. * Validate that the given attribute value match the proper production
  3410. *
  3411. * [ VC: ID ]
  3412. * Values of type ID must match the Name production....
  3413. *
  3414. * [ VC: IDREF ]
  3415. * Values of type IDREF must match the Name production, and values
  3416. * of type IDREFS must match Names ...
  3417. *
  3418. * [ VC: Entity Name ]
  3419. * Values of type ENTITY must match the Name production, values
  3420. * of type ENTITIES must match Names ...
  3421. *
  3422. * [ VC: Name Token ]
  3423. * Values of type NMTOKEN must match the Nmtoken production; values
  3424. * of type NMTOKENS must match Nmtokens.
  3425. *
  3426. * returns 1 if valid or 0 otherwise
  3427. */
  3428. int
  3429. xmlValidateAttributeValue(xmlAttributeType type, const xmlChar *value) {
  3430. return(xmlValidateAttributeValueInternal(NULL, type, value));
  3431. }
  3432. /**
  3433. * xmlValidateAttributeValue2:
  3434. * @ctxt: the validation context
  3435. * @doc: the document
  3436. * @name: the attribute name (used for error reporting only)
  3437. * @type: the attribute type
  3438. * @value: the attribute value
  3439. *
  3440. * Validate that the given attribute value match a given type.
  3441. * This typically cannot be done before having finished parsing
  3442. * the subsets.
  3443. *
  3444. * [ VC: IDREF ]
  3445. * Values of type IDREF must match one of the declared IDs
  3446. * Values of type IDREFS must match a sequence of the declared IDs
  3447. * each Name must match the value of an ID attribute on some element
  3448. * in the XML document; i.e. IDREF values must match the value of
  3449. * some ID attribute
  3450. *
  3451. * [ VC: Entity Name ]
  3452. * Values of type ENTITY must match one declared entity
  3453. * Values of type ENTITIES must match a sequence of declared entities
  3454. *
  3455. * [ VC: Notation Attributes ]
  3456. * all notation names in the declaration must be declared.
  3457. *
  3458. * returns 1 if valid or 0 otherwise
  3459. */
  3460. static int
  3461. xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  3462. const xmlChar *name, xmlAttributeType type, const xmlChar *value) {
  3463. int ret = 1;
  3464. switch (type) {
  3465. case XML_ATTRIBUTE_IDREFS:
  3466. case XML_ATTRIBUTE_IDREF:
  3467. case XML_ATTRIBUTE_ID:
  3468. case XML_ATTRIBUTE_NMTOKENS:
  3469. case XML_ATTRIBUTE_ENUMERATION:
  3470. case XML_ATTRIBUTE_NMTOKEN:
  3471. case XML_ATTRIBUTE_CDATA:
  3472. break;
  3473. case XML_ATTRIBUTE_ENTITY: {
  3474. xmlEntityPtr ent;
  3475. ent = xmlGetDocEntity(doc, value);
  3476. /* yeah it's a bit messy... */
  3477. if ((ent == NULL) && (doc->standalone == 1)) {
  3478. doc->standalone = 0;
  3479. ent = xmlGetDocEntity(doc, value);
  3480. }
  3481. if (ent == NULL) {
  3482. xmlErrValidNode(ctxt, (xmlNodePtr) doc,
  3483. XML_DTD_UNKNOWN_ENTITY,
  3484. "ENTITY attribute %s reference an unknown entity \"%s\"\n",
  3485. name, value, NULL);
  3486. ret = 0;
  3487. } else if (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
  3488. xmlErrValidNode(ctxt, (xmlNodePtr) doc,
  3489. XML_DTD_ENTITY_TYPE,
  3490. "ENTITY attribute %s reference an entity \"%s\" of wrong type\n",
  3491. name, value, NULL);
  3492. ret = 0;
  3493. }
  3494. break;
  3495. }
  3496. case XML_ATTRIBUTE_ENTITIES: {
  3497. xmlChar *dup, *nam = NULL, *cur, save;
  3498. xmlEntityPtr ent;
  3499. dup = xmlStrdup(value);
  3500. if (dup == NULL)
  3501. return(0);
  3502. cur = dup;
  3503. while (*cur != 0) {
  3504. nam = cur;
  3505. while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
  3506. save = *cur;
  3507. *cur = 0;
  3508. ent = xmlGetDocEntity(doc, nam);
  3509. if (ent == NULL) {
  3510. xmlErrValidNode(ctxt, (xmlNodePtr) doc,
  3511. XML_DTD_UNKNOWN_ENTITY,
  3512. "ENTITIES attribute %s reference an unknown entity \"%s\"\n",
  3513. name, nam, NULL);
  3514. ret = 0;
  3515. } else if (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
  3516. xmlErrValidNode(ctxt, (xmlNodePtr) doc,
  3517. XML_DTD_ENTITY_TYPE,
  3518. "ENTITIES attribute %s reference an entity \"%s\" of wrong type\n",
  3519. name, nam, NULL);
  3520. ret = 0;
  3521. }
  3522. if (save == 0)
  3523. break;
  3524. *cur = save;
  3525. while (IS_BLANK_CH(*cur)) cur++;
  3526. }
  3527. xmlFree(dup);
  3528. break;
  3529. }
  3530. case XML_ATTRIBUTE_NOTATION: {
  3531. xmlNotationPtr nota;
  3532. nota = xmlGetDtdNotationDesc(doc->intSubset, value);
  3533. if ((nota == NULL) && (doc->extSubset != NULL))
  3534. nota = xmlGetDtdNotationDesc(doc->extSubset, value);
  3535. if (nota == NULL) {
  3536. xmlErrValidNode(ctxt, (xmlNodePtr) doc,
  3537. XML_DTD_UNKNOWN_NOTATION,
  3538. "NOTATION attribute %s reference an unknown notation \"%s\"\n",
  3539. name, value, NULL);
  3540. ret = 0;
  3541. }
  3542. break;
  3543. }
  3544. }
  3545. return(ret);
  3546. }
  3547. /**
  3548. * xmlValidCtxtNormalizeAttributeValue:
  3549. * @ctxt: the validation context
  3550. * @doc: the document
  3551. * @elem: the parent
  3552. * @name: the attribute name
  3553. * @value: the attribute value
  3554. * @ctxt: the validation context or NULL
  3555. *
  3556. * Does the validation related extra step of the normalization of attribute
  3557. * values:
  3558. *
  3559. * If the declared value is not CDATA, then the XML processor must further
  3560. * process the normalized attribute value by discarding any leading and
  3561. * trailing space (#x20) characters, and by replacing sequences of space
  3562. * (#x20) characters by single space (#x20) character.
  3563. *
  3564. * Also check VC: Standalone Document Declaration in P32, and update
  3565. * ctxt->valid accordingly
  3566. *
  3567. * returns a new normalized string if normalization is needed, NULL otherwise
  3568. * the caller must free the returned value.
  3569. */
  3570. xmlChar *
  3571. xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  3572. xmlNodePtr elem, const xmlChar *name, const xmlChar *value) {
  3573. xmlChar *ret;
  3574. xmlAttributePtr attrDecl = NULL;
  3575. int extsubset = 0;
  3576. if (doc == NULL) return(NULL);
  3577. if (elem == NULL) return(NULL);
  3578. if (name == NULL) return(NULL);
  3579. if (value == NULL) return(NULL);
  3580. if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
  3581. xmlChar fn[50];
  3582. xmlChar *fullname;
  3583. fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
  3584. if (fullname == NULL)
  3585. return(NULL);
  3586. attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, name);
  3587. if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
  3588. attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname, name);
  3589. if (attrDecl != NULL)
  3590. extsubset = 1;
  3591. }
  3592. if ((fullname != fn) && (fullname != elem->name))
  3593. xmlFree(fullname);
  3594. }
  3595. if ((attrDecl == NULL) && (doc->intSubset != NULL))
  3596. attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name);
  3597. if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
  3598. attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, name);
  3599. if (attrDecl != NULL)
  3600. extsubset = 1;
  3601. }
  3602. if (attrDecl == NULL)
  3603. return(NULL);
  3604. if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
  3605. return(NULL);
  3606. ret = xmlStrdup(value);
  3607. if (ret == NULL)
  3608. return(NULL);
  3609. xmlValidNormalizeString(ret);
  3610. if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) {
  3611. xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE,
  3612. "standalone: %s on %s value had to be normalized based on external subset declaration\n",
  3613. name, elem->name, NULL);
  3614. ctxt->valid = 0;
  3615. }
  3616. return(ret);
  3617. }
  3618. /**
  3619. * xmlValidNormalizeAttributeValue:
  3620. * @doc: the document
  3621. * @elem: the parent
  3622. * @name: the attribute name
  3623. * @value: the attribute value
  3624. *
  3625. * Does the validation related extra step of the normalization of attribute
  3626. * values:
  3627. *
  3628. * If the declared value is not CDATA, then the XML processor must further
  3629. * process the normalized attribute value by discarding any leading and
  3630. * trailing space (#x20) characters, and by replacing sequences of space
  3631. * (#x20) characters by single space (#x20) character.
  3632. *
  3633. * Returns a new normalized string if normalization is needed, NULL otherwise
  3634. * the caller must free the returned value.
  3635. */
  3636. xmlChar *
  3637. xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
  3638. const xmlChar *name, const xmlChar *value) {
  3639. xmlChar *ret;
  3640. xmlAttributePtr attrDecl = NULL;
  3641. if (doc == NULL) return(NULL);
  3642. if (elem == NULL) return(NULL);
  3643. if (name == NULL) return(NULL);
  3644. if (value == NULL) return(NULL);
  3645. if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
  3646. xmlChar fn[50];
  3647. xmlChar *fullname;
  3648. fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
  3649. if (fullname == NULL)
  3650. return(NULL);
  3651. if ((fullname != fn) && (fullname != elem->name))
  3652. xmlFree(fullname);
  3653. }
  3654. attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name);
  3655. if ((attrDecl == NULL) && (doc->extSubset != NULL))
  3656. attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, name);
  3657. if (attrDecl == NULL)
  3658. return(NULL);
  3659. if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
  3660. return(NULL);
  3661. ret = xmlStrdup(value);
  3662. if (ret == NULL)
  3663. return(NULL);
  3664. xmlValidNormalizeString(ret);
  3665. return(ret);
  3666. }
  3667. static void
  3668. xmlValidateAttributeIdCallback(void *payload, void *data,
  3669. const xmlChar *name ATTRIBUTE_UNUSED) {
  3670. xmlAttributePtr attr = (xmlAttributePtr) payload;
  3671. int *count = (int *) data;
  3672. if (attr->atype == XML_ATTRIBUTE_ID) (*count)++;
  3673. }
  3674. /**
  3675. * xmlValidateAttributeDecl:
  3676. * @ctxt: the validation context
  3677. * @doc: a document instance
  3678. * @attr: an attribute definition
  3679. *
  3680. * Try to validate a single attribute definition
  3681. * basically it does the following checks as described by the
  3682. * XML-1.0 recommendation:
  3683. * - [ VC: Attribute Default Legal ]
  3684. * - [ VC: Enumeration ]
  3685. * - [ VC: ID Attribute Default ]
  3686. *
  3687. * The ID/IDREF uniqueness and matching are done separately
  3688. *
  3689. * returns 1 if valid or 0 otherwise
  3690. */
  3691. int
  3692. xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  3693. xmlAttributePtr attr) {
  3694. int ret = 1;
  3695. int val;
  3696. CHECK_DTD;
  3697. if(attr == NULL) return(1);
  3698. /* Attribute Default Legal */
  3699. /* Enumeration */
  3700. if (attr->defaultValue != NULL) {
  3701. val = xmlValidateAttributeValueInternal(doc, attr->atype,
  3702. attr->defaultValue);
  3703. if (val == 0) {
  3704. xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ATTRIBUTE_DEFAULT,
  3705. "Syntax of default value for attribute %s of %s is not valid\n",
  3706. attr->name, attr->elem, NULL);
  3707. }
  3708. ret &= val;
  3709. }
  3710. /* ID Attribute Default */
  3711. if ((attr->atype == XML_ATTRIBUTE_ID)&&
  3712. (attr->def != XML_ATTRIBUTE_IMPLIED) &&
  3713. (attr->def != XML_ATTRIBUTE_REQUIRED)) {
  3714. xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_FIXED,
  3715. "ID attribute %s of %s is not valid must be #IMPLIED or #REQUIRED\n",
  3716. attr->name, attr->elem, NULL);
  3717. ret = 0;
  3718. }
  3719. /* One ID per Element Type */
  3720. if (attr->atype == XML_ATTRIBUTE_ID) {
  3721. int nbId;
  3722. /* the trick is that we parse DtD as their own internal subset */
  3723. xmlElementPtr elem = xmlGetDtdElementDesc(doc->intSubset,
  3724. attr->elem);
  3725. if (elem != NULL) {
  3726. nbId = xmlScanIDAttributeDecl(NULL, elem, 0);
  3727. } else {
  3728. xmlAttributeTablePtr table;
  3729. /*
  3730. * The attribute may be declared in the internal subset and the
  3731. * element in the external subset.
  3732. */
  3733. nbId = 0;
  3734. if (doc->intSubset != NULL) {
  3735. table = (xmlAttributeTablePtr) doc->intSubset->attributes;
  3736. xmlHashScan3(table, NULL, NULL, attr->elem,
  3737. xmlValidateAttributeIdCallback, &nbId);
  3738. }
  3739. }
  3740. if (nbId > 1) {
  3741. xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
  3742. "Element %s has %d ID attribute defined in the internal subset : %s\n",
  3743. attr->elem, nbId, attr->name);
  3744. } else if (doc->extSubset != NULL) {
  3745. int extId = 0;
  3746. elem = xmlGetDtdElementDesc(doc->extSubset, attr->elem);
  3747. if (elem != NULL) {
  3748. extId = xmlScanIDAttributeDecl(NULL, elem, 0);
  3749. }
  3750. if (extId > 1) {
  3751. xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
  3752. "Element %s has %d ID attribute defined in the external subset : %s\n",
  3753. attr->elem, extId, attr->name);
  3754. } else if (extId + nbId > 1) {
  3755. xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
  3756. "Element %s has ID attributes defined in the internal and external subset : %s\n",
  3757. attr->elem, attr->name, NULL);
  3758. }
  3759. }
  3760. }
  3761. /* Validity Constraint: Enumeration */
  3762. if ((attr->defaultValue != NULL) && (attr->tree != NULL)) {
  3763. xmlEnumerationPtr tree = attr->tree;
  3764. while (tree != NULL) {
  3765. if (xmlStrEqual(tree->name, attr->defaultValue)) break;
  3766. tree = tree->next;
  3767. }
  3768. if (tree == NULL) {
  3769. xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ATTRIBUTE_VALUE,
  3770. "Default value \"%s\" for attribute %s of %s is not among the enumerated set\n",
  3771. attr->defaultValue, attr->name, attr->elem);
  3772. ret = 0;
  3773. }
  3774. }
  3775. return(ret);
  3776. }
  3777. /**
  3778. * xmlValidateElementDecl:
  3779. * @ctxt: the validation context
  3780. * @doc: a document instance
  3781. * @elem: an element definition
  3782. *
  3783. * Try to validate a single element definition
  3784. * basically it does the following checks as described by the
  3785. * XML-1.0 recommendation:
  3786. * - [ VC: One ID per Element Type ]
  3787. * - [ VC: No Duplicate Types ]
  3788. * - [ VC: Unique Element Type Declaration ]
  3789. *
  3790. * returns 1 if valid or 0 otherwise
  3791. */
  3792. int
  3793. xmlValidateElementDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  3794. xmlElementPtr elem) {
  3795. int ret = 1;
  3796. xmlElementPtr tst;
  3797. CHECK_DTD;
  3798. if (elem == NULL) return(1);
  3799. #if 0
  3800. #ifdef LIBXML_REGEXP_ENABLED
  3801. /* Build the regexp associated to the content model */
  3802. ret = xmlValidBuildContentModel(ctxt, elem);
  3803. #endif
  3804. #endif
  3805. /* No Duplicate Types */
  3806. if (elem->etype == XML_ELEMENT_TYPE_MIXED) {
  3807. xmlElementContentPtr cur, next;
  3808. const xmlChar *name;
  3809. cur = elem->content;
  3810. while (cur != NULL) {
  3811. if (cur->type != XML_ELEMENT_CONTENT_OR) break;
  3812. if (cur->c1 == NULL) break;
  3813. if (cur->c1->type == XML_ELEMENT_CONTENT_ELEMENT) {
  3814. name = cur->c1->name;
  3815. next = cur->c2;
  3816. while (next != NULL) {
  3817. if (next->type == XML_ELEMENT_CONTENT_ELEMENT) {
  3818. if ((xmlStrEqual(next->name, name)) &&
  3819. (xmlStrEqual(next->prefix, cur->c1->prefix))) {
  3820. if (cur->c1->prefix == NULL) {
  3821. xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
  3822. "Definition of %s has duplicate references of %s\n",
  3823. elem->name, name, NULL);
  3824. } else {
  3825. xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
  3826. "Definition of %s has duplicate references of %s:%s\n",
  3827. elem->name, cur->c1->prefix, name);
  3828. }
  3829. ret = 0;
  3830. }
  3831. break;
  3832. }
  3833. if (next->c1 == NULL) break;
  3834. if (next->c1->type != XML_ELEMENT_CONTENT_ELEMENT) break;
  3835. if ((xmlStrEqual(next->c1->name, name)) &&
  3836. (xmlStrEqual(next->c1->prefix, cur->c1->prefix))) {
  3837. if (cur->c1->prefix == NULL) {
  3838. xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
  3839. "Definition of %s has duplicate references to %s\n",
  3840. elem->name, name, NULL);
  3841. } else {
  3842. xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
  3843. "Definition of %s has duplicate references to %s:%s\n",
  3844. elem->name, cur->c1->prefix, name);
  3845. }
  3846. ret = 0;
  3847. }
  3848. next = next->c2;
  3849. }
  3850. }
  3851. cur = cur->c2;
  3852. }
  3853. }
  3854. /* VC: Unique Element Type Declaration */
  3855. tst = xmlGetDtdElementDesc(doc->intSubset, elem->name);
  3856. if ((tst != NULL ) && (tst != elem) &&
  3857. ((tst->prefix == elem->prefix) ||
  3858. (xmlStrEqual(tst->prefix, elem->prefix))) &&
  3859. (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
  3860. xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED,
  3861. "Redefinition of element %s\n",
  3862. elem->name, NULL, NULL);
  3863. ret = 0;
  3864. }
  3865. tst = xmlGetDtdElementDesc(doc->extSubset, elem->name);
  3866. if ((tst != NULL ) && (tst != elem) &&
  3867. ((tst->prefix == elem->prefix) ||
  3868. (xmlStrEqual(tst->prefix, elem->prefix))) &&
  3869. (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
  3870. xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED,
  3871. "Redefinition of element %s\n",
  3872. elem->name, NULL, NULL);
  3873. ret = 0;
  3874. }
  3875. /* One ID per Element Type
  3876. * already done when registering the attribute
  3877. if (xmlScanIDAttributeDecl(ctxt, elem) > 1) {
  3878. ret = 0;
  3879. } */
  3880. return(ret);
  3881. }
  3882. /**
  3883. * xmlValidateOneAttribute:
  3884. * @ctxt: the validation context
  3885. * @doc: a document instance
  3886. * @elem: an element instance
  3887. * @attr: an attribute instance
  3888. * @value: the attribute value (without entities processing)
  3889. *
  3890. * Try to validate a single attribute for an element
  3891. * basically it does the following checks as described by the
  3892. * XML-1.0 recommendation:
  3893. * - [ VC: Attribute Value Type ]
  3894. * - [ VC: Fixed Attribute Default ]
  3895. * - [ VC: Entity Name ]
  3896. * - [ VC: Name Token ]
  3897. * - [ VC: ID ]
  3898. * - [ VC: IDREF ]
  3899. * - [ VC: Entity Name ]
  3900. * - [ VC: Notation Attributes ]
  3901. *
  3902. * The ID/IDREF uniqueness and matching are done separately
  3903. *
  3904. * returns 1 if valid or 0 otherwise
  3905. */
  3906. int
  3907. xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  3908. xmlNodePtr elem, xmlAttrPtr attr, const xmlChar *value)
  3909. {
  3910. xmlAttributePtr attrDecl = NULL;
  3911. int val;
  3912. int ret = 1;
  3913. CHECK_DTD;
  3914. if ((elem == NULL) || (elem->name == NULL)) return(0);
  3915. if ((attr == NULL) || (attr->name == NULL)) return(0);
  3916. if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
  3917. xmlChar fn[50];
  3918. xmlChar *fullname;
  3919. fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
  3920. if (fullname == NULL)
  3921. return(0);
  3922. if (attr->ns != NULL) {
  3923. attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
  3924. attr->name, attr->ns->prefix);
  3925. if ((attrDecl == NULL) && (doc->extSubset != NULL))
  3926. attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
  3927. attr->name, attr->ns->prefix);
  3928. } else {
  3929. attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, attr->name);
  3930. if ((attrDecl == NULL) && (doc->extSubset != NULL))
  3931. attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
  3932. fullname, attr->name);
  3933. }
  3934. if ((fullname != fn) && (fullname != elem->name))
  3935. xmlFree(fullname);
  3936. }
  3937. if (attrDecl == NULL) {
  3938. if (attr->ns != NULL) {
  3939. attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
  3940. attr->name, attr->ns->prefix);
  3941. if ((attrDecl == NULL) && (doc->extSubset != NULL))
  3942. attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
  3943. attr->name, attr->ns->prefix);
  3944. } else {
  3945. attrDecl = xmlGetDtdAttrDesc(doc->intSubset,
  3946. elem->name, attr->name);
  3947. if ((attrDecl == NULL) && (doc->extSubset != NULL))
  3948. attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
  3949. elem->name, attr->name);
  3950. }
  3951. }
  3952. /* Validity Constraint: Attribute Value Type */
  3953. if (attrDecl == NULL) {
  3954. xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE,
  3955. "No declaration for attribute %s of element %s\n",
  3956. attr->name, elem->name, NULL);
  3957. return(0);
  3958. }
  3959. attr->atype = attrDecl->atype;
  3960. val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
  3961. if (val == 0) {
  3962. xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
  3963. "Syntax of value for attribute %s of %s is not valid\n",
  3964. attr->name, elem->name, NULL);
  3965. ret = 0;
  3966. }
  3967. /* Validity constraint: Fixed Attribute Default */
  3968. if (attrDecl->def == XML_ATTRIBUTE_FIXED) {
  3969. if (!xmlStrEqual(value, attrDecl->defaultValue)) {
  3970. xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT,
  3971. "Value for attribute %s of %s is different from default \"%s\"\n",
  3972. attr->name, elem->name, attrDecl->defaultValue);
  3973. ret = 0;
  3974. }
  3975. }
  3976. /* Validity Constraint: ID uniqueness */
  3977. if (attrDecl->atype == XML_ATTRIBUTE_ID) {
  3978. if (xmlAddID(ctxt, doc, value, attr) == NULL)
  3979. ret = 0;
  3980. }
  3981. if ((attrDecl->atype == XML_ATTRIBUTE_IDREF) ||
  3982. (attrDecl->atype == XML_ATTRIBUTE_IDREFS)) {
  3983. if (xmlAddRef(ctxt, doc, value, attr) == NULL)
  3984. ret = 0;
  3985. }
  3986. /* Validity Constraint: Notation Attributes */
  3987. if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
  3988. xmlEnumerationPtr tree = attrDecl->tree;
  3989. xmlNotationPtr nota;
  3990. /* First check that the given NOTATION was declared */
  3991. nota = xmlGetDtdNotationDesc(doc->intSubset, value);
  3992. if (nota == NULL)
  3993. nota = xmlGetDtdNotationDesc(doc->extSubset, value);
  3994. if (nota == NULL) {
  3995. xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION,
  3996. "Value \"%s\" for attribute %s of %s is not a declared Notation\n",
  3997. value, attr->name, elem->name);
  3998. ret = 0;
  3999. }
  4000. /* Second, verify that it's among the list */
  4001. while (tree != NULL) {
  4002. if (xmlStrEqual(tree->name, value)) break;
  4003. tree = tree->next;
  4004. }
  4005. if (tree == NULL) {
  4006. xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE,
  4007. "Value \"%s\" for attribute %s of %s is not among the enumerated notations\n",
  4008. value, attr->name, elem->name);
  4009. ret = 0;
  4010. }
  4011. }
  4012. /* Validity Constraint: Enumeration */
  4013. if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) {
  4014. xmlEnumerationPtr tree = attrDecl->tree;
  4015. while (tree != NULL) {
  4016. if (xmlStrEqual(tree->name, value)) break;
  4017. tree = tree->next;
  4018. }
  4019. if (tree == NULL) {
  4020. xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
  4021. "Value \"%s\" for attribute %s of %s is not among the enumerated set\n",
  4022. value, attr->name, elem->name);
  4023. ret = 0;
  4024. }
  4025. }
  4026. /* Fixed Attribute Default */
  4027. if ((attrDecl->def == XML_ATTRIBUTE_FIXED) &&
  4028. (!xmlStrEqual(attrDecl->defaultValue, value))) {
  4029. xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
  4030. "Value for attribute %s of %s must be \"%s\"\n",
  4031. attr->name, elem->name, attrDecl->defaultValue);
  4032. ret = 0;
  4033. }
  4034. /* Extra check for the attribute value */
  4035. ret &= xmlValidateAttributeValue2(ctxt, doc, attr->name,
  4036. attrDecl->atype, value);
  4037. return(ret);
  4038. }
  4039. /**
  4040. * xmlValidateOneNamespace:
  4041. * @ctxt: the validation context
  4042. * @doc: a document instance
  4043. * @elem: an element instance
  4044. * @prefix: the namespace prefix
  4045. * @ns: an namespace declaration instance
  4046. * @value: the attribute value (without entities processing)
  4047. *
  4048. * Try to validate a single namespace declaration for an element
  4049. * basically it does the following checks as described by the
  4050. * XML-1.0 recommendation:
  4051. * - [ VC: Attribute Value Type ]
  4052. * - [ VC: Fixed Attribute Default ]
  4053. * - [ VC: Entity Name ]
  4054. * - [ VC: Name Token ]
  4055. * - [ VC: ID ]
  4056. * - [ VC: IDREF ]
  4057. * - [ VC: Entity Name ]
  4058. * - [ VC: Notation Attributes ]
  4059. *
  4060. * The ID/IDREF uniqueness and matching are done separately
  4061. *
  4062. * returns 1 if valid or 0 otherwise
  4063. */
  4064. int
  4065. xmlValidateOneNamespace(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  4066. xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) {
  4067. /* xmlElementPtr elemDecl; */
  4068. xmlAttributePtr attrDecl = NULL;
  4069. int val;
  4070. int ret = 1;
  4071. CHECK_DTD;
  4072. if ((elem == NULL) || (elem->name == NULL)) return(0);
  4073. if ((ns == NULL) || (ns->href == NULL)) return(0);
  4074. if (prefix != NULL) {
  4075. xmlChar fn[50];
  4076. xmlChar *fullname;
  4077. fullname = xmlBuildQName(elem->name, prefix, fn, 50);
  4078. if (fullname == NULL) {
  4079. xmlVErrMemory(ctxt, "Validating namespace");
  4080. return(0);
  4081. }
  4082. if (ns->prefix != NULL) {
  4083. attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
  4084. ns->prefix, BAD_CAST "xmlns");
  4085. if ((attrDecl == NULL) && (doc->extSubset != NULL))
  4086. attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
  4087. ns->prefix, BAD_CAST "xmlns");
  4088. } else {
  4089. attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname,
  4090. BAD_CAST "xmlns");
  4091. if ((attrDecl == NULL) && (doc->extSubset != NULL))
  4092. attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname,
  4093. BAD_CAST "xmlns");
  4094. }
  4095. if ((fullname != fn) && (fullname != elem->name))
  4096. xmlFree(fullname);
  4097. }
  4098. if (attrDecl == NULL) {
  4099. if (ns->prefix != NULL) {
  4100. attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
  4101. ns->prefix, BAD_CAST "xmlns");
  4102. if ((attrDecl == NULL) && (doc->extSubset != NULL))
  4103. attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
  4104. ns->prefix, BAD_CAST "xmlns");
  4105. } else {
  4106. attrDecl = xmlGetDtdAttrDesc(doc->intSubset,
  4107. elem->name, BAD_CAST "xmlns");
  4108. if ((attrDecl == NULL) && (doc->extSubset != NULL))
  4109. attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
  4110. elem->name, BAD_CAST "xmlns");
  4111. }
  4112. }
  4113. /* Validity Constraint: Attribute Value Type */
  4114. if (attrDecl == NULL) {
  4115. if (ns->prefix != NULL) {
  4116. xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE,
  4117. "No declaration for attribute xmlns:%s of element %s\n",
  4118. ns->prefix, elem->name, NULL);
  4119. } else {
  4120. xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE,
  4121. "No declaration for attribute xmlns of element %s\n",
  4122. elem->name, NULL, NULL);
  4123. }
  4124. return(0);
  4125. }
  4126. val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
  4127. if (val == 0) {
  4128. if (ns->prefix != NULL) {
  4129. xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_DEFAULT,
  4130. "Syntax of value for attribute xmlns:%s of %s is not valid\n",
  4131. ns->prefix, elem->name, NULL);
  4132. } else {
  4133. xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_DEFAULT,
  4134. "Syntax of value for attribute xmlns of %s is not valid\n",
  4135. elem->name, NULL, NULL);
  4136. }
  4137. ret = 0;
  4138. }
  4139. /* Validity constraint: Fixed Attribute Default */
  4140. if (attrDecl->def == XML_ATTRIBUTE_FIXED) {
  4141. if (!xmlStrEqual(value, attrDecl->defaultValue)) {
  4142. if (ns->prefix != NULL) {
  4143. xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT,
  4144. "Value for attribute xmlns:%s of %s is different from default \"%s\"\n",
  4145. ns->prefix, elem->name, attrDecl->defaultValue);
  4146. } else {
  4147. xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT,
  4148. "Value for attribute xmlns of %s is different from default \"%s\"\n",
  4149. elem->name, attrDecl->defaultValue, NULL);
  4150. }
  4151. ret = 0;
  4152. }
  4153. }
  4154. /*
  4155. * Casting ns to xmlAttrPtr is wrong. We'd need separate functions
  4156. * xmlAddID and xmlAddRef for namespace declarations, but it makes
  4157. * no practical sense to use ID types anyway.
  4158. */
  4159. #if 0
  4160. /* Validity Constraint: ID uniqueness */
  4161. if (attrDecl->atype == XML_ATTRIBUTE_ID) {
  4162. if (xmlAddID(ctxt, doc, value, (xmlAttrPtr) ns) == NULL)
  4163. ret = 0;
  4164. }
  4165. if ((attrDecl->atype == XML_ATTRIBUTE_IDREF) ||
  4166. (attrDecl->atype == XML_ATTRIBUTE_IDREFS)) {
  4167. if (xmlAddRef(ctxt, doc, value, (xmlAttrPtr) ns) == NULL)
  4168. ret = 0;
  4169. }
  4170. #endif
  4171. /* Validity Constraint: Notation Attributes */
  4172. if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
  4173. xmlEnumerationPtr tree = attrDecl->tree;
  4174. xmlNotationPtr nota;
  4175. /* First check that the given NOTATION was declared */
  4176. nota = xmlGetDtdNotationDesc(doc->intSubset, value);
  4177. if (nota == NULL)
  4178. nota = xmlGetDtdNotationDesc(doc->extSubset, value);
  4179. if (nota == NULL) {
  4180. if (ns->prefix != NULL) {
  4181. xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION,
  4182. "Value \"%s\" for attribute xmlns:%s of %s is not a declared Notation\n",
  4183. value, ns->prefix, elem->name);
  4184. } else {
  4185. xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION,
  4186. "Value \"%s\" for attribute xmlns of %s is not a declared Notation\n",
  4187. value, elem->name, NULL);
  4188. }
  4189. ret = 0;
  4190. }
  4191. /* Second, verify that it's among the list */
  4192. while (tree != NULL) {
  4193. if (xmlStrEqual(tree->name, value)) break;
  4194. tree = tree->next;
  4195. }
  4196. if (tree == NULL) {
  4197. if (ns->prefix != NULL) {
  4198. xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE,
  4199. "Value \"%s\" for attribute xmlns:%s of %s is not among the enumerated notations\n",
  4200. value, ns->prefix, elem->name);
  4201. } else {
  4202. xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE,
  4203. "Value \"%s\" for attribute xmlns of %s is not among the enumerated notations\n",
  4204. value, elem->name, NULL);
  4205. }
  4206. ret = 0;
  4207. }
  4208. }
  4209. /* Validity Constraint: Enumeration */
  4210. if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) {
  4211. xmlEnumerationPtr tree = attrDecl->tree;
  4212. while (tree != NULL) {
  4213. if (xmlStrEqual(tree->name, value)) break;
  4214. tree = tree->next;
  4215. }
  4216. if (tree == NULL) {
  4217. if (ns->prefix != NULL) {
  4218. xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
  4219. "Value \"%s\" for attribute xmlns:%s of %s is not among the enumerated set\n",
  4220. value, ns->prefix, elem->name);
  4221. } else {
  4222. xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
  4223. "Value \"%s\" for attribute xmlns of %s is not among the enumerated set\n",
  4224. value, elem->name, NULL);
  4225. }
  4226. ret = 0;
  4227. }
  4228. }
  4229. /* Fixed Attribute Default */
  4230. if ((attrDecl->def == XML_ATTRIBUTE_FIXED) &&
  4231. (!xmlStrEqual(attrDecl->defaultValue, value))) {
  4232. if (ns->prefix != NULL) {
  4233. xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE,
  4234. "Value for attribute xmlns:%s of %s must be \"%s\"\n",
  4235. ns->prefix, elem->name, attrDecl->defaultValue);
  4236. } else {
  4237. xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE,
  4238. "Value for attribute xmlns of %s must be \"%s\"\n",
  4239. elem->name, attrDecl->defaultValue, NULL);
  4240. }
  4241. ret = 0;
  4242. }
  4243. /* Extra check for the attribute value */
  4244. if (ns->prefix != NULL) {
  4245. ret &= xmlValidateAttributeValue2(ctxt, doc, ns->prefix,
  4246. attrDecl->atype, value);
  4247. } else {
  4248. ret &= xmlValidateAttributeValue2(ctxt, doc, BAD_CAST "xmlns",
  4249. attrDecl->atype, value);
  4250. }
  4251. return(ret);
  4252. }
  4253. #ifndef LIBXML_REGEXP_ENABLED
  4254. /**
  4255. * xmlValidateSkipIgnorable:
  4256. * @ctxt: the validation context
  4257. * @child: the child list
  4258. *
  4259. * Skip ignorable elements w.r.t. the validation process
  4260. *
  4261. * returns the first element to consider for validation of the content model
  4262. */
  4263. static xmlNodePtr
  4264. xmlValidateSkipIgnorable(xmlNodePtr child) {
  4265. while (child != NULL) {
  4266. switch (child->type) {
  4267. /* These things are ignored (skipped) during validation. */
  4268. case XML_PI_NODE:
  4269. case XML_COMMENT_NODE:
  4270. case XML_XINCLUDE_START:
  4271. case XML_XINCLUDE_END:
  4272. child = child->next;
  4273. break;
  4274. case XML_TEXT_NODE:
  4275. if (xmlIsBlankNode(child))
  4276. child = child->next;
  4277. else
  4278. return(child);
  4279. break;
  4280. /* keep current node */
  4281. default:
  4282. return(child);
  4283. }
  4284. }
  4285. return(child);
  4286. }
  4287. /**
  4288. * xmlValidateElementType:
  4289. * @ctxt: the validation context
  4290. *
  4291. * Try to validate the content model of an element internal function
  4292. *
  4293. * returns 1 if valid or 0 ,-1 in case of error, -2 if an entity
  4294. * reference is found and -3 if the validation succeeded but
  4295. * the content model is not determinist.
  4296. */
  4297. static int
  4298. xmlValidateElementType(xmlValidCtxtPtr ctxt) {
  4299. int ret = -1;
  4300. int determinist = 1;
  4301. NODE = xmlValidateSkipIgnorable(NODE);
  4302. if ((NODE == NULL) && (CONT == NULL))
  4303. return(1);
  4304. if ((NODE == NULL) &&
  4305. ((CONT->ocur == XML_ELEMENT_CONTENT_MULT) ||
  4306. (CONT->ocur == XML_ELEMENT_CONTENT_OPT))) {
  4307. return(1);
  4308. }
  4309. if (CONT == NULL) return(-1);
  4310. if ((NODE != NULL) && (NODE->type == XML_ENTITY_REF_NODE))
  4311. return(-2);
  4312. /*
  4313. * We arrive here when more states need to be examined
  4314. */
  4315. cont:
  4316. /*
  4317. * We just recovered from a rollback generated by a possible
  4318. * epsilon transition, go directly to the analysis phase
  4319. */
  4320. if (STATE == ROLLBACK_PARENT) {
  4321. ret = 1;
  4322. goto analyze;
  4323. }
  4324. /*
  4325. * we may have to save a backup state here. This is the equivalent
  4326. * of handling epsilon transition in NFAs.
  4327. */
  4328. if ((CONT != NULL) &&
  4329. ((CONT->parent == NULL) ||
  4330. (CONT->parent == (xmlElementContentPtr) 1) ||
  4331. (CONT->parent->type != XML_ELEMENT_CONTENT_OR)) &&
  4332. ((CONT->ocur == XML_ELEMENT_CONTENT_MULT) ||
  4333. (CONT->ocur == XML_ELEMENT_CONTENT_OPT) ||
  4334. ((CONT->ocur == XML_ELEMENT_CONTENT_PLUS) && (OCCURRENCE)))) {
  4335. if (vstateVPush(ctxt, CONT, NODE, DEPTH, OCCURS, ROLLBACK_PARENT) < 0)
  4336. return(0);
  4337. }
  4338. /*
  4339. * Check first if the content matches
  4340. */
  4341. switch (CONT->type) {
  4342. case XML_ELEMENT_CONTENT_PCDATA:
  4343. if (NODE == NULL) {
  4344. ret = 0;
  4345. break;
  4346. }
  4347. if (NODE->type == XML_TEXT_NODE) {
  4348. /*
  4349. * go to next element in the content model
  4350. * skipping ignorable elems
  4351. */
  4352. do {
  4353. NODE = NODE->next;
  4354. NODE = xmlValidateSkipIgnorable(NODE);
  4355. if ((NODE != NULL) &&
  4356. (NODE->type == XML_ENTITY_REF_NODE))
  4357. return(-2);
  4358. } while ((NODE != NULL) &&
  4359. ((NODE->type != XML_ELEMENT_NODE) &&
  4360. (NODE->type != XML_TEXT_NODE) &&
  4361. (NODE->type != XML_CDATA_SECTION_NODE)));
  4362. ret = 1;
  4363. break;
  4364. } else {
  4365. ret = 0;
  4366. break;
  4367. }
  4368. break;
  4369. case XML_ELEMENT_CONTENT_ELEMENT:
  4370. if (NODE == NULL) {
  4371. ret = 0;
  4372. break;
  4373. }
  4374. ret = ((NODE->type == XML_ELEMENT_NODE) &&
  4375. (xmlStrEqual(NODE->name, CONT->name)));
  4376. if (ret == 1) {
  4377. if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) {
  4378. ret = (CONT->prefix == NULL);
  4379. } else if (CONT->prefix == NULL) {
  4380. ret = 0;
  4381. } else {
  4382. ret = xmlStrEqual(NODE->ns->prefix, CONT->prefix);
  4383. }
  4384. }
  4385. if (ret == 1) {
  4386. /*
  4387. * go to next element in the content model
  4388. * skipping ignorable elems
  4389. */
  4390. do {
  4391. NODE = NODE->next;
  4392. NODE = xmlValidateSkipIgnorable(NODE);
  4393. if ((NODE != NULL) &&
  4394. (NODE->type == XML_ENTITY_REF_NODE))
  4395. return(-2);
  4396. } while ((NODE != NULL) &&
  4397. ((NODE->type != XML_ELEMENT_NODE) &&
  4398. (NODE->type != XML_TEXT_NODE) &&
  4399. (NODE->type != XML_CDATA_SECTION_NODE)));
  4400. } else {
  4401. ret = 0;
  4402. break;
  4403. }
  4404. break;
  4405. case XML_ELEMENT_CONTENT_OR:
  4406. /*
  4407. * Small optimization.
  4408. */
  4409. if (CONT->c1->type == XML_ELEMENT_CONTENT_ELEMENT) {
  4410. if ((NODE == NULL) ||
  4411. (!xmlStrEqual(NODE->name, CONT->c1->name))) {
  4412. DEPTH++;
  4413. CONT = CONT->c2;
  4414. goto cont;
  4415. }
  4416. if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) {
  4417. ret = (CONT->c1->prefix == NULL);
  4418. } else if (CONT->c1->prefix == NULL) {
  4419. ret = 0;
  4420. } else {
  4421. ret = xmlStrEqual(NODE->ns->prefix, CONT->c1->prefix);
  4422. }
  4423. if (ret == 0) {
  4424. DEPTH++;
  4425. CONT = CONT->c2;
  4426. goto cont;
  4427. }
  4428. }
  4429. /*
  4430. * save the second branch 'or' branch
  4431. */
  4432. if (vstateVPush(ctxt, CONT->c2, NODE, DEPTH + 1,
  4433. OCCURS, ROLLBACK_OR) < 0)
  4434. return(-1);
  4435. DEPTH++;
  4436. CONT = CONT->c1;
  4437. goto cont;
  4438. case XML_ELEMENT_CONTENT_SEQ:
  4439. /*
  4440. * Small optimization.
  4441. */
  4442. if ((CONT->c1->type == XML_ELEMENT_CONTENT_ELEMENT) &&
  4443. ((CONT->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
  4444. (CONT->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
  4445. if ((NODE == NULL) ||
  4446. (!xmlStrEqual(NODE->name, CONT->c1->name))) {
  4447. DEPTH++;
  4448. CONT = CONT->c2;
  4449. goto cont;
  4450. }
  4451. if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) {
  4452. ret = (CONT->c1->prefix == NULL);
  4453. } else if (CONT->c1->prefix == NULL) {
  4454. ret = 0;
  4455. } else {
  4456. ret = xmlStrEqual(NODE->ns->prefix, CONT->c1->prefix);
  4457. }
  4458. if (ret == 0) {
  4459. DEPTH++;
  4460. CONT = CONT->c2;
  4461. goto cont;
  4462. }
  4463. }
  4464. DEPTH++;
  4465. CONT = CONT->c1;
  4466. goto cont;
  4467. }
  4468. /*
  4469. * At this point handle going up in the tree
  4470. */
  4471. if (ret == -1) {
  4472. return(ret);
  4473. }
  4474. analyze:
  4475. while (CONT != NULL) {
  4476. /*
  4477. * First do the analysis depending on the occurrence model at
  4478. * this level.
  4479. */
  4480. if (ret == 0) {
  4481. switch (CONT->ocur) {
  4482. xmlNodePtr cur;
  4483. case XML_ELEMENT_CONTENT_ONCE:
  4484. cur = ctxt->vstate->node;
  4485. if (vstateVPop(ctxt) < 0 ) {
  4486. return(0);
  4487. }
  4488. if (cur != ctxt->vstate->node)
  4489. determinist = -3;
  4490. goto cont;
  4491. case XML_ELEMENT_CONTENT_PLUS:
  4492. if (OCCURRENCE == 0) {
  4493. cur = ctxt->vstate->node;
  4494. if (vstateVPop(ctxt) < 0 ) {
  4495. return(0);
  4496. }
  4497. if (cur != ctxt->vstate->node)
  4498. determinist = -3;
  4499. goto cont;
  4500. }
  4501. ret = 1;
  4502. break;
  4503. case XML_ELEMENT_CONTENT_MULT:
  4504. ret = 1;
  4505. break;
  4506. case XML_ELEMENT_CONTENT_OPT:
  4507. ret = 1;
  4508. break;
  4509. }
  4510. } else {
  4511. switch (CONT->ocur) {
  4512. case XML_ELEMENT_CONTENT_OPT:
  4513. ret = 1;
  4514. break;
  4515. case XML_ELEMENT_CONTENT_ONCE:
  4516. ret = 1;
  4517. break;
  4518. case XML_ELEMENT_CONTENT_PLUS:
  4519. if (STATE == ROLLBACK_PARENT) {
  4520. ret = 1;
  4521. break;
  4522. }
  4523. if (NODE == NULL) {
  4524. ret = 1;
  4525. break;
  4526. }
  4527. SET_OCCURRENCE;
  4528. goto cont;
  4529. case XML_ELEMENT_CONTENT_MULT:
  4530. if (STATE == ROLLBACK_PARENT) {
  4531. ret = 1;
  4532. break;
  4533. }
  4534. if (NODE == NULL) {
  4535. ret = 1;
  4536. break;
  4537. }
  4538. /* SET_OCCURRENCE; */
  4539. goto cont;
  4540. }
  4541. }
  4542. STATE = 0;
  4543. /*
  4544. * Then act accordingly at the parent level
  4545. */
  4546. RESET_OCCURRENCE;
  4547. if ((CONT->parent == NULL) ||
  4548. (CONT->parent == (xmlElementContentPtr) 1))
  4549. break;
  4550. switch (CONT->parent->type) {
  4551. case XML_ELEMENT_CONTENT_PCDATA:
  4552. return(-1);
  4553. case XML_ELEMENT_CONTENT_ELEMENT:
  4554. return(-1);
  4555. case XML_ELEMENT_CONTENT_OR:
  4556. if (ret == 1) {
  4557. CONT = CONT->parent;
  4558. DEPTH--;
  4559. } else {
  4560. CONT = CONT->parent;
  4561. DEPTH--;
  4562. }
  4563. break;
  4564. case XML_ELEMENT_CONTENT_SEQ:
  4565. if (ret == 0) {
  4566. CONT = CONT->parent;
  4567. DEPTH--;
  4568. } else if (CONT == CONT->parent->c1) {
  4569. CONT = CONT->parent->c2;
  4570. goto cont;
  4571. } else {
  4572. CONT = CONT->parent;
  4573. DEPTH--;
  4574. }
  4575. }
  4576. }
  4577. if (NODE != NULL) {
  4578. xmlNodePtr cur;
  4579. cur = ctxt->vstate->node;
  4580. if (vstateVPop(ctxt) < 0 ) {
  4581. return(0);
  4582. }
  4583. if (cur != ctxt->vstate->node)
  4584. determinist = -3;
  4585. goto cont;
  4586. }
  4587. if (ret == 0) {
  4588. xmlNodePtr cur;
  4589. cur = ctxt->vstate->node;
  4590. if (vstateVPop(ctxt) < 0 ) {
  4591. return(0);
  4592. }
  4593. if (cur != ctxt->vstate->node)
  4594. determinist = -3;
  4595. goto cont;
  4596. }
  4597. return(determinist);
  4598. }
  4599. #endif
  4600. /**
  4601. * xmlSnprintfElements:
  4602. * @buf: an output buffer
  4603. * @size: the size of the buffer
  4604. * @content: An element
  4605. * @glob: 1 if one must print the englobing parenthesis, 0 otherwise
  4606. *
  4607. * This will dump the list of elements to the buffer
  4608. * Intended just for the debug routine
  4609. */
  4610. static void
  4611. xmlSnprintfElements(char *buf, int size, xmlNodePtr node, int glob) {
  4612. xmlNodePtr cur;
  4613. int len;
  4614. if (node == NULL) return;
  4615. if (glob) strcat(buf, "(");
  4616. cur = node;
  4617. while (cur != NULL) {
  4618. len = strlen(buf);
  4619. if (size - len < 50) {
  4620. if ((size - len > 4) && (buf[len - 1] != '.'))
  4621. strcat(buf, " ...");
  4622. return;
  4623. }
  4624. switch (cur->type) {
  4625. case XML_ELEMENT_NODE:
  4626. if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
  4627. if (size - len < xmlStrlen(cur->ns->prefix) + 10) {
  4628. if ((size - len > 4) && (buf[len - 1] != '.'))
  4629. strcat(buf, " ...");
  4630. return;
  4631. }
  4632. strcat(buf, (char *) cur->ns->prefix);
  4633. strcat(buf, ":");
  4634. }
  4635. if (size - len < xmlStrlen(cur->name) + 10) {
  4636. if ((size - len > 4) && (buf[len - 1] != '.'))
  4637. strcat(buf, " ...");
  4638. return;
  4639. }
  4640. strcat(buf, (char *) cur->name);
  4641. if (cur->next != NULL)
  4642. strcat(buf, " ");
  4643. break;
  4644. case XML_TEXT_NODE:
  4645. if (xmlIsBlankNode(cur))
  4646. break;
  4647. /* Falls through. */
  4648. case XML_CDATA_SECTION_NODE:
  4649. case XML_ENTITY_REF_NODE:
  4650. strcat(buf, "CDATA");
  4651. if (cur->next != NULL)
  4652. strcat(buf, " ");
  4653. break;
  4654. case XML_ATTRIBUTE_NODE:
  4655. case XML_DOCUMENT_NODE:
  4656. case XML_HTML_DOCUMENT_NODE:
  4657. case XML_DOCUMENT_TYPE_NODE:
  4658. case XML_DOCUMENT_FRAG_NODE:
  4659. case XML_NOTATION_NODE:
  4660. case XML_NAMESPACE_DECL:
  4661. strcat(buf, "???");
  4662. if (cur->next != NULL)
  4663. strcat(buf, " ");
  4664. break;
  4665. case XML_ENTITY_NODE:
  4666. case XML_PI_NODE:
  4667. case XML_DTD_NODE:
  4668. case XML_COMMENT_NODE:
  4669. case XML_ELEMENT_DECL:
  4670. case XML_ATTRIBUTE_DECL:
  4671. case XML_ENTITY_DECL:
  4672. case XML_XINCLUDE_START:
  4673. case XML_XINCLUDE_END:
  4674. break;
  4675. }
  4676. cur = cur->next;
  4677. }
  4678. if (glob) strcat(buf, ")");
  4679. }
  4680. /**
  4681. * xmlValidateElementContent:
  4682. * @ctxt: the validation context
  4683. * @child: the child list
  4684. * @elemDecl: pointer to the element declaration
  4685. * @warn: emit the error message
  4686. * @parent: the parent element (for error reporting)
  4687. *
  4688. * Try to validate the content model of an element
  4689. *
  4690. * returns 1 if valid or 0 if not and -1 in case of error
  4691. */
  4692. static int
  4693. xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child,
  4694. xmlElementPtr elemDecl, int warn, xmlNodePtr parent) {
  4695. int ret = 1;
  4696. #ifndef LIBXML_REGEXP_ENABLED
  4697. xmlNodePtr repl = NULL, last = NULL, tmp;
  4698. #endif
  4699. xmlNodePtr cur;
  4700. xmlElementContentPtr cont;
  4701. const xmlChar *name;
  4702. if ((elemDecl == NULL) || (parent == NULL) || (ctxt == NULL))
  4703. return(-1);
  4704. cont = elemDecl->content;
  4705. name = elemDecl->name;
  4706. #ifdef LIBXML_REGEXP_ENABLED
  4707. /* Build the regexp associated to the content model */
  4708. if (elemDecl->contModel == NULL)
  4709. ret = xmlValidBuildContentModel(ctxt, elemDecl);
  4710. if (elemDecl->contModel == NULL) {
  4711. return(-1);
  4712. } else {
  4713. xmlRegExecCtxtPtr exec;
  4714. if (!xmlRegexpIsDeterminist(elemDecl->contModel)) {
  4715. return(-1);
  4716. }
  4717. ctxt->nodeMax = 0;
  4718. ctxt->nodeNr = 0;
  4719. ctxt->nodeTab = NULL;
  4720. exec = xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL);
  4721. if (exec != NULL) {
  4722. cur = child;
  4723. while (cur != NULL) {
  4724. switch (cur->type) {
  4725. case XML_ENTITY_REF_NODE:
  4726. /*
  4727. * Push the current node to be able to roll back
  4728. * and process within the entity
  4729. */
  4730. if ((cur->children != NULL) &&
  4731. (cur->children->children != NULL)) {
  4732. nodeVPush(ctxt, cur);
  4733. cur = cur->children->children;
  4734. continue;
  4735. }
  4736. break;
  4737. case XML_TEXT_NODE:
  4738. if (xmlIsBlankNode(cur))
  4739. break;
  4740. ret = 0;
  4741. goto fail;
  4742. case XML_CDATA_SECTION_NODE:
  4743. /* TODO */
  4744. ret = 0;
  4745. goto fail;
  4746. case XML_ELEMENT_NODE:
  4747. if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
  4748. xmlChar fn[50];
  4749. xmlChar *fullname;
  4750. fullname = xmlBuildQName(cur->name,
  4751. cur->ns->prefix, fn, 50);
  4752. if (fullname == NULL) {
  4753. ret = -1;
  4754. goto fail;
  4755. }
  4756. ret = xmlRegExecPushString(exec, fullname, NULL);
  4757. if ((fullname != fn) && (fullname != cur->name))
  4758. xmlFree(fullname);
  4759. } else {
  4760. ret = xmlRegExecPushString(exec, cur->name, NULL);
  4761. }
  4762. break;
  4763. default:
  4764. break;
  4765. }
  4766. /*
  4767. * Switch to next element
  4768. */
  4769. cur = cur->next;
  4770. while (cur == NULL) {
  4771. cur = nodeVPop(ctxt);
  4772. if (cur == NULL)
  4773. break;
  4774. cur = cur->next;
  4775. }
  4776. }
  4777. ret = xmlRegExecPushString(exec, NULL, NULL);
  4778. fail:
  4779. xmlRegFreeExecCtxt(exec);
  4780. }
  4781. }
  4782. #else /* LIBXML_REGEXP_ENABLED */
  4783. /*
  4784. * Allocate the stack
  4785. */
  4786. ctxt->vstateMax = 8;
  4787. ctxt->vstateTab = (xmlValidState *) xmlMalloc(
  4788. ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
  4789. if (ctxt->vstateTab == NULL) {
  4790. xmlVErrMemory(ctxt, "malloc failed");
  4791. return(-1);
  4792. }
  4793. /*
  4794. * The first entry in the stack is reserved to the current state
  4795. */
  4796. ctxt->nodeMax = 0;
  4797. ctxt->nodeNr = 0;
  4798. ctxt->nodeTab = NULL;
  4799. ctxt->vstate = &ctxt->vstateTab[0];
  4800. ctxt->vstateNr = 1;
  4801. CONT = cont;
  4802. NODE = child;
  4803. DEPTH = 0;
  4804. OCCURS = 0;
  4805. STATE = 0;
  4806. ret = xmlValidateElementType(ctxt);
  4807. if ((ret == -3) && (warn)) {
  4808. char expr[5000];
  4809. expr[0] = 0;
  4810. xmlSnprintfElementContent(expr, 5000, elemDecl->content, 1);
  4811. xmlErrValidNode(ctxt, (xmlNodePtr) elemDecl,
  4812. XML_DTD_CONTENT_NOT_DETERMINIST,
  4813. "Content model of %s is not deterministic: %s\n",
  4814. name, BAD_CAST expr, NULL);
  4815. } else if (ret == -2) {
  4816. /*
  4817. * An entities reference appeared at this level.
  4818. * Build a minimal representation of this node content
  4819. * sufficient to run the validation process on it
  4820. */
  4821. cur = child;
  4822. while (cur != NULL) {
  4823. switch (cur->type) {
  4824. case XML_ENTITY_REF_NODE:
  4825. /*
  4826. * Push the current node to be able to roll back
  4827. * and process within the entity
  4828. */
  4829. if ((cur->children != NULL) &&
  4830. (cur->children->children != NULL)) {
  4831. nodeVPush(ctxt, cur);
  4832. cur = cur->children->children;
  4833. continue;
  4834. }
  4835. break;
  4836. case XML_TEXT_NODE:
  4837. if (xmlIsBlankNode(cur))
  4838. break;
  4839. /* no break on purpose */
  4840. case XML_CDATA_SECTION_NODE:
  4841. /* no break on purpose */
  4842. case XML_ELEMENT_NODE:
  4843. /*
  4844. * Allocate a new node and minimally fills in
  4845. * what's required
  4846. */
  4847. tmp = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
  4848. if (tmp == NULL) {
  4849. xmlVErrMemory(ctxt, "malloc failed");
  4850. xmlFreeNodeList(repl);
  4851. ret = -1;
  4852. goto done;
  4853. }
  4854. tmp->type = cur->type;
  4855. tmp->name = cur->name;
  4856. tmp->ns = cur->ns;
  4857. tmp->next = NULL;
  4858. tmp->content = NULL;
  4859. if (repl == NULL)
  4860. repl = last = tmp;
  4861. else {
  4862. last->next = tmp;
  4863. last = tmp;
  4864. }
  4865. if (cur->type == XML_CDATA_SECTION_NODE) {
  4866. /*
  4867. * E59 spaces in CDATA does not match the
  4868. * nonterminal S
  4869. */
  4870. tmp->content = xmlStrdup(BAD_CAST "CDATA");
  4871. }
  4872. break;
  4873. default:
  4874. break;
  4875. }
  4876. /*
  4877. * Switch to next element
  4878. */
  4879. cur = cur->next;
  4880. while (cur == NULL) {
  4881. cur = nodeVPop(ctxt);
  4882. if (cur == NULL)
  4883. break;
  4884. cur = cur->next;
  4885. }
  4886. }
  4887. /*
  4888. * Relaunch the validation
  4889. */
  4890. ctxt->vstate = &ctxt->vstateTab[0];
  4891. ctxt->vstateNr = 1;
  4892. CONT = cont;
  4893. NODE = repl;
  4894. DEPTH = 0;
  4895. OCCURS = 0;
  4896. STATE = 0;
  4897. ret = xmlValidateElementType(ctxt);
  4898. }
  4899. #endif /* LIBXML_REGEXP_ENABLED */
  4900. if ((warn) && ((ret != 1) && (ret != -3))) {
  4901. if (ctxt != NULL) {
  4902. char expr[5000];
  4903. char list[5000];
  4904. expr[0] = 0;
  4905. xmlSnprintfElementContent(&expr[0], 5000, cont, 1);
  4906. list[0] = 0;
  4907. #ifndef LIBXML_REGEXP_ENABLED
  4908. if (repl != NULL)
  4909. xmlSnprintfElements(&list[0], 5000, repl, 1);
  4910. else
  4911. #endif /* LIBXML_REGEXP_ENABLED */
  4912. xmlSnprintfElements(&list[0], 5000, child, 1);
  4913. if (name != NULL) {
  4914. xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
  4915. "Element %s content does not follow the DTD, expecting %s, got %s\n",
  4916. name, BAD_CAST expr, BAD_CAST list);
  4917. } else {
  4918. xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
  4919. "Element content does not follow the DTD, expecting %s, got %s\n",
  4920. BAD_CAST expr, BAD_CAST list, NULL);
  4921. }
  4922. } else {
  4923. if (name != NULL) {
  4924. xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
  4925. "Element %s content does not follow the DTD\n",
  4926. name, NULL, NULL);
  4927. } else {
  4928. xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
  4929. "Element content does not follow the DTD\n",
  4930. NULL, NULL, NULL);
  4931. }
  4932. }
  4933. ret = 0;
  4934. }
  4935. if (ret == -3)
  4936. ret = 1;
  4937. #ifndef LIBXML_REGEXP_ENABLED
  4938. done:
  4939. /*
  4940. * Deallocate the copy if done, and free up the validation stack
  4941. */
  4942. while (repl != NULL) {
  4943. tmp = repl->next;
  4944. xmlFree(repl);
  4945. repl = tmp;
  4946. }
  4947. ctxt->vstateMax = 0;
  4948. if (ctxt->vstateTab != NULL) {
  4949. xmlFree(ctxt->vstateTab);
  4950. ctxt->vstateTab = NULL;
  4951. }
  4952. #endif
  4953. ctxt->nodeMax = 0;
  4954. ctxt->nodeNr = 0;
  4955. if (ctxt->nodeTab != NULL) {
  4956. xmlFree(ctxt->nodeTab);
  4957. ctxt->nodeTab = NULL;
  4958. }
  4959. return(ret);
  4960. }
  4961. /**
  4962. * xmlValidateCdataElement:
  4963. * @ctxt: the validation context
  4964. * @doc: a document instance
  4965. * @elem: an element instance
  4966. *
  4967. * Check that an element follows #CDATA
  4968. *
  4969. * returns 1 if valid or 0 otherwise
  4970. */
  4971. static int
  4972. xmlValidateOneCdataElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  4973. xmlNodePtr elem) {
  4974. int ret = 1;
  4975. xmlNodePtr cur, child;
  4976. if ((ctxt == NULL) || (doc == NULL) || (elem == NULL) ||
  4977. (elem->type != XML_ELEMENT_NODE))
  4978. return(0);
  4979. child = elem->children;
  4980. cur = child;
  4981. while (cur != NULL) {
  4982. switch (cur->type) {
  4983. case XML_ENTITY_REF_NODE:
  4984. /*
  4985. * Push the current node to be able to roll back
  4986. * and process within the entity
  4987. */
  4988. if ((cur->children != NULL) &&
  4989. (cur->children->children != NULL)) {
  4990. nodeVPush(ctxt, cur);
  4991. cur = cur->children->children;
  4992. continue;
  4993. }
  4994. break;
  4995. case XML_COMMENT_NODE:
  4996. case XML_PI_NODE:
  4997. case XML_TEXT_NODE:
  4998. case XML_CDATA_SECTION_NODE:
  4999. break;
  5000. default:
  5001. ret = 0;
  5002. goto done;
  5003. }
  5004. /*
  5005. * Switch to next element
  5006. */
  5007. cur = cur->next;
  5008. while (cur == NULL) {
  5009. cur = nodeVPop(ctxt);
  5010. if (cur == NULL)
  5011. break;
  5012. cur = cur->next;
  5013. }
  5014. }
  5015. done:
  5016. ctxt->nodeMax = 0;
  5017. ctxt->nodeNr = 0;
  5018. if (ctxt->nodeTab != NULL) {
  5019. xmlFree(ctxt->nodeTab);
  5020. ctxt->nodeTab = NULL;
  5021. }
  5022. return(ret);
  5023. }
  5024. #ifdef LIBXML_REGEXP_ENABLED
  5025. /**
  5026. * xmlValidateCheckMixed:
  5027. * @ctxt: the validation context
  5028. * @cont: the mixed content model
  5029. * @qname: the qualified name as appearing in the serialization
  5030. *
  5031. * Check if the given node is part of the content model.
  5032. *
  5033. * Returns 1 if yes, 0 if no, -1 in case of error
  5034. */
  5035. static int
  5036. xmlValidateCheckMixed(xmlValidCtxtPtr ctxt,
  5037. xmlElementContentPtr cont, const xmlChar *qname) {
  5038. const xmlChar *name;
  5039. int plen;
  5040. name = xmlSplitQName3(qname, &plen);
  5041. if (name == NULL) {
  5042. while (cont != NULL) {
  5043. if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
  5044. if ((cont->prefix == NULL) && (xmlStrEqual(cont->name, qname)))
  5045. return(1);
  5046. } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
  5047. (cont->c1 != NULL) &&
  5048. (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
  5049. if ((cont->c1->prefix == NULL) &&
  5050. (xmlStrEqual(cont->c1->name, qname)))
  5051. return(1);
  5052. } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
  5053. (cont->c1 == NULL) ||
  5054. (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
  5055. xmlErrValid(NULL, XML_DTD_MIXED_CORRUPT,
  5056. "Internal: MIXED struct corrupted\n",
  5057. NULL);
  5058. break;
  5059. }
  5060. cont = cont->c2;
  5061. }
  5062. } else {
  5063. while (cont != NULL) {
  5064. if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
  5065. if ((cont->prefix != NULL) &&
  5066. (xmlStrncmp(cont->prefix, qname, plen) == 0) &&
  5067. (xmlStrEqual(cont->name, name)))
  5068. return(1);
  5069. } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
  5070. (cont->c1 != NULL) &&
  5071. (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
  5072. if ((cont->c1->prefix != NULL) &&
  5073. (xmlStrncmp(cont->c1->prefix, qname, plen) == 0) &&
  5074. (xmlStrEqual(cont->c1->name, name)))
  5075. return(1);
  5076. } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
  5077. (cont->c1 == NULL) ||
  5078. (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
  5079. xmlErrValid(ctxt, XML_DTD_MIXED_CORRUPT,
  5080. "Internal: MIXED struct corrupted\n",
  5081. NULL);
  5082. break;
  5083. }
  5084. cont = cont->c2;
  5085. }
  5086. }
  5087. return(0);
  5088. }
  5089. #endif /* LIBXML_REGEXP_ENABLED */
  5090. /**
  5091. * xmlValidGetElemDecl:
  5092. * @ctxt: the validation context
  5093. * @doc: a document instance
  5094. * @elem: an element instance
  5095. * @extsubset: pointer, (out) indicate if the declaration was found
  5096. * in the external subset.
  5097. *
  5098. * Finds a declaration associated to an element in the document.
  5099. *
  5100. * returns the pointer to the declaration or NULL if not found.
  5101. */
  5102. static xmlElementPtr
  5103. xmlValidGetElemDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  5104. xmlNodePtr elem, int *extsubset) {
  5105. xmlElementPtr elemDecl = NULL;
  5106. const xmlChar *prefix = NULL;
  5107. if ((ctxt == NULL) || (doc == NULL) ||
  5108. (elem == NULL) || (elem->name == NULL))
  5109. return(NULL);
  5110. if (extsubset != NULL)
  5111. *extsubset = 0;
  5112. /*
  5113. * Fetch the declaration for the qualified name
  5114. */
  5115. if ((elem->ns != NULL) && (elem->ns->prefix != NULL))
  5116. prefix = elem->ns->prefix;
  5117. if (prefix != NULL) {
  5118. elemDecl = xmlGetDtdQElementDesc(doc->intSubset,
  5119. elem->name, prefix);
  5120. if ((elemDecl == NULL) && (doc->extSubset != NULL)) {
  5121. elemDecl = xmlGetDtdQElementDesc(doc->extSubset,
  5122. elem->name, prefix);
  5123. if ((elemDecl != NULL) && (extsubset != NULL))
  5124. *extsubset = 1;
  5125. }
  5126. }
  5127. /*
  5128. * Fetch the declaration for the non qualified name
  5129. * This is "non-strict" validation should be done on the
  5130. * full QName but in that case being flexible makes sense.
  5131. */
  5132. if (elemDecl == NULL) {
  5133. elemDecl = xmlGetDtdElementDesc(doc->intSubset, elem->name);
  5134. if ((elemDecl == NULL) && (doc->extSubset != NULL)) {
  5135. elemDecl = xmlGetDtdElementDesc(doc->extSubset, elem->name);
  5136. if ((elemDecl != NULL) && (extsubset != NULL))
  5137. *extsubset = 1;
  5138. }
  5139. }
  5140. if (elemDecl == NULL) {
  5141. xmlErrValidNode(ctxt, elem,
  5142. XML_DTD_UNKNOWN_ELEM,
  5143. "No declaration for element %s\n",
  5144. elem->name, NULL, NULL);
  5145. }
  5146. return(elemDecl);
  5147. }
  5148. #ifdef LIBXML_REGEXP_ENABLED
  5149. /**
  5150. * xmlValidatePushElement:
  5151. * @ctxt: the validation context
  5152. * @doc: a document instance
  5153. * @elem: an element instance
  5154. * @qname: the qualified name as appearing in the serialization
  5155. *
  5156. * Push a new element start on the validation stack.
  5157. *
  5158. * returns 1 if no validation problem was found or 0 otherwise
  5159. */
  5160. int
  5161. xmlValidatePushElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  5162. xmlNodePtr elem, const xmlChar *qname) {
  5163. int ret = 1;
  5164. xmlElementPtr eDecl;
  5165. int extsubset = 0;
  5166. if (ctxt == NULL)
  5167. return(0);
  5168. /* printf("PushElem %s\n", qname); */
  5169. if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) {
  5170. xmlValidStatePtr state = ctxt->vstate;
  5171. xmlElementPtr elemDecl;
  5172. /*
  5173. * Check the new element against the content model of the new elem.
  5174. */
  5175. if (state->elemDecl != NULL) {
  5176. elemDecl = state->elemDecl;
  5177. switch(elemDecl->etype) {
  5178. case XML_ELEMENT_TYPE_UNDEFINED:
  5179. ret = 0;
  5180. break;
  5181. case XML_ELEMENT_TYPE_EMPTY:
  5182. xmlErrValidNode(ctxt, state->node,
  5183. XML_DTD_NOT_EMPTY,
  5184. "Element %s was declared EMPTY this one has content\n",
  5185. state->node->name, NULL, NULL);
  5186. ret = 0;
  5187. break;
  5188. case XML_ELEMENT_TYPE_ANY:
  5189. /* I don't think anything is required then */
  5190. break;
  5191. case XML_ELEMENT_TYPE_MIXED:
  5192. /* simple case of declared as #PCDATA */
  5193. if ((elemDecl->content != NULL) &&
  5194. (elemDecl->content->type ==
  5195. XML_ELEMENT_CONTENT_PCDATA)) {
  5196. xmlErrValidNode(ctxt, state->node,
  5197. XML_DTD_NOT_PCDATA,
  5198. "Element %s was declared #PCDATA but contains non text nodes\n",
  5199. state->node->name, NULL, NULL);
  5200. ret = 0;
  5201. } else {
  5202. ret = xmlValidateCheckMixed(ctxt, elemDecl->content,
  5203. qname);
  5204. if (ret != 1) {
  5205. xmlErrValidNode(ctxt, state->node,
  5206. XML_DTD_INVALID_CHILD,
  5207. "Element %s is not declared in %s list of possible children\n",
  5208. qname, state->node->name, NULL);
  5209. }
  5210. }
  5211. break;
  5212. case XML_ELEMENT_TYPE_ELEMENT:
  5213. /*
  5214. * TODO:
  5215. * VC: Standalone Document Declaration
  5216. * - element types with element content, if white space
  5217. * occurs directly within any instance of those types.
  5218. */
  5219. if (state->exec != NULL) {
  5220. ret = xmlRegExecPushString(state->exec, qname, NULL);
  5221. if (ret < 0) {
  5222. xmlErrValidNode(ctxt, state->node,
  5223. XML_DTD_CONTENT_MODEL,
  5224. "Element %s content does not follow the DTD, Misplaced %s\n",
  5225. state->node->name, qname, NULL);
  5226. ret = 0;
  5227. } else {
  5228. ret = 1;
  5229. }
  5230. }
  5231. break;
  5232. }
  5233. }
  5234. }
  5235. eDecl = xmlValidGetElemDecl(ctxt, doc, elem, &extsubset);
  5236. vstateVPush(ctxt, eDecl, elem);
  5237. return(ret);
  5238. }
  5239. /**
  5240. * xmlValidatePushCData:
  5241. * @ctxt: the validation context
  5242. * @data: some character data read
  5243. * @len: the length of the data
  5244. *
  5245. * check the CData parsed for validation in the current stack
  5246. *
  5247. * returns 1 if no validation problem was found or 0 otherwise
  5248. */
  5249. int
  5250. xmlValidatePushCData(xmlValidCtxtPtr ctxt, const xmlChar *data, int len) {
  5251. int ret = 1;
  5252. /* printf("CDATA %s %d\n", data, len); */
  5253. if (ctxt == NULL)
  5254. return(0);
  5255. if (len <= 0)
  5256. return(ret);
  5257. if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) {
  5258. xmlValidStatePtr state = ctxt->vstate;
  5259. xmlElementPtr elemDecl;
  5260. /*
  5261. * Check the new element against the content model of the new elem.
  5262. */
  5263. if (state->elemDecl != NULL) {
  5264. elemDecl = state->elemDecl;
  5265. switch(elemDecl->etype) {
  5266. case XML_ELEMENT_TYPE_UNDEFINED:
  5267. ret = 0;
  5268. break;
  5269. case XML_ELEMENT_TYPE_EMPTY:
  5270. xmlErrValidNode(ctxt, state->node,
  5271. XML_DTD_NOT_EMPTY,
  5272. "Element %s was declared EMPTY this one has content\n",
  5273. state->node->name, NULL, NULL);
  5274. ret = 0;
  5275. break;
  5276. case XML_ELEMENT_TYPE_ANY:
  5277. break;
  5278. case XML_ELEMENT_TYPE_MIXED:
  5279. break;
  5280. case XML_ELEMENT_TYPE_ELEMENT: {
  5281. int i;
  5282. for (i = 0;i < len;i++) {
  5283. if (!IS_BLANK_CH(data[i])) {
  5284. xmlErrValidNode(ctxt, state->node,
  5285. XML_DTD_CONTENT_MODEL,
  5286. "Element %s content does not follow the DTD, Text not allowed\n",
  5287. state->node->name, NULL, NULL);
  5288. ret = 0;
  5289. goto done;
  5290. }
  5291. }
  5292. /*
  5293. * TODO:
  5294. * VC: Standalone Document Declaration
  5295. * element types with element content, if white space
  5296. * occurs directly within any instance of those types.
  5297. */
  5298. break;
  5299. }
  5300. }
  5301. }
  5302. }
  5303. done:
  5304. return(ret);
  5305. }
  5306. /**
  5307. * xmlValidatePopElement:
  5308. * @ctxt: the validation context
  5309. * @doc: a document instance
  5310. * @elem: an element instance
  5311. * @qname: the qualified name as appearing in the serialization
  5312. *
  5313. * Pop the element end from the validation stack.
  5314. *
  5315. * returns 1 if no validation problem was found or 0 otherwise
  5316. */
  5317. int
  5318. xmlValidatePopElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc ATTRIBUTE_UNUSED,
  5319. xmlNodePtr elem ATTRIBUTE_UNUSED,
  5320. const xmlChar *qname ATTRIBUTE_UNUSED) {
  5321. int ret = 1;
  5322. if (ctxt == NULL)
  5323. return(0);
  5324. /* printf("PopElem %s\n", qname); */
  5325. if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) {
  5326. xmlValidStatePtr state = ctxt->vstate;
  5327. xmlElementPtr elemDecl;
  5328. /*
  5329. * Check the new element against the content model of the new elem.
  5330. */
  5331. if (state->elemDecl != NULL) {
  5332. elemDecl = state->elemDecl;
  5333. if (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT) {
  5334. if (state->exec != NULL) {
  5335. ret = xmlRegExecPushString(state->exec, NULL, NULL);
  5336. if (ret <= 0) {
  5337. xmlErrValidNode(ctxt, state->node,
  5338. XML_DTD_CONTENT_MODEL,
  5339. "Element %s content does not follow the DTD, Expecting more children\n",
  5340. state->node->name, NULL,NULL);
  5341. ret = 0;
  5342. } else {
  5343. /*
  5344. * previous validation errors should not generate
  5345. * a new one here
  5346. */
  5347. ret = 1;
  5348. }
  5349. }
  5350. }
  5351. }
  5352. vstateVPop(ctxt);
  5353. }
  5354. return(ret);
  5355. }
  5356. #endif /* LIBXML_REGEXP_ENABLED */
  5357. /**
  5358. * xmlValidateOneElement:
  5359. * @ctxt: the validation context
  5360. * @doc: a document instance
  5361. * @elem: an element instance
  5362. *
  5363. * Try to validate a single element and it's attributes,
  5364. * basically it does the following checks as described by the
  5365. * XML-1.0 recommendation:
  5366. * - [ VC: Element Valid ]
  5367. * - [ VC: Required Attribute ]
  5368. * Then call xmlValidateOneAttribute() for each attribute present.
  5369. *
  5370. * The ID/IDREF checkings are done separately
  5371. *
  5372. * returns 1 if valid or 0 otherwise
  5373. */
  5374. int
  5375. xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  5376. xmlNodePtr elem) {
  5377. xmlElementPtr elemDecl = NULL;
  5378. xmlElementContentPtr cont;
  5379. xmlAttributePtr attr;
  5380. xmlNodePtr child;
  5381. int ret = 1, tmp;
  5382. const xmlChar *name;
  5383. int extsubset = 0;
  5384. CHECK_DTD;
  5385. if (elem == NULL) return(0);
  5386. switch (elem->type) {
  5387. case XML_ATTRIBUTE_NODE:
  5388. xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
  5389. "Attribute element not expected\n", NULL, NULL ,NULL);
  5390. return(0);
  5391. case XML_TEXT_NODE:
  5392. if (elem->children != NULL) {
  5393. xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
  5394. "Text element has children !\n",
  5395. NULL,NULL,NULL);
  5396. return(0);
  5397. }
  5398. if (elem->ns != NULL) {
  5399. xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
  5400. "Text element has namespace !\n",
  5401. NULL,NULL,NULL);
  5402. return(0);
  5403. }
  5404. if (elem->content == NULL) {
  5405. xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
  5406. "Text element has no content !\n",
  5407. NULL,NULL,NULL);
  5408. return(0);
  5409. }
  5410. return(1);
  5411. case XML_XINCLUDE_START:
  5412. case XML_XINCLUDE_END:
  5413. return(1);
  5414. case XML_CDATA_SECTION_NODE:
  5415. case XML_ENTITY_REF_NODE:
  5416. case XML_PI_NODE:
  5417. case XML_COMMENT_NODE:
  5418. return(1);
  5419. case XML_ENTITY_NODE:
  5420. xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
  5421. "Entity element not expected\n", NULL, NULL ,NULL);
  5422. return(0);
  5423. case XML_NOTATION_NODE:
  5424. xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
  5425. "Notation element not expected\n", NULL, NULL ,NULL);
  5426. return(0);
  5427. case XML_DOCUMENT_NODE:
  5428. case XML_DOCUMENT_TYPE_NODE:
  5429. case XML_DOCUMENT_FRAG_NODE:
  5430. xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
  5431. "Document element not expected\n", NULL, NULL ,NULL);
  5432. return(0);
  5433. case XML_HTML_DOCUMENT_NODE:
  5434. xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
  5435. "HTML Document not expected\n", NULL, NULL ,NULL);
  5436. return(0);
  5437. case XML_ELEMENT_NODE:
  5438. break;
  5439. default:
  5440. xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
  5441. "unknown element type\n", NULL, NULL ,NULL);
  5442. return(0);
  5443. }
  5444. /*
  5445. * Fetch the declaration
  5446. */
  5447. elemDecl = xmlValidGetElemDecl(ctxt, doc, elem, &extsubset);
  5448. if (elemDecl == NULL)
  5449. return(0);
  5450. /*
  5451. * If vstateNr is not zero that means continuous validation is
  5452. * activated, do not try to check the content model at that level.
  5453. */
  5454. if (ctxt->vstateNr == 0) {
  5455. /* Check that the element content matches the definition */
  5456. switch (elemDecl->etype) {
  5457. case XML_ELEMENT_TYPE_UNDEFINED:
  5458. xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ELEM,
  5459. "No declaration for element %s\n",
  5460. elem->name, NULL, NULL);
  5461. return(0);
  5462. case XML_ELEMENT_TYPE_EMPTY:
  5463. if (elem->children != NULL) {
  5464. xmlErrValidNode(ctxt, elem, XML_DTD_NOT_EMPTY,
  5465. "Element %s was declared EMPTY this one has content\n",
  5466. elem->name, NULL, NULL);
  5467. ret = 0;
  5468. }
  5469. break;
  5470. case XML_ELEMENT_TYPE_ANY:
  5471. /* I don't think anything is required then */
  5472. break;
  5473. case XML_ELEMENT_TYPE_MIXED:
  5474. /* simple case of declared as #PCDATA */
  5475. if ((elemDecl->content != NULL) &&
  5476. (elemDecl->content->type == XML_ELEMENT_CONTENT_PCDATA)) {
  5477. ret = xmlValidateOneCdataElement(ctxt, doc, elem);
  5478. if (!ret) {
  5479. xmlErrValidNode(ctxt, elem, XML_DTD_NOT_PCDATA,
  5480. "Element %s was declared #PCDATA but contains non text nodes\n",
  5481. elem->name, NULL, NULL);
  5482. }
  5483. break;
  5484. }
  5485. child = elem->children;
  5486. /* Hum, this start to get messy */
  5487. while (child != NULL) {
  5488. if (child->type == XML_ELEMENT_NODE) {
  5489. name = child->name;
  5490. if ((child->ns != NULL) && (child->ns->prefix != NULL)) {
  5491. xmlChar fn[50];
  5492. xmlChar *fullname;
  5493. fullname = xmlBuildQName(child->name, child->ns->prefix,
  5494. fn, 50);
  5495. if (fullname == NULL)
  5496. return(0);
  5497. cont = elemDecl->content;
  5498. while (cont != NULL) {
  5499. if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
  5500. if (xmlStrEqual(cont->name, fullname))
  5501. break;
  5502. } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
  5503. (cont->c1 != NULL) &&
  5504. (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
  5505. if (xmlStrEqual(cont->c1->name, fullname))
  5506. break;
  5507. } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
  5508. (cont->c1 == NULL) ||
  5509. (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
  5510. xmlErrValid(NULL, XML_DTD_MIXED_CORRUPT,
  5511. "Internal: MIXED struct corrupted\n",
  5512. NULL);
  5513. break;
  5514. }
  5515. cont = cont->c2;
  5516. }
  5517. if ((fullname != fn) && (fullname != child->name))
  5518. xmlFree(fullname);
  5519. if (cont != NULL)
  5520. goto child_ok;
  5521. }
  5522. cont = elemDecl->content;
  5523. while (cont != NULL) {
  5524. if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
  5525. if (xmlStrEqual(cont->name, name)) break;
  5526. } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
  5527. (cont->c1 != NULL) &&
  5528. (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)) {
  5529. if (xmlStrEqual(cont->c1->name, name)) break;
  5530. } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
  5531. (cont->c1 == NULL) ||
  5532. (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)) {
  5533. xmlErrValid(ctxt, XML_DTD_MIXED_CORRUPT,
  5534. "Internal: MIXED struct corrupted\n",
  5535. NULL);
  5536. break;
  5537. }
  5538. cont = cont->c2;
  5539. }
  5540. if (cont == NULL) {
  5541. xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_CHILD,
  5542. "Element %s is not declared in %s list of possible children\n",
  5543. name, elem->name, NULL);
  5544. ret = 0;
  5545. }
  5546. }
  5547. child_ok:
  5548. child = child->next;
  5549. }
  5550. break;
  5551. case XML_ELEMENT_TYPE_ELEMENT:
  5552. if ((doc->standalone == 1) && (extsubset == 1)) {
  5553. /*
  5554. * VC: Standalone Document Declaration
  5555. * - element types with element content, if white space
  5556. * occurs directly within any instance of those types.
  5557. */
  5558. child = elem->children;
  5559. while (child != NULL) {
  5560. if (child->type == XML_TEXT_NODE) {
  5561. const xmlChar *content = child->content;
  5562. while (IS_BLANK_CH(*content))
  5563. content++;
  5564. if (*content == 0) {
  5565. xmlErrValidNode(ctxt, elem,
  5566. XML_DTD_STANDALONE_WHITE_SPACE,
  5567. "standalone: %s declared in the external subset contains white spaces nodes\n",
  5568. elem->name, NULL, NULL);
  5569. ret = 0;
  5570. break;
  5571. }
  5572. }
  5573. child =child->next;
  5574. }
  5575. }
  5576. child = elem->children;
  5577. cont = elemDecl->content;
  5578. tmp = xmlValidateElementContent(ctxt, child, elemDecl, 1, elem);
  5579. if (tmp <= 0)
  5580. ret = tmp;
  5581. break;
  5582. }
  5583. } /* not continuous */
  5584. /* [ VC: Required Attribute ] */
  5585. attr = elemDecl->attributes;
  5586. while (attr != NULL) {
  5587. if (attr->def == XML_ATTRIBUTE_REQUIRED) {
  5588. int qualified = -1;
  5589. if ((attr->prefix == NULL) &&
  5590. (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) {
  5591. xmlNsPtr ns;
  5592. ns = elem->nsDef;
  5593. while (ns != NULL) {
  5594. if (ns->prefix == NULL)
  5595. goto found;
  5596. ns = ns->next;
  5597. }
  5598. } else if (xmlStrEqual(attr->prefix, BAD_CAST "xmlns")) {
  5599. xmlNsPtr ns;
  5600. ns = elem->nsDef;
  5601. while (ns != NULL) {
  5602. if (xmlStrEqual(attr->name, ns->prefix))
  5603. goto found;
  5604. ns = ns->next;
  5605. }
  5606. } else {
  5607. xmlAttrPtr attrib;
  5608. attrib = elem->properties;
  5609. while (attrib != NULL) {
  5610. if (xmlStrEqual(attrib->name, attr->name)) {
  5611. if (attr->prefix != NULL) {
  5612. xmlNsPtr nameSpace = attrib->ns;
  5613. if (nameSpace == NULL)
  5614. nameSpace = elem->ns;
  5615. /*
  5616. * qualified names handling is problematic, having a
  5617. * different prefix should be possible but DTDs don't
  5618. * allow to define the URI instead of the prefix :-(
  5619. */
  5620. if (nameSpace == NULL) {
  5621. if (qualified < 0)
  5622. qualified = 0;
  5623. } else if (!xmlStrEqual(nameSpace->prefix,
  5624. attr->prefix)) {
  5625. if (qualified < 1)
  5626. qualified = 1;
  5627. } else
  5628. goto found;
  5629. } else {
  5630. /*
  5631. * We should allow applications to define namespaces
  5632. * for their application even if the DTD doesn't
  5633. * carry one, otherwise, basically we would always
  5634. * break.
  5635. */
  5636. goto found;
  5637. }
  5638. }
  5639. attrib = attrib->next;
  5640. }
  5641. }
  5642. if (qualified == -1) {
  5643. if (attr->prefix == NULL) {
  5644. xmlErrValidNode(ctxt, elem, XML_DTD_MISSING_ATTRIBUTE,
  5645. "Element %s does not carry attribute %s\n",
  5646. elem->name, attr->name, NULL);
  5647. ret = 0;
  5648. } else {
  5649. xmlErrValidNode(ctxt, elem, XML_DTD_MISSING_ATTRIBUTE,
  5650. "Element %s does not carry attribute %s:%s\n",
  5651. elem->name, attr->prefix,attr->name);
  5652. ret = 0;
  5653. }
  5654. } else if (qualified == 0) {
  5655. xmlErrValidWarning(ctxt, elem, XML_DTD_NO_PREFIX,
  5656. "Element %s required attribute %s:%s has no prefix\n",
  5657. elem->name, attr->prefix, attr->name);
  5658. } else if (qualified == 1) {
  5659. xmlErrValidWarning(ctxt, elem, XML_DTD_DIFFERENT_PREFIX,
  5660. "Element %s required attribute %s:%s has different prefix\n",
  5661. elem->name, attr->prefix, attr->name);
  5662. }
  5663. } else if (attr->def == XML_ATTRIBUTE_FIXED) {
  5664. /*
  5665. * Special tests checking #FIXED namespace declarations
  5666. * have the right value since this is not done as an
  5667. * attribute checking
  5668. */
  5669. if ((attr->prefix == NULL) &&
  5670. (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) {
  5671. xmlNsPtr ns;
  5672. ns = elem->nsDef;
  5673. while (ns != NULL) {
  5674. if (ns->prefix == NULL) {
  5675. if (!xmlStrEqual(attr->defaultValue, ns->href)) {
  5676. xmlErrValidNode(ctxt, elem,
  5677. XML_DTD_ELEM_DEFAULT_NAMESPACE,
  5678. "Element %s namespace name for default namespace does not match the DTD\n",
  5679. elem->name, NULL, NULL);
  5680. ret = 0;
  5681. }
  5682. goto found;
  5683. }
  5684. ns = ns->next;
  5685. }
  5686. } else if (xmlStrEqual(attr->prefix, BAD_CAST "xmlns")) {
  5687. xmlNsPtr ns;
  5688. ns = elem->nsDef;
  5689. while (ns != NULL) {
  5690. if (xmlStrEqual(attr->name, ns->prefix)) {
  5691. if (!xmlStrEqual(attr->defaultValue, ns->href)) {
  5692. xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE,
  5693. "Element %s namespace name for %s does not match the DTD\n",
  5694. elem->name, ns->prefix, NULL);
  5695. ret = 0;
  5696. }
  5697. goto found;
  5698. }
  5699. ns = ns->next;
  5700. }
  5701. }
  5702. }
  5703. found:
  5704. attr = attr->nexth;
  5705. }
  5706. return(ret);
  5707. }
  5708. /**
  5709. * xmlValidateRoot:
  5710. * @ctxt: the validation context
  5711. * @doc: a document instance
  5712. *
  5713. * Try to validate a the root element
  5714. * basically it does the following check as described by the
  5715. * XML-1.0 recommendation:
  5716. * - [ VC: Root Element Type ]
  5717. * it doesn't try to recurse or apply other check to the element
  5718. *
  5719. * returns 1 if valid or 0 otherwise
  5720. */
  5721. int
  5722. xmlValidateRoot(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
  5723. xmlNodePtr root;
  5724. int ret;
  5725. if (doc == NULL) return(0);
  5726. root = xmlDocGetRootElement(doc);
  5727. if ((root == NULL) || (root->name == NULL)) {
  5728. xmlErrValid(ctxt, XML_DTD_NO_ROOT,
  5729. "no root element\n", NULL);
  5730. return(0);
  5731. }
  5732. /*
  5733. * When doing post validation against a separate DTD, those may
  5734. * no internal subset has been generated
  5735. */
  5736. if ((doc->intSubset != NULL) &&
  5737. (doc->intSubset->name != NULL)) {
  5738. /*
  5739. * Check first the document root against the NQName
  5740. */
  5741. if (!xmlStrEqual(doc->intSubset->name, root->name)) {
  5742. if ((root->ns != NULL) && (root->ns->prefix != NULL)) {
  5743. xmlChar fn[50];
  5744. xmlChar *fullname;
  5745. fullname = xmlBuildQName(root->name, root->ns->prefix, fn, 50);
  5746. if (fullname == NULL) {
  5747. xmlVErrMemory(ctxt, NULL);
  5748. return(0);
  5749. }
  5750. ret = xmlStrEqual(doc->intSubset->name, fullname);
  5751. if ((fullname != fn) && (fullname != root->name))
  5752. xmlFree(fullname);
  5753. if (ret == 1)
  5754. goto name_ok;
  5755. }
  5756. if ((xmlStrEqual(doc->intSubset->name, BAD_CAST "HTML")) &&
  5757. (xmlStrEqual(root->name, BAD_CAST "html")))
  5758. goto name_ok;
  5759. xmlErrValidNode(ctxt, root, XML_DTD_ROOT_NAME,
  5760. "root and DTD name do not match '%s' and '%s'\n",
  5761. root->name, doc->intSubset->name, NULL);
  5762. return(0);
  5763. }
  5764. }
  5765. name_ok:
  5766. return(1);
  5767. }
  5768. /**
  5769. * xmlValidateElement:
  5770. * @ctxt: the validation context
  5771. * @doc: a document instance
  5772. * @root: an element instance
  5773. *
  5774. * Try to validate the subtree under an element
  5775. *
  5776. * returns 1 if valid or 0 otherwise
  5777. */
  5778. int
  5779. xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr root) {
  5780. xmlNodePtr elem;
  5781. xmlAttrPtr attr;
  5782. xmlNsPtr ns;
  5783. const xmlChar *value;
  5784. int ret = 1;
  5785. if (root == NULL) return(0);
  5786. CHECK_DTD;
  5787. elem = root;
  5788. while (1) {
  5789. ret &= xmlValidateOneElement(ctxt, doc, elem);
  5790. if (elem->type == XML_ELEMENT_NODE) {
  5791. attr = elem->properties;
  5792. while (attr != NULL) {
  5793. value = xmlNodeListGetString(doc, attr->children, 0);
  5794. ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value);
  5795. if (value != NULL)
  5796. xmlFree((char *)value);
  5797. attr= attr->next;
  5798. }
  5799. ns = elem->nsDef;
  5800. while (ns != NULL) {
  5801. if (elem->ns == NULL)
  5802. ret &= xmlValidateOneNamespace(ctxt, doc, elem, NULL,
  5803. ns, ns->href);
  5804. else
  5805. ret &= xmlValidateOneNamespace(ctxt, doc, elem,
  5806. elem->ns->prefix, ns,
  5807. ns->href);
  5808. ns = ns->next;
  5809. }
  5810. if (elem->children != NULL) {
  5811. elem = elem->children;
  5812. continue;
  5813. }
  5814. }
  5815. while (1) {
  5816. if (elem == root)
  5817. goto done;
  5818. if (elem->next != NULL)
  5819. break;
  5820. elem = elem->parent;
  5821. }
  5822. elem = elem->next;
  5823. }
  5824. done:
  5825. return(ret);
  5826. }
  5827. /**
  5828. * xmlValidateRef:
  5829. * @ref: A reference to be validated
  5830. * @ctxt: Validation context
  5831. * @name: Name of ID we are searching for
  5832. *
  5833. */
  5834. static void
  5835. xmlValidateRef(xmlRefPtr ref, xmlValidCtxtPtr ctxt,
  5836. const xmlChar *name) {
  5837. xmlAttrPtr id;
  5838. xmlAttrPtr attr;
  5839. if (ref == NULL)
  5840. return;
  5841. if ((ref->attr == NULL) && (ref->name == NULL))
  5842. return;
  5843. attr = ref->attr;
  5844. if (attr == NULL) {
  5845. xmlChar *dup, *str = NULL, *cur, save;
  5846. dup = xmlStrdup(name);
  5847. if (dup == NULL) {
  5848. ctxt->valid = 0;
  5849. return;
  5850. }
  5851. cur = dup;
  5852. while (*cur != 0) {
  5853. str = cur;
  5854. while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
  5855. save = *cur;
  5856. *cur = 0;
  5857. id = xmlGetID(ctxt->doc, str);
  5858. if (id == NULL) {
  5859. xmlErrValidNodeNr(ctxt, NULL, XML_DTD_UNKNOWN_ID,
  5860. "attribute %s line %d references an unknown ID \"%s\"\n",
  5861. ref->name, ref->lineno, str);
  5862. ctxt->valid = 0;
  5863. }
  5864. if (save == 0)
  5865. break;
  5866. *cur = save;
  5867. while (IS_BLANK_CH(*cur)) cur++;
  5868. }
  5869. xmlFree(dup);
  5870. } else if (attr->atype == XML_ATTRIBUTE_IDREF) {
  5871. id = xmlGetID(ctxt->doc, name);
  5872. if (id == NULL) {
  5873. xmlErrValidNode(ctxt, attr->parent, XML_DTD_UNKNOWN_ID,
  5874. "IDREF attribute %s references an unknown ID \"%s\"\n",
  5875. attr->name, name, NULL);
  5876. ctxt->valid = 0;
  5877. }
  5878. } else if (attr->atype == XML_ATTRIBUTE_IDREFS) {
  5879. xmlChar *dup, *str = NULL, *cur, save;
  5880. dup = xmlStrdup(name);
  5881. if (dup == NULL) {
  5882. xmlVErrMemory(ctxt, "IDREFS split");
  5883. ctxt->valid = 0;
  5884. return;
  5885. }
  5886. cur = dup;
  5887. while (*cur != 0) {
  5888. str = cur;
  5889. while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
  5890. save = *cur;
  5891. *cur = 0;
  5892. id = xmlGetID(ctxt->doc, str);
  5893. if (id == NULL) {
  5894. xmlErrValidNode(ctxt, attr->parent, XML_DTD_UNKNOWN_ID,
  5895. "IDREFS attribute %s references an unknown ID \"%s\"\n",
  5896. attr->name, str, NULL);
  5897. ctxt->valid = 0;
  5898. }
  5899. if (save == 0)
  5900. break;
  5901. *cur = save;
  5902. while (IS_BLANK_CH(*cur)) cur++;
  5903. }
  5904. xmlFree(dup);
  5905. }
  5906. }
  5907. /**
  5908. * xmlWalkValidateList:
  5909. * @data: Contents of current link
  5910. * @user: Value supplied by the user
  5911. *
  5912. * Returns 0 to abort the walk or 1 to continue
  5913. */
  5914. static int
  5915. xmlWalkValidateList(const void *data, void *user)
  5916. {
  5917. xmlValidateMemoPtr memo = (xmlValidateMemoPtr)user;
  5918. xmlValidateRef((xmlRefPtr)data, memo->ctxt, memo->name);
  5919. return 1;
  5920. }
  5921. /**
  5922. * xmlValidateCheckRefCallback:
  5923. * @ref_list: List of references
  5924. * @ctxt: Validation context
  5925. * @name: Name of ID we are searching for
  5926. *
  5927. */
  5928. static void
  5929. xmlValidateCheckRefCallback(void *payload, void *data, const xmlChar *name) {
  5930. xmlListPtr ref_list = (xmlListPtr) payload;
  5931. xmlValidCtxtPtr ctxt = (xmlValidCtxtPtr) data;
  5932. xmlValidateMemo memo;
  5933. if (ref_list == NULL)
  5934. return;
  5935. memo.ctxt = ctxt;
  5936. memo.name = name;
  5937. xmlListWalk(ref_list, xmlWalkValidateList, &memo);
  5938. }
  5939. /**
  5940. * xmlValidateDocumentFinal:
  5941. * @ctxt: the validation context
  5942. * @doc: a document instance
  5943. *
  5944. * Does the final step for the document validation once all the
  5945. * incremental validation steps have been completed
  5946. *
  5947. * basically it does the following checks described by the XML Rec
  5948. *
  5949. * Check all the IDREF/IDREFS attributes definition for validity
  5950. *
  5951. * returns 1 if valid or 0 otherwise
  5952. */
  5953. int
  5954. xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
  5955. xmlRefTablePtr table;
  5956. unsigned int save;
  5957. if (ctxt == NULL)
  5958. return(0);
  5959. if (doc == NULL) {
  5960. xmlErrValid(ctxt, XML_DTD_NO_DOC,
  5961. "xmlValidateDocumentFinal: doc == NULL\n", NULL);
  5962. return(0);
  5963. }
  5964. /* trick to get correct line id report */
  5965. save = ctxt->flags;
  5966. ctxt->flags &= ~XML_VCTXT_USE_PCTXT;
  5967. /*
  5968. * Check all the NOTATION/NOTATIONS attributes
  5969. */
  5970. /*
  5971. * Check all the ENTITY/ENTITIES attributes definition for validity
  5972. */
  5973. /*
  5974. * Check all the IDREF/IDREFS attributes definition for validity
  5975. */
  5976. table = (xmlRefTablePtr) doc->refs;
  5977. ctxt->doc = doc;
  5978. ctxt->valid = 1;
  5979. xmlHashScan(table, xmlValidateCheckRefCallback, ctxt);
  5980. ctxt->flags = save;
  5981. return(ctxt->valid);
  5982. }
  5983. /**
  5984. * xmlValidateDtd:
  5985. * @ctxt: the validation context
  5986. * @doc: a document instance
  5987. * @dtd: a dtd instance
  5988. *
  5989. * Try to validate the document against the dtd instance
  5990. *
  5991. * Basically it does check all the definitions in the DtD.
  5992. * Note the the internal subset (if present) is de-coupled
  5993. * (i.e. not used), which could give problems if ID or IDREF
  5994. * is present.
  5995. *
  5996. * returns 1 if valid or 0 otherwise
  5997. */
  5998. int
  5999. xmlValidateDtd(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd) {
  6000. int ret;
  6001. xmlDtdPtr oldExt, oldInt;
  6002. xmlNodePtr root;
  6003. if (dtd == NULL) return(0);
  6004. if (doc == NULL) return(0);
  6005. oldExt = doc->extSubset;
  6006. oldInt = doc->intSubset;
  6007. doc->extSubset = dtd;
  6008. doc->intSubset = NULL;
  6009. ret = xmlValidateRoot(ctxt, doc);
  6010. if (ret == 0) {
  6011. doc->extSubset = oldExt;
  6012. doc->intSubset = oldInt;
  6013. return(ret);
  6014. }
  6015. if (doc->ids != NULL) {
  6016. xmlFreeIDTable(doc->ids);
  6017. doc->ids = NULL;
  6018. }
  6019. if (doc->refs != NULL) {
  6020. xmlFreeRefTable(doc->refs);
  6021. doc->refs = NULL;
  6022. }
  6023. root = xmlDocGetRootElement(doc);
  6024. ret = xmlValidateElement(ctxt, doc, root);
  6025. ret &= xmlValidateDocumentFinal(ctxt, doc);
  6026. doc->extSubset = oldExt;
  6027. doc->intSubset = oldInt;
  6028. return(ret);
  6029. }
  6030. static void
  6031. xmlValidateNotationCallback(void *payload, void *data,
  6032. const xmlChar *name ATTRIBUTE_UNUSED) {
  6033. xmlEntityPtr cur = (xmlEntityPtr) payload;
  6034. xmlValidCtxtPtr ctxt = (xmlValidCtxtPtr) data;
  6035. if (cur == NULL)
  6036. return;
  6037. if (cur->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
  6038. xmlChar *notation = cur->content;
  6039. if (notation != NULL) {
  6040. int ret;
  6041. ret = xmlValidateNotationUse(ctxt, cur->doc, notation);
  6042. if (ret != 1) {
  6043. ctxt->valid = 0;
  6044. }
  6045. }
  6046. }
  6047. }
  6048. static void
  6049. xmlValidateAttributeCallback(void *payload, void *data,
  6050. const xmlChar *name ATTRIBUTE_UNUSED) {
  6051. xmlAttributePtr cur = (xmlAttributePtr) payload;
  6052. xmlValidCtxtPtr ctxt = (xmlValidCtxtPtr) data;
  6053. int ret;
  6054. xmlDocPtr doc;
  6055. xmlElementPtr elem = NULL;
  6056. if (cur == NULL)
  6057. return;
  6058. switch (cur->atype) {
  6059. case XML_ATTRIBUTE_CDATA:
  6060. case XML_ATTRIBUTE_ID:
  6061. case XML_ATTRIBUTE_IDREF :
  6062. case XML_ATTRIBUTE_IDREFS:
  6063. case XML_ATTRIBUTE_NMTOKEN:
  6064. case XML_ATTRIBUTE_NMTOKENS:
  6065. case XML_ATTRIBUTE_ENUMERATION:
  6066. break;
  6067. case XML_ATTRIBUTE_ENTITY:
  6068. case XML_ATTRIBUTE_ENTITIES:
  6069. case XML_ATTRIBUTE_NOTATION:
  6070. if (cur->defaultValue != NULL) {
  6071. ret = xmlValidateAttributeValue2(ctxt, ctxt->doc, cur->name,
  6072. cur->atype, cur->defaultValue);
  6073. if ((ret == 0) && (ctxt->valid == 1))
  6074. ctxt->valid = 0;
  6075. }
  6076. if (cur->tree != NULL) {
  6077. xmlEnumerationPtr tree = cur->tree;
  6078. while (tree != NULL) {
  6079. ret = xmlValidateAttributeValue2(ctxt, ctxt->doc,
  6080. cur->name, cur->atype, tree->name);
  6081. if ((ret == 0) && (ctxt->valid == 1))
  6082. ctxt->valid = 0;
  6083. tree = tree->next;
  6084. }
  6085. }
  6086. }
  6087. if (cur->atype == XML_ATTRIBUTE_NOTATION) {
  6088. doc = cur->doc;
  6089. if (cur->elem == NULL) {
  6090. xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
  6091. "xmlValidateAttributeCallback(%s): internal error\n",
  6092. (const char *) cur->name);
  6093. return;
  6094. }
  6095. if (doc != NULL)
  6096. elem = xmlGetDtdElementDesc(doc->intSubset, cur->elem);
  6097. if ((elem == NULL) && (doc != NULL))
  6098. elem = xmlGetDtdElementDesc(doc->extSubset, cur->elem);
  6099. if ((elem == NULL) && (cur->parent != NULL) &&
  6100. (cur->parent->type == XML_DTD_NODE))
  6101. elem = xmlGetDtdElementDesc((xmlDtdPtr) cur->parent, cur->elem);
  6102. if (elem == NULL) {
  6103. xmlErrValidNode(ctxt, NULL, XML_DTD_UNKNOWN_ELEM,
  6104. "attribute %s: could not find decl for element %s\n",
  6105. cur->name, cur->elem, NULL);
  6106. return;
  6107. }
  6108. if (elem->etype == XML_ELEMENT_TYPE_EMPTY) {
  6109. xmlErrValidNode(ctxt, NULL, XML_DTD_EMPTY_NOTATION,
  6110. "NOTATION attribute %s declared for EMPTY element %s\n",
  6111. cur->name, cur->elem, NULL);
  6112. ctxt->valid = 0;
  6113. }
  6114. }
  6115. }
  6116. /**
  6117. * xmlValidateDtdFinal:
  6118. * @ctxt: the validation context
  6119. * @doc: a document instance
  6120. *
  6121. * Does the final step for the dtds validation once all the
  6122. * subsets have been parsed
  6123. *
  6124. * basically it does the following checks described by the XML Rec
  6125. * - check that ENTITY and ENTITIES type attributes default or
  6126. * possible values matches one of the defined entities.
  6127. * - check that NOTATION type attributes default or
  6128. * possible values matches one of the defined notations.
  6129. *
  6130. * returns 1 if valid or 0 if invalid and -1 if not well-formed
  6131. */
  6132. int
  6133. xmlValidateDtdFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
  6134. xmlDtdPtr dtd;
  6135. xmlAttributeTablePtr table;
  6136. xmlEntitiesTablePtr entities;
  6137. if ((doc == NULL) || (ctxt == NULL)) return(0);
  6138. if ((doc->intSubset == NULL) && (doc->extSubset == NULL))
  6139. return(0);
  6140. ctxt->doc = doc;
  6141. ctxt->valid = 1;
  6142. dtd = doc->intSubset;
  6143. if ((dtd != NULL) && (dtd->attributes != NULL)) {
  6144. table = (xmlAttributeTablePtr) dtd->attributes;
  6145. xmlHashScan(table, xmlValidateAttributeCallback, ctxt);
  6146. }
  6147. if ((dtd != NULL) && (dtd->entities != NULL)) {
  6148. entities = (xmlEntitiesTablePtr) dtd->entities;
  6149. xmlHashScan(entities, xmlValidateNotationCallback, ctxt);
  6150. }
  6151. dtd = doc->extSubset;
  6152. if ((dtd != NULL) && (dtd->attributes != NULL)) {
  6153. table = (xmlAttributeTablePtr) dtd->attributes;
  6154. xmlHashScan(table, xmlValidateAttributeCallback, ctxt);
  6155. }
  6156. if ((dtd != NULL) && (dtd->entities != NULL)) {
  6157. entities = (xmlEntitiesTablePtr) dtd->entities;
  6158. xmlHashScan(entities, xmlValidateNotationCallback, ctxt);
  6159. }
  6160. return(ctxt->valid);
  6161. }
  6162. /**
  6163. * xmlValidateDocument:
  6164. * @ctxt: the validation context
  6165. * @doc: a document instance
  6166. *
  6167. * Try to validate the document instance
  6168. *
  6169. * basically it does the all the checks described by the XML Rec
  6170. * i.e. validates the internal and external subset (if present)
  6171. * and validate the document tree.
  6172. *
  6173. * returns 1 if valid or 0 otherwise
  6174. */
  6175. int
  6176. xmlValidateDocument(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
  6177. int ret;
  6178. xmlNodePtr root;
  6179. if (doc == NULL)
  6180. return(0);
  6181. if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) {
  6182. xmlErrValid(ctxt, XML_DTD_NO_DTD,
  6183. "no DTD found!\n", NULL);
  6184. return(0);
  6185. }
  6186. if ((doc->intSubset != NULL) && ((doc->intSubset->SystemID != NULL) ||
  6187. (doc->intSubset->ExternalID != NULL)) && (doc->extSubset == NULL)) {
  6188. xmlChar *sysID;
  6189. if (doc->intSubset->SystemID != NULL) {
  6190. sysID = xmlBuildURI(doc->intSubset->SystemID,
  6191. doc->URL);
  6192. if (sysID == NULL) {
  6193. xmlErrValid(ctxt, XML_DTD_LOAD_ERROR,
  6194. "Could not build URI for external subset \"%s\"\n",
  6195. (const char *) doc->intSubset->SystemID);
  6196. return 0;
  6197. }
  6198. } else
  6199. sysID = NULL;
  6200. doc->extSubset = xmlParseDTD(doc->intSubset->ExternalID,
  6201. (const xmlChar *)sysID);
  6202. if (sysID != NULL)
  6203. xmlFree(sysID);
  6204. if (doc->extSubset == NULL) {
  6205. if (doc->intSubset->SystemID != NULL) {
  6206. xmlErrValid(ctxt, XML_DTD_LOAD_ERROR,
  6207. "Could not load the external subset \"%s\"\n",
  6208. (const char *) doc->intSubset->SystemID);
  6209. } else {
  6210. xmlErrValid(ctxt, XML_DTD_LOAD_ERROR,
  6211. "Could not load the external subset \"%s\"\n",
  6212. (const char *) doc->intSubset->ExternalID);
  6213. }
  6214. return(0);
  6215. }
  6216. }
  6217. if (doc->ids != NULL) {
  6218. xmlFreeIDTable(doc->ids);
  6219. doc->ids = NULL;
  6220. }
  6221. if (doc->refs != NULL) {
  6222. xmlFreeRefTable(doc->refs);
  6223. doc->refs = NULL;
  6224. }
  6225. ret = xmlValidateDtdFinal(ctxt, doc);
  6226. if (!xmlValidateRoot(ctxt, doc)) return(0);
  6227. root = xmlDocGetRootElement(doc);
  6228. ret &= xmlValidateElement(ctxt, doc, root);
  6229. ret &= xmlValidateDocumentFinal(ctxt, doc);
  6230. return(ret);
  6231. }
  6232. /************************************************************************
  6233. * *
  6234. * Routines for dynamic validation editing *
  6235. * *
  6236. ************************************************************************/
  6237. /**
  6238. * xmlValidGetPotentialChildren:
  6239. * @ctree: an element content tree
  6240. * @names: an array to store the list of child names
  6241. * @len: a pointer to the number of element in the list
  6242. * @max: the size of the array
  6243. *
  6244. * Build/extend a list of potential children allowed by the content tree
  6245. *
  6246. * returns the number of element in the list, or -1 in case of error.
  6247. */
  6248. int
  6249. xmlValidGetPotentialChildren(xmlElementContent *ctree,
  6250. const xmlChar **names,
  6251. int *len, int max) {
  6252. int i;
  6253. if ((ctree == NULL) || (names == NULL) || (len == NULL))
  6254. return(-1);
  6255. if (*len >= max) return(*len);
  6256. switch (ctree->type) {
  6257. case XML_ELEMENT_CONTENT_PCDATA:
  6258. for (i = 0; i < *len;i++)
  6259. if (xmlStrEqual(BAD_CAST "#PCDATA", names[i])) return(*len);
  6260. names[(*len)++] = BAD_CAST "#PCDATA";
  6261. break;
  6262. case XML_ELEMENT_CONTENT_ELEMENT:
  6263. for (i = 0; i < *len;i++)
  6264. if (xmlStrEqual(ctree->name, names[i])) return(*len);
  6265. names[(*len)++] = ctree->name;
  6266. break;
  6267. case XML_ELEMENT_CONTENT_SEQ:
  6268. xmlValidGetPotentialChildren(ctree->c1, names, len, max);
  6269. xmlValidGetPotentialChildren(ctree->c2, names, len, max);
  6270. break;
  6271. case XML_ELEMENT_CONTENT_OR:
  6272. xmlValidGetPotentialChildren(ctree->c1, names, len, max);
  6273. xmlValidGetPotentialChildren(ctree->c2, names, len, max);
  6274. break;
  6275. }
  6276. return(*len);
  6277. }
  6278. /*
  6279. * Dummy function to suppress messages while we try out valid elements
  6280. */
  6281. static void xmlNoValidityErr(void *ctx ATTRIBUTE_UNUSED,
  6282. const char *msg ATTRIBUTE_UNUSED, ...) {
  6283. return;
  6284. }
  6285. /**
  6286. * xmlValidGetValidElements:
  6287. * @prev: an element to insert after
  6288. * @next: an element to insert next
  6289. * @names: an array to store the list of child names
  6290. * @max: the size of the array
  6291. *
  6292. * This function returns the list of authorized children to insert
  6293. * within an existing tree while respecting the validity constraints
  6294. * forced by the Dtd. The insertion point is defined using @prev and
  6295. * @next in the following ways:
  6296. * to insert before 'node': xmlValidGetValidElements(node->prev, node, ...
  6297. * to insert next 'node': xmlValidGetValidElements(node, node->next, ...
  6298. * to replace 'node': xmlValidGetValidElements(node->prev, node->next, ...
  6299. * to prepend a child to 'node': xmlValidGetValidElements(NULL, node->childs,
  6300. * to append a child to 'node': xmlValidGetValidElements(node->last, NULL, ...
  6301. *
  6302. * pointers to the element names are inserted at the beginning of the array
  6303. * and do not need to be freed.
  6304. *
  6305. * returns the number of element in the list, or -1 in case of error. If
  6306. * the function returns the value @max the caller is invited to grow the
  6307. * receiving array and retry.
  6308. */
  6309. int
  6310. xmlValidGetValidElements(xmlNode *prev, xmlNode *next, const xmlChar **names,
  6311. int max) {
  6312. xmlValidCtxt vctxt;
  6313. int nb_valid_elements = 0;
  6314. const xmlChar *elements[256]={0};
  6315. int nb_elements = 0, i;
  6316. const xmlChar *name;
  6317. xmlNode *ref_node;
  6318. xmlNode *parent;
  6319. xmlNode *test_node;
  6320. xmlNode *prev_next;
  6321. xmlNode *next_prev;
  6322. xmlNode *parent_childs;
  6323. xmlNode *parent_last;
  6324. xmlElement *element_desc;
  6325. if (prev == NULL && next == NULL)
  6326. return(-1);
  6327. if (names == NULL) return(-1);
  6328. if (max <= 0) return(-1);
  6329. memset(&vctxt, 0, sizeof (xmlValidCtxt));
  6330. vctxt.error = xmlNoValidityErr; /* this suppresses err/warn output */
  6331. nb_valid_elements = 0;
  6332. ref_node = prev ? prev : next;
  6333. parent = ref_node->parent;
  6334. /*
  6335. * Retrieves the parent element declaration
  6336. */
  6337. element_desc = xmlGetDtdElementDesc(parent->doc->intSubset,
  6338. parent->name);
  6339. if ((element_desc == NULL) && (parent->doc->extSubset != NULL))
  6340. element_desc = xmlGetDtdElementDesc(parent->doc->extSubset,
  6341. parent->name);
  6342. if (element_desc == NULL) return(-1);
  6343. /*
  6344. * Do a backup of the current tree structure
  6345. */
  6346. prev_next = prev ? prev->next : NULL;
  6347. next_prev = next ? next->prev : NULL;
  6348. parent_childs = parent->children;
  6349. parent_last = parent->last;
  6350. /*
  6351. * Creates a dummy node and insert it into the tree
  6352. */
  6353. test_node = xmlNewDocNode (ref_node->doc, NULL, BAD_CAST "<!dummy?>", NULL);
  6354. if (test_node == NULL)
  6355. return(-1);
  6356. test_node->parent = parent;
  6357. test_node->prev = prev;
  6358. test_node->next = next;
  6359. name = test_node->name;
  6360. if (prev) prev->next = test_node;
  6361. else parent->children = test_node;
  6362. if (next) next->prev = test_node;
  6363. else parent->last = test_node;
  6364. /*
  6365. * Insert each potential child node and check if the parent is
  6366. * still valid
  6367. */
  6368. nb_elements = xmlValidGetPotentialChildren(element_desc->content,
  6369. elements, &nb_elements, 256);
  6370. for (i = 0;i < nb_elements;i++) {
  6371. test_node->name = elements[i];
  6372. if (xmlValidateOneElement(&vctxt, parent->doc, parent)) {
  6373. int j;
  6374. for (j = 0; j < nb_valid_elements;j++)
  6375. if (xmlStrEqual(elements[i], names[j])) break;
  6376. names[nb_valid_elements++] = elements[i];
  6377. if (nb_valid_elements >= max) break;
  6378. }
  6379. }
  6380. /*
  6381. * Restore the tree structure
  6382. */
  6383. if (prev) prev->next = prev_next;
  6384. if (next) next->prev = next_prev;
  6385. parent->children = parent_childs;
  6386. parent->last = parent_last;
  6387. /*
  6388. * Free up the dummy node
  6389. */
  6390. test_node->name = name;
  6391. xmlFreeNode(test_node);
  6392. return(nb_valid_elements);
  6393. }
  6394. #endif /* LIBXML_VALID_ENABLED */