ReactOS 0.4.16-dev-2206-gc56950d
valid.c
Go to the documentation of this file.
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
10#define IN_LIBXML
11#include "libxml.h"
12
13#include <string.h>
14#include <stdlib.h>
15
16#include <libxml/xmlmemory.h>
17#include <libxml/hash.h>
18#include <libxml/uri.h>
19#include <libxml/valid.h>
20#include <libxml/parser.h>
22#include <libxml/xmlerror.h>
23#include <libxml/list.h>
24
25#include "private/error.h"
26#include "private/parser.h"
27
28static xmlElementPtr
29xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
30 int create);
31
32#define TODO \
33 xmlGenericError(xmlGenericErrorContext, \
34 "Unimplemented block at %s:%d\n", \
35 __FILE__, __LINE__);
36
37#ifdef LIBXML_VALID_ENABLED
38static int
39xmlValidateAttributeValueInternal(xmlDocPtr doc, xmlAttributeType type,
40 const xmlChar *value);
41#endif
42/************************************************************************
43 * *
44 * Error handling routines *
45 * *
46 ************************************************************************/
47
55static void
57{
58 xmlGenericErrorFunc channel = NULL;
59 xmlParserCtxtPtr pctxt = NULL;
60 void *data = NULL;
61
62 if (ctxt != NULL) {
63 channel = ctxt->error;
64 data = ctxt->userData;
65 /* Look up flag to detect if it is part of a parsing
66 context */
67 if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
68 pctxt = ctxt->userData;
69 }
70 }
71 if (extra)
72 __xmlRaiseError(NULL, channel, data,
74 XML_ERR_FATAL, NULL, 0, extra, NULL, NULL, 0, 0,
75 "Memory allocation failed : %s\n", extra);
76 else
77 __xmlRaiseError(NULL, channel, data,
79 XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0,
80 "Memory allocation failed\n");
81}
82
91static void LIBXML_ATTR_FORMAT(3,0)
92xmlErrValid(xmlValidCtxtPtr ctxt, xmlParserErrors error,
93 const char *msg, const char *extra)
94{
95 xmlGenericErrorFunc channel = NULL;
96 xmlParserCtxtPtr pctxt = NULL;
97 void *data = NULL;
98
99 if (ctxt != NULL) {
100 channel = ctxt->error;
101 data = ctxt->userData;
102 /* Look up flag to detect if it is part of a parsing
103 context */
104 if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
105 pctxt = ctxt->userData;
106 }
107 }
108 if (extra)
109 __xmlRaiseError(NULL, channel, data,
110 pctxt, NULL, XML_FROM_VALID, error,
111 XML_ERR_ERROR, NULL, 0, extra, NULL, NULL, 0, 0,
112 msg, extra);
113 else
114 __xmlRaiseError(NULL, channel, data,
115 pctxt, NULL, XML_FROM_VALID, error,
116 XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
117 "%s", msg);
118}
119
120#if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
132static void LIBXML_ATTR_FORMAT(4,0)
133xmlErrValidNode(xmlValidCtxtPtr ctxt,
134 xmlNodePtr node, xmlParserErrors error,
135 const char *msg, const xmlChar * str1,
136 const xmlChar * str2, const xmlChar * str3)
137{
138 xmlStructuredErrorFunc schannel = NULL;
139 xmlGenericErrorFunc channel = NULL;
140 xmlParserCtxtPtr pctxt = NULL;
141 void *data = NULL;
142
143 if (ctxt != NULL) {
144 channel = ctxt->error;
145 data = ctxt->userData;
146 /* Look up flag to detect if it is part of a parsing
147 context */
148 if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
149 pctxt = ctxt->userData;
150 }
151 }
152 __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error,
154 (const char *) str1,
155 (const char *) str2,
156 (const char *) str3, 0, 0, msg, str1, str2, str3);
157}
158#endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */
159
160#ifdef LIBXML_VALID_ENABLED
172static void LIBXML_ATTR_FORMAT(4,0)
173xmlErrValidNodeNr(xmlValidCtxtPtr ctxt,
174 xmlNodePtr node, xmlParserErrors error,
175 const char *msg, const xmlChar * str1,
176 int int2, const xmlChar * str3)
177{
178 xmlStructuredErrorFunc schannel = NULL;
179 xmlGenericErrorFunc channel = NULL;
180 xmlParserCtxtPtr pctxt = NULL;
181 void *data = NULL;
182
183 if (ctxt != NULL) {
184 channel = ctxt->error;
185 data = ctxt->userData;
186 /* Look up flag to detect if it is part of a parsing
187 context */
188 if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
189 pctxt = ctxt->userData;
190 }
191 }
192 __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error,
194 (const char *) str1,
195 (const char *) str3,
196 NULL, int2, 0, msg, str1, int2, str3);
197}
198
210static void LIBXML_ATTR_FORMAT(4,0)
211xmlErrValidWarning(xmlValidCtxtPtr ctxt,
212 xmlNodePtr node, xmlParserErrors error,
213 const char *msg, const xmlChar * str1,
214 const xmlChar * str2, const xmlChar * str3)
215{
216 xmlStructuredErrorFunc schannel = NULL;
217 xmlGenericErrorFunc channel = NULL;
218 xmlParserCtxtPtr pctxt = NULL;
219 void *data = NULL;
220
221 if (ctxt != NULL) {
222 channel = ctxt->warning;
223 data = ctxt->userData;
224 /* Look up flag to detect if it is part of a parsing
225 context */
226 if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
227 pctxt = ctxt->userData;
228 }
229 }
230 __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error,
232 (const char *) str1,
233 (const char *) str2,
234 (const char *) str3, 0, 0, msg, str1, str2, str3);
235}
236
237
238
239#ifdef LIBXML_REGEXP_ENABLED
240/*
241 * If regexp are enabled we can do continuous validation without the
242 * need of a tree to validate the content model. this is done in each
243 * callbacks.
244 * Each xmlValidState represent the validation state associated to the
245 * set of nodes currently open from the document root to the current element.
246 */
247
248
249typedef struct _xmlValidState {
250 xmlElementPtr elemDecl; /* pointer to the content model */
251 xmlNodePtr node; /* pointer to the current node */
252 xmlRegExecCtxtPtr exec; /* regexp runtime */
253} _xmlValidState;
254
255
256static int
257vstateVPush(xmlValidCtxtPtr ctxt, xmlElementPtr elemDecl, xmlNodePtr node) {
258 if ((ctxt->vstateMax == 0) || (ctxt->vstateTab == NULL)) {
259 ctxt->vstateMax = 10;
260 ctxt->vstateTab = (xmlValidState *) xmlMalloc(ctxt->vstateMax *
261 sizeof(ctxt->vstateTab[0]));
262 if (ctxt->vstateTab == NULL) {
263 xmlVErrMemory(ctxt, "malloc failed");
264 return(-1);
265 }
266 }
267
268 if (ctxt->vstateNr >= ctxt->vstateMax) {
269 xmlValidState *tmp;
270
271 tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
272 2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
273 if (tmp == NULL) {
274 xmlVErrMemory(ctxt, "realloc failed");
275 return(-1);
276 }
277 ctxt->vstateMax *= 2;
278 ctxt->vstateTab = tmp;
279 }
280 ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr];
281 ctxt->vstateTab[ctxt->vstateNr].elemDecl = elemDecl;
282 ctxt->vstateTab[ctxt->vstateNr].node = node;
283 if ((elemDecl != NULL) && (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT)) {
284 if (elemDecl->contModel == NULL)
285 xmlValidBuildContentModel(ctxt, elemDecl);
286 if (elemDecl->contModel != NULL) {
287 ctxt->vstateTab[ctxt->vstateNr].exec =
288 xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL);
289 } else {
290 ctxt->vstateTab[ctxt->vstateNr].exec = NULL;
291 xmlErrValidNode(ctxt, (xmlNodePtr) elemDecl,
293 "Failed to build content model regexp for %s\n",
294 node->name, NULL, NULL);
295 }
296 }
297 return(ctxt->vstateNr++);
298}
299
300static int
301vstateVPop(xmlValidCtxtPtr ctxt) {
302 xmlElementPtr elemDecl;
303
304 if (ctxt->vstateNr < 1) return(-1);
305 ctxt->vstateNr--;
306 elemDecl = ctxt->vstateTab[ctxt->vstateNr].elemDecl;
307 ctxt->vstateTab[ctxt->vstateNr].elemDecl = NULL;
308 ctxt->vstateTab[ctxt->vstateNr].node = NULL;
309 if ((elemDecl != NULL) && (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT)) {
310 xmlRegFreeExecCtxt(ctxt->vstateTab[ctxt->vstateNr].exec);
311 }
312 ctxt->vstateTab[ctxt->vstateNr].exec = NULL;
313 if (ctxt->vstateNr >= 1)
314 ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr - 1];
315 else
316 ctxt->vstate = NULL;
317 return(ctxt->vstateNr);
318}
319
320#else /* not LIBXML_REGEXP_ENABLED */
321/*
322 * If regexp are not enabled, it uses a home made algorithm less
323 * complex and easier to
324 * debug/maintain than a generic NFA -> DFA state based algo. The
325 * only restriction is on the deepness of the tree limited by the
326 * size of the occurs bitfield
327 *
328 * this is the content of a saved state for rollbacks
329 */
330
331#define ROLLBACK_OR 0
332#define ROLLBACK_PARENT 1
333
334typedef struct _xmlValidState {
335 xmlElementContentPtr cont; /* pointer to the content model subtree */
336 xmlNodePtr node; /* pointer to the current node in the list */
337 long occurs;/* bitfield for multiple occurrences */
338 unsigned char depth; /* current depth in the overall tree */
339 unsigned char state; /* ROLLBACK_XXX */
340} _xmlValidState;
341
342#define MAX_RECURSE 25000
343#define MAX_DEPTH ((sizeof(_xmlValidState.occurs)) * 8)
344#define CONT ctxt->vstate->cont
345#define NODE ctxt->vstate->node
346#define DEPTH ctxt->vstate->depth
347#define OCCURS ctxt->vstate->occurs
348#define STATE ctxt->vstate->state
349
350#define OCCURRENCE (ctxt->vstate->occurs & (1 << DEPTH))
351#define PARENT_OCCURRENCE (ctxt->vstate->occurs & ((1 << DEPTH) - 1))
352
353#define SET_OCCURRENCE ctxt->vstate->occurs |= (1 << DEPTH)
354#define RESET_OCCURRENCE ctxt->vstate->occurs &= ((1 << DEPTH) - 1)
355
356static int
357vstateVPush(xmlValidCtxtPtr ctxt, xmlElementContentPtr cont,
358 xmlNodePtr node, unsigned char depth, long occurs,
359 unsigned char state) {
360 int i = ctxt->vstateNr - 1;
361
362 if (ctxt->vstateNr > MAX_RECURSE) {
363 return(-1);
364 }
365 if (ctxt->vstateTab == NULL) {
366 ctxt->vstateMax = 8;
367 ctxt->vstateTab = (xmlValidState *) xmlMalloc(
368 ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
369 if (ctxt->vstateTab == NULL) {
370 xmlVErrMemory(ctxt, "malloc failed");
371 return(-1);
372 }
373 }
374 if (ctxt->vstateNr >= ctxt->vstateMax) {
375 xmlValidState *tmp;
376
377 tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
378 2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
379 if (tmp == NULL) {
380 xmlVErrMemory(ctxt, "malloc failed");
381 return(-1);
382 }
383 ctxt->vstateMax *= 2;
384 ctxt->vstateTab = tmp;
385 ctxt->vstate = &ctxt->vstateTab[0];
386 }
387 /*
388 * Don't push on the stack a state already here
389 */
390 if ((i >= 0) && (ctxt->vstateTab[i].cont == cont) &&
391 (ctxt->vstateTab[i].node == node) &&
392 (ctxt->vstateTab[i].depth == depth) &&
393 (ctxt->vstateTab[i].occurs == occurs) &&
394 (ctxt->vstateTab[i].state == state))
395 return(ctxt->vstateNr);
396 ctxt->vstateTab[ctxt->vstateNr].cont = cont;
397 ctxt->vstateTab[ctxt->vstateNr].node = node;
398 ctxt->vstateTab[ctxt->vstateNr].depth = depth;
399 ctxt->vstateTab[ctxt->vstateNr].occurs = occurs;
400 ctxt->vstateTab[ctxt->vstateNr].state = state;
401 return(ctxt->vstateNr++);
402}
403
404static int
405vstateVPop(xmlValidCtxtPtr ctxt) {
406 if (ctxt->vstateNr <= 1) return(-1);
407 ctxt->vstateNr--;
408 ctxt->vstate = &ctxt->vstateTab[0];
409 ctxt->vstate->cont = ctxt->vstateTab[ctxt->vstateNr].cont;
410 ctxt->vstate->node = ctxt->vstateTab[ctxt->vstateNr].node;
411 ctxt->vstate->depth = ctxt->vstateTab[ctxt->vstateNr].depth;
412 ctxt->vstate->occurs = ctxt->vstateTab[ctxt->vstateNr].occurs;
413 ctxt->vstate->state = ctxt->vstateTab[ctxt->vstateNr].state;
414 return(ctxt->vstateNr);
415}
416
417#endif /* LIBXML_REGEXP_ENABLED */
418
419static int
420nodeVPush(xmlValidCtxtPtr ctxt, xmlNodePtr value)
421{
422 if (ctxt->nodeMax <= 0) {
423 ctxt->nodeMax = 4;
424 ctxt->nodeTab =
425 (xmlNodePtr *) xmlMalloc(ctxt->nodeMax *
426 sizeof(ctxt->nodeTab[0]));
427 if (ctxt->nodeTab == NULL) {
428 xmlVErrMemory(ctxt, "malloc failed");
429 ctxt->nodeMax = 0;
430 return (0);
431 }
432 }
433 if (ctxt->nodeNr >= ctxt->nodeMax) {
434 xmlNodePtr *tmp;
435 tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
436 ctxt->nodeMax * 2 * sizeof(ctxt->nodeTab[0]));
437 if (tmp == NULL) {
438 xmlVErrMemory(ctxt, "realloc failed");
439 return (0);
440 }
441 ctxt->nodeMax *= 2;
442 ctxt->nodeTab = tmp;
443 }
444 ctxt->nodeTab[ctxt->nodeNr] = value;
445 ctxt->node = value;
446 return (ctxt->nodeNr++);
447}
448static xmlNodePtr
449nodeVPop(xmlValidCtxtPtr ctxt)
450{
451 xmlNodePtr ret;
452
453 if (ctxt->nodeNr <= 0)
454 return (NULL);
455 ctxt->nodeNr--;
456 if (ctxt->nodeNr > 0)
457 ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
458 else
459 ctxt->node = NULL;
460 ret = ctxt->nodeTab[ctxt->nodeNr];
461 ctxt->nodeTab[ctxt->nodeNr] = NULL;
462 return (ret);
463}
464
465/* TODO: use hash table for accesses to elem and attribute definitions */
466
467
468#define CHECK_DTD \
469 if (doc == NULL) return(0); \
470 else if ((doc->intSubset == NULL) && \
471 (doc->extSubset == NULL)) return(0)
472
473#ifdef LIBXML_REGEXP_ENABLED
474
475/************************************************************************
476 * *
477 * Content model validation based on the regexps *
478 * *
479 ************************************************************************/
480
491static int
492xmlValidBuildAContentModel(xmlElementContentPtr content,
493 xmlValidCtxtPtr ctxt,
494 const xmlChar *name) {
495 if (content == NULL) {
496 xmlErrValidNode(ctxt, NULL, XML_ERR_INTERNAL_ERROR,
497 "Found NULL content in content model of %s\n",
498 name, NULL, NULL);
499 return(0);
500 }
501 switch (content->type) {
502 case XML_ELEMENT_CONTENT_PCDATA:
503 xmlErrValidNode(ctxt, NULL, XML_ERR_INTERNAL_ERROR,
504 "Found PCDATA in content model of %s\n",
505 name, NULL, NULL);
506 return(0);
507 break;
508 case XML_ELEMENT_CONTENT_ELEMENT: {
509 xmlAutomataStatePtr oldstate = ctxt->state;
510 xmlChar fn[50];
512
513 fullname = xmlBuildQName(content->name, content->prefix, fn, 50);
514 if (fullname == NULL) {
515 xmlVErrMemory(ctxt, "Building content model");
516 return(0);
517 }
518
519 switch (content->ocur) {
520 case XML_ELEMENT_CONTENT_ONCE:
521 ctxt->state = xmlAutomataNewTransition(ctxt->am,
522 ctxt->state, NULL, fullname, NULL);
523 break;
524 case XML_ELEMENT_CONTENT_OPT:
525 ctxt->state = xmlAutomataNewTransition(ctxt->am,
526 ctxt->state, NULL, fullname, NULL);
527 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
528 break;
529 case XML_ELEMENT_CONTENT_PLUS:
530 ctxt->state = xmlAutomataNewTransition(ctxt->am,
531 ctxt->state, NULL, fullname, NULL);
532 xmlAutomataNewTransition(ctxt->am, ctxt->state,
533 ctxt->state, fullname, NULL);
534 break;
535 case XML_ELEMENT_CONTENT_MULT:
536 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
537 ctxt->state, NULL);
538 xmlAutomataNewTransition(ctxt->am,
539 ctxt->state, ctxt->state, fullname, NULL);
540 break;
541 }
542 if ((fullname != fn) && (fullname != content->name))
544 break;
545 }
546 case XML_ELEMENT_CONTENT_SEQ: {
547 xmlAutomataStatePtr oldstate, oldend;
548 xmlElementContentOccur ocur;
549
550 /*
551 * Simply iterate over the content
552 */
553 oldstate = ctxt->state;
554 ocur = content->ocur;
555 if (ocur != XML_ELEMENT_CONTENT_ONCE) {
556 ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
557 oldstate = ctxt->state;
558 }
559 do {
560 xmlValidBuildAContentModel(content->c1, ctxt, name);
561 content = content->c2;
562 } while ((content->type == XML_ELEMENT_CONTENT_SEQ) &&
563 (content->ocur == XML_ELEMENT_CONTENT_ONCE));
564 xmlValidBuildAContentModel(content, ctxt, name);
565 oldend = ctxt->state;
566 ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL);
567 switch (ocur) {
568 case XML_ELEMENT_CONTENT_ONCE:
569 break;
570 case XML_ELEMENT_CONTENT_OPT:
571 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
572 break;
573 case XML_ELEMENT_CONTENT_MULT:
574 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
575 xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
576 break;
577 case XML_ELEMENT_CONTENT_PLUS:
578 xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
579 break;
580 }
581 break;
582 }
583 case XML_ELEMENT_CONTENT_OR: {
584 xmlAutomataStatePtr oldstate, oldend;
585 xmlElementContentOccur ocur;
586
587 ocur = content->ocur;
588 if ((ocur == XML_ELEMENT_CONTENT_PLUS) ||
589 (ocur == XML_ELEMENT_CONTENT_MULT)) {
590 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
591 ctxt->state, NULL);
592 }
593 oldstate = ctxt->state;
594 oldend = xmlAutomataNewState(ctxt->am);
595
596 /*
597 * iterate over the subtypes and remerge the end with an
598 * epsilon transition
599 */
600 do {
601 ctxt->state = oldstate;
602 xmlValidBuildAContentModel(content->c1, ctxt, name);
603 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend);
604 content = content->c2;
605 } while ((content->type == XML_ELEMENT_CONTENT_OR) &&
606 (content->ocur == XML_ELEMENT_CONTENT_ONCE));
607 ctxt->state = oldstate;
608 xmlValidBuildAContentModel(content, ctxt, name);
609 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend);
610 ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL);
611 switch (ocur) {
612 case XML_ELEMENT_CONTENT_ONCE:
613 break;
614 case XML_ELEMENT_CONTENT_OPT:
615 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
616 break;
617 case XML_ELEMENT_CONTENT_MULT:
618 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
619 xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
620 break;
621 case XML_ELEMENT_CONTENT_PLUS:
622 xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
623 break;
624 }
625 break;
626 }
627 default:
628 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
629 "ContentModel broken for element %s\n",
630 (const char *) name);
631 return(0);
632 }
633 return(1);
634}
645int
646xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) {
647
648 if ((ctxt == NULL) || (elem == NULL))
649 return(0);
650 if (elem->type != XML_ELEMENT_DECL)
651 return(0);
652 if (elem->etype != XML_ELEMENT_TYPE_ELEMENT)
653 return(1);
654 /* TODO: should we rebuild in this case ? */
655 if (elem->contModel != NULL) {
656 if (!xmlRegexpIsDeterminist(elem->contModel)) {
657 ctxt->valid = 0;
658 return(0);
659 }
660 return(1);
661 }
662
663 ctxt->am = xmlNewAutomata();
664 if (ctxt->am == NULL) {
665 xmlErrValidNode(ctxt, (xmlNodePtr) elem,
667 "Cannot create automata for element %s\n",
668 elem->name, NULL, NULL);
669 return(0);
670 }
671 ctxt->state = xmlAutomataGetInitState(ctxt->am);
672 xmlValidBuildAContentModel(elem->content, ctxt, elem->name);
673 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
674 elem->contModel = xmlAutomataCompile(ctxt->am);
675 if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
676 char expr[5000];
677 expr[0] = 0;
678 xmlSnprintfElementContent(expr, 5000, elem->content, 1);
679 xmlErrValidNode(ctxt, (xmlNodePtr) elem,
681 "Content model of %s is not deterministic: %s\n",
682 elem->name, BAD_CAST expr, NULL);
683 ctxt->valid = 0;
684 ctxt->state = NULL;
685 xmlFreeAutomata(ctxt->am);
686 ctxt->am = NULL;
687 return(0);
688 }
689 ctxt->state = NULL;
690 xmlFreeAutomata(ctxt->am);
691 ctxt->am = NULL;
692 return(1);
693}
694
695#endif /* LIBXML_REGEXP_ENABLED */
696
697/****************************************************************
698 * *
699 * Util functions for data allocation/deallocation *
700 * *
701 ****************************************************************/
702
710xmlValidCtxtPtr xmlNewValidCtxt(void) {
712
713 if ((ret = xmlMalloc(sizeof (xmlValidCtxt))) == NULL) {
714 xmlVErrMemory(NULL, "malloc failed");
715 return (NULL);
716 }
717
718 (void) memset(ret, 0, sizeof (xmlValidCtxt));
719
720 return (ret);
721}
722
729void
730xmlFreeValidCtxt(xmlValidCtxtPtr cur) {
731 if (cur == NULL)
732 return;
733 if (cur->vstateTab != NULL)
734 xmlFree(cur->vstateTab);
735 if (cur->nodeTab != NULL)
736 xmlFree(cur->nodeTab);
737 xmlFree(cur);
738}
739
740#endif /* LIBXML_VALID_ENABLED */
741
752xmlElementContentPtr
754 xmlElementContentType type) {
755 xmlElementContentPtr ret;
756 xmlDictPtr dict = NULL;
757
758 if (doc != NULL)
759 dict = doc->dict;
760
761 switch(type) {
762 case XML_ELEMENT_CONTENT_ELEMENT:
763 if (name == NULL) {
764 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
765 "xmlNewElementContent : name == NULL !\n",
766 NULL);
767 }
768 break;
769 case XML_ELEMENT_CONTENT_PCDATA:
770 case XML_ELEMENT_CONTENT_SEQ:
771 case XML_ELEMENT_CONTENT_OR:
772 if (name != NULL) {
773 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
774 "xmlNewElementContent : name != NULL !\n",
775 NULL);
776 }
777 break;
778 default:
779 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
780 "Internal: ELEMENT content corrupted invalid type\n",
781 NULL);
782 return(NULL);
783 }
784 ret = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent));
785 if (ret == NULL) {
786 xmlVErrMemory(NULL, "malloc failed");
787 return(NULL);
788 }
789 memset(ret, 0, sizeof(xmlElementContent));
790 ret->type = type;
791 ret->ocur = XML_ELEMENT_CONTENT_ONCE;
792 if (name != NULL) {
793 int l;
794 const xmlChar *tmp;
795
796 tmp = xmlSplitQName3(name, &l);
797 if (tmp == NULL) {
798 if (dict == NULL)
799 ret->name = xmlStrdup(name);
800 else
801 ret->name = xmlDictLookup(dict, name, -1);
802 } else {
803 if (dict == NULL) {
804 ret->prefix = xmlStrndup(name, l);
805 ret->name = xmlStrdup(tmp);
806 } else {
807 ret->prefix = xmlDictLookup(dict, name, l);
808 ret->name = xmlDictLookup(dict, tmp, -1);
809 }
810 }
811 }
812 return(ret);
813}
814
825xmlElementContentPtr
826xmlNewElementContent(const xmlChar *name, xmlElementContentType type) {
828}
829
839xmlElementContentPtr
840xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) {
841 xmlElementContentPtr ret = NULL, prev = NULL, tmp;
842 xmlDictPtr dict = NULL;
843
844 if (cur == NULL) return(NULL);
845
846 if (doc != NULL)
847 dict = doc->dict;
848
849 ret = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent));
850 if (ret == NULL) {
851 xmlVErrMemory(NULL, "malloc failed");
852 return(NULL);
853 }
854 memset(ret, 0, sizeof(xmlElementContent));
855 ret->type = cur->type;
856 ret->ocur = cur->ocur;
857 if (cur->name != NULL) {
858 if (dict)
859 ret->name = xmlDictLookup(dict, cur->name, -1);
860 else
861 ret->name = xmlStrdup(cur->name);
862 }
863
864 if (cur->prefix != NULL) {
865 if (dict)
866 ret->prefix = xmlDictLookup(dict, cur->prefix, -1);
867 else
868 ret->prefix = xmlStrdup(cur->prefix);
869 }
870 if (cur->c1 != NULL)
871 ret->c1 = xmlCopyDocElementContent(doc, cur->c1);
872 if (ret->c1 != NULL)
873 ret->c1->parent = ret;
874 if (cur->c2 != NULL) {
875 prev = ret;
876 cur = cur->c2;
877 while (cur != NULL) {
878 tmp = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent));
879 if (tmp == NULL) {
880 xmlVErrMemory(NULL, "malloc failed");
881 return(ret);
882 }
883 memset(tmp, 0, sizeof(xmlElementContent));
884 tmp->type = cur->type;
885 tmp->ocur = cur->ocur;
886 prev->c2 = tmp;
887 tmp->parent = prev;
888 if (cur->name != NULL) {
889 if (dict)
890 tmp->name = xmlDictLookup(dict, cur->name, -1);
891 else
892 tmp->name = xmlStrdup(cur->name);
893 }
894
895 if (cur->prefix != NULL) {
896 if (dict)
897 tmp->prefix = xmlDictLookup(dict, cur->prefix, -1);
898 else
899 tmp->prefix = xmlStrdup(cur->prefix);
900 }
901 if (cur->c1 != NULL)
902 tmp->c1 = xmlCopyDocElementContent(doc,cur->c1);
903 if (tmp->c1 != NULL)
904 tmp->c1->parent = tmp;
905 prev = tmp;
906 cur = cur->c2;
907 }
908 }
909 return(ret);
910}
911
921xmlElementContentPtr
922xmlCopyElementContent(xmlElementContentPtr cur) {
924}
925
933void
934xmlFreeDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) {
935 xmlDictPtr dict = NULL;
936 size_t depth = 0;
937
938 if (cur == NULL)
939 return;
940 if (doc != NULL)
941 dict = doc->dict;
942
943 while (1) {
944 xmlElementContentPtr parent;
945
946 while ((cur->c1 != NULL) || (cur->c2 != NULL)) {
947 cur = (cur->c1 != NULL) ? cur->c1 : cur->c2;
948 depth += 1;
949 }
950
951 switch (cur->type) {
952 case XML_ELEMENT_CONTENT_PCDATA:
953 case XML_ELEMENT_CONTENT_ELEMENT:
954 case XML_ELEMENT_CONTENT_SEQ:
955 case XML_ELEMENT_CONTENT_OR:
956 break;
957 default:
958 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
959 "Internal: ELEMENT content corrupted invalid type\n",
960 NULL);
961 return;
962 }
963 if (dict) {
964 if ((cur->name != NULL) && (!xmlDictOwns(dict, cur->name)))
965 xmlFree((xmlChar *) cur->name);
966 if ((cur->prefix != NULL) && (!xmlDictOwns(dict, cur->prefix)))
967 xmlFree((xmlChar *) cur->prefix);
968 } else {
969 if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
970 if (cur->prefix != NULL) xmlFree((xmlChar *) cur->prefix);
971 }
972 parent = cur->parent;
973 if ((depth == 0) || (parent == NULL)) {
974 xmlFree(cur);
975 break;
976 }
977 if (cur == parent->c1)
978 parent->c1 = NULL;
979 else
980 parent->c2 = NULL;
981 xmlFree(cur);
982
983 if (parent->c2 != NULL) {
984 cur = parent->c2;
985 } else {
986 depth -= 1;
987 cur = parent;
988 }
989 }
990}
991
999void
1000xmlFreeElementContent(xmlElementContentPtr cur) {
1002}
1003
1004#ifdef LIBXML_OUTPUT_ENABLED
1012static void
1013xmlDumpElementOccur(xmlBufferPtr buf, xmlElementContentPtr cur) {
1014 switch (cur->ocur) {
1015 case XML_ELEMENT_CONTENT_ONCE:
1016 break;
1017 case XML_ELEMENT_CONTENT_OPT:
1018 xmlBufferWriteChar(buf, "?");
1019 break;
1020 case XML_ELEMENT_CONTENT_MULT:
1021 xmlBufferWriteChar(buf, "*");
1022 break;
1023 case XML_ELEMENT_CONTENT_PLUS:
1024 xmlBufferWriteChar(buf, "+");
1025 break;
1026 }
1027}
1028
1036static void
1037xmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content) {
1038 xmlElementContentPtr cur;
1039
1040 if (content == NULL) return;
1041
1042 xmlBufferWriteChar(buf, "(");
1043 cur = content;
1044
1045 do {
1046 if (cur == NULL) return;
1047
1048 switch (cur->type) {
1049 case XML_ELEMENT_CONTENT_PCDATA:
1050 xmlBufferWriteChar(buf, "#PCDATA");
1051 break;
1052 case XML_ELEMENT_CONTENT_ELEMENT:
1053 if (cur->prefix != NULL) {
1054 xmlBufferWriteCHAR(buf, cur->prefix);
1055 xmlBufferWriteChar(buf, ":");
1056 }
1057 xmlBufferWriteCHAR(buf, cur->name);
1058 break;
1059 case XML_ELEMENT_CONTENT_SEQ:
1060 case XML_ELEMENT_CONTENT_OR:
1061 if ((cur != content) &&
1062 (cur->parent != NULL) &&
1063 ((cur->type != cur->parent->type) ||
1064 (cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
1065 xmlBufferWriteChar(buf, "(");
1066 cur = cur->c1;
1067 continue;
1068 default:
1069 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
1070 "Internal: ELEMENT cur corrupted invalid type\n",
1071 NULL);
1072 }
1073
1074 while (cur != content) {
1075 xmlElementContentPtr parent = cur->parent;
1076
1077 if (parent == NULL) return;
1078
1079 if (((cur->type == XML_ELEMENT_CONTENT_OR) ||
1080 (cur->type == XML_ELEMENT_CONTENT_SEQ)) &&
1081 ((cur->type != parent->type) ||
1082 (cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
1083 xmlBufferWriteChar(buf, ")");
1084 xmlDumpElementOccur(buf, cur);
1085
1086 if (cur == parent->c1) {
1087 if (parent->type == XML_ELEMENT_CONTENT_SEQ)
1088 xmlBufferWriteChar(buf, " , ");
1089 else if (parent->type == XML_ELEMENT_CONTENT_OR)
1090 xmlBufferWriteChar(buf, " | ");
1091
1092 cur = parent->c2;
1093 break;
1094 }
1095
1096 cur = parent;
1097 }
1098 } while (cur != content);
1099
1100 xmlBufferWriteChar(buf, ")");
1101 xmlDumpElementOccur(buf, content);
1102}
1103
1112void
1113xmlSprintfElementContent(char *buf ATTRIBUTE_UNUSED,
1114 xmlElementContentPtr content ATTRIBUTE_UNUSED,
1115 int englob ATTRIBUTE_UNUSED) {
1116}
1117#endif /* LIBXML_OUTPUT_ENABLED */
1118
1129void
1130xmlSnprintfElementContent(char *buf, int size, xmlElementContentPtr content, int englob) {
1131 int len;
1132
1133 if (content == NULL) return;
1134 len = strlen(buf);
1135 if (size - len < 50) {
1136 if ((size - len > 4) && (buf[len - 1] != '.'))
1137 strcat(buf, " ...");
1138 return;
1139 }
1140 if (englob) strcat(buf, "(");
1141 switch (content->type) {
1142 case XML_ELEMENT_CONTENT_PCDATA:
1143 strcat(buf, "#PCDATA");
1144 break;
1145 case XML_ELEMENT_CONTENT_ELEMENT: {
1146 int qnameLen = xmlStrlen(content->name);
1147
1148 if (content->prefix != NULL)
1149 qnameLen += xmlStrlen(content->prefix) + 1;
1150 if (size - len < qnameLen + 10) {
1151 strcat(buf, " ...");
1152 return;
1153 }
1154 if (content->prefix != NULL) {
1155 strcat(buf, (char *) content->prefix);
1156 strcat(buf, ":");
1157 }
1158 if (content->name != NULL)
1159 strcat(buf, (char *) content->name);
1160 break;
1161 }
1162 case XML_ELEMENT_CONTENT_SEQ:
1163 if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
1164 (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
1166 else
1168 len = strlen(buf);
1169 if (size - len < 50) {
1170 if ((size - len > 4) && (buf[len - 1] != '.'))
1171 strcat(buf, " ...");
1172 return;
1173 }
1174 strcat(buf, " , ");
1175 if (((content->c2->type == XML_ELEMENT_CONTENT_OR) ||
1176 (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE)) &&
1177 (content->c2->type != XML_ELEMENT_CONTENT_ELEMENT))
1179 else
1181 break;
1182 case XML_ELEMENT_CONTENT_OR:
1183 if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
1184 (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
1186 else
1188 len = strlen(buf);
1189 if (size - len < 50) {
1190 if ((size - len > 4) && (buf[len - 1] != '.'))
1191 strcat(buf, " ...");
1192 return;
1193 }
1194 strcat(buf, " | ");
1195 if (((content->c2->type == XML_ELEMENT_CONTENT_SEQ) ||
1196 (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE)) &&
1197 (content->c2->type != XML_ELEMENT_CONTENT_ELEMENT))
1199 else
1201 break;
1202 }
1203 if (size - strlen(buf) <= 2) return;
1204 if (englob)
1205 strcat(buf, ")");
1206 switch (content->ocur) {
1207 case XML_ELEMENT_CONTENT_ONCE:
1208 break;
1209 case XML_ELEMENT_CONTENT_OPT:
1210 strcat(buf, "?");
1211 break;
1212 case XML_ELEMENT_CONTENT_MULT:
1213 strcat(buf, "*");
1214 break;
1215 case XML_ELEMENT_CONTENT_PLUS:
1216 strcat(buf, "+");
1217 break;
1218 }
1219}
1220
1221/****************************************************************
1222 * *
1223 * Registration of DTD declarations *
1224 * *
1225 ****************************************************************/
1226
1233static void
1234xmlFreeElement(xmlElementPtr elem) {
1235 if (elem == NULL) return;
1236 xmlUnlinkNode((xmlNodePtr) elem);
1237 xmlFreeDocElementContent(elem->doc, elem->content);
1238 if (elem->name != NULL)
1239 xmlFree((xmlChar *) elem->name);
1240 if (elem->prefix != NULL)
1241 xmlFree((xmlChar *) elem->prefix);
1242#ifdef LIBXML_REGEXP_ENABLED
1243 if (elem->contModel != NULL)
1244 xmlRegFreeRegexp(elem->contModel);
1245#endif
1246 xmlFree(elem);
1247}
1248
1249
1262xmlElementPtr
1264 xmlDtdPtr dtd, const xmlChar *name,
1265 xmlElementTypeVal type,
1266 xmlElementContentPtr content) {
1267 xmlElementPtr ret;
1269 xmlAttributePtr oldAttributes = NULL;
1270 xmlChar *ns, *uqname;
1271
1272 if (dtd == NULL) {
1273 return(NULL);
1274 }
1275 if (name == NULL) {
1276 return(NULL);
1277 }
1278
1279 switch (type) {
1280 case XML_ELEMENT_TYPE_EMPTY:
1281 if (content != NULL) {
1282 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
1283 "xmlAddElementDecl: content != NULL for EMPTY\n",
1284 NULL);
1285 return(NULL);
1286 }
1287 break;
1288 case XML_ELEMENT_TYPE_ANY:
1289 if (content != NULL) {
1290 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
1291 "xmlAddElementDecl: content != NULL for ANY\n",
1292 NULL);
1293 return(NULL);
1294 }
1295 break;
1296 case XML_ELEMENT_TYPE_MIXED:
1297 if (content == NULL) {
1298 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
1299 "xmlAddElementDecl: content == NULL for MIXED\n",
1300 NULL);
1301 return(NULL);
1302 }
1303 break;
1304 case XML_ELEMENT_TYPE_ELEMENT:
1305 if (content == NULL) {
1306 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
1307 "xmlAddElementDecl: content == NULL for ELEMENT\n",
1308 NULL);
1309 return(NULL);
1310 }
1311 break;
1312 default:
1313 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
1314 "Internal: ELEMENT decl corrupted invalid type\n",
1315 NULL);
1316 return(NULL);
1317 }
1318
1319 /*
1320 * check if name is a QName
1321 */
1322 uqname = xmlSplitQName2(name, &ns);
1323 if (uqname != NULL)
1324 name = uqname;
1325
1326 /*
1327 * Create the Element table if needed.
1328 */
1329 table = (xmlElementTablePtr) dtd->elements;
1330 if (table == NULL) {
1331 xmlDictPtr dict = NULL;
1332
1333 if (dtd->doc != NULL)
1334 dict = dtd->doc->dict;
1335 table = xmlHashCreateDict(0, dict);
1336 dtd->elements = (void *) table;
1337 }
1338 if (table == NULL) {
1339 xmlVErrMemory(ctxt,
1340 "xmlAddElementDecl: Table creation failed!\n");
1341 if (uqname != NULL)
1342 xmlFree(uqname);
1343 if (ns != NULL)
1344 xmlFree(ns);
1345 return(NULL);
1346 }
1347
1348 /*
1349 * lookup old attributes inserted on an undefined element in the
1350 * internal subset.
1351 */
1352 if ((dtd->doc != NULL) && (dtd->doc->intSubset != NULL)) {
1353 ret = xmlHashLookup2(dtd->doc->intSubset->elements, name, ns);
1354 if ((ret != NULL) && (ret->etype == XML_ELEMENT_TYPE_UNDEFINED)) {
1355 oldAttributes = ret->attributes;
1356 ret->attributes = NULL;
1357 xmlHashRemoveEntry2(dtd->doc->intSubset->elements, name, ns, NULL);
1359 }
1360 }
1361
1362 /*
1363 * The element may already be present if one of its attribute
1364 * was registered first
1365 */
1367 if (ret != NULL) {
1368 if (ret->etype != XML_ELEMENT_TYPE_UNDEFINED) {
1369#ifdef LIBXML_VALID_ENABLED
1370 /*
1371 * The element is already defined in this DTD.
1372 */
1373 xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ELEM_REDEFINED,
1374 "Redefinition of element %s\n",
1375 name, NULL, NULL);
1376#endif /* LIBXML_VALID_ENABLED */
1377 if (uqname != NULL)
1378 xmlFree(uqname);
1379 if (ns != NULL)
1380 xmlFree(ns);
1381 return(NULL);
1382 }
1383 if (ns != NULL) {
1384 xmlFree(ns);
1385 ns = NULL;
1386 }
1387 } else {
1388 ret = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
1389 if (ret == NULL) {
1390 xmlVErrMemory(ctxt, "malloc failed");
1391 if (uqname != NULL)
1392 xmlFree(uqname);
1393 if (ns != NULL)
1394 xmlFree(ns);
1395 return(NULL);
1396 }
1397 memset(ret, 0, sizeof(xmlElement));
1398 ret->type = XML_ELEMENT_DECL;
1399
1400 /*
1401 * fill the structure.
1402 */
1403 ret->name = xmlStrdup(name);
1404 if (ret->name == NULL) {
1405 xmlVErrMemory(ctxt, "malloc failed");
1406 if (uqname != NULL)
1407 xmlFree(uqname);
1408 if (ns != NULL)
1409 xmlFree(ns);
1410 xmlFree(ret);
1411 return(NULL);
1412 }
1413 ret->prefix = ns;
1414
1415 /*
1416 * Validity Check:
1417 * Insertion must not fail
1418 */
1419 if (xmlHashAddEntry2(table, name, ns, ret)) {
1420#ifdef LIBXML_VALID_ENABLED
1421 /*
1422 * The element is already defined in this DTD.
1423 */
1424 xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ELEM_REDEFINED,
1425 "Redefinition of element %s\n",
1426 name, NULL, NULL);
1427#endif /* LIBXML_VALID_ENABLED */
1429 if (uqname != NULL)
1430 xmlFree(uqname);
1431 return(NULL);
1432 }
1433 /*
1434 * For new element, may have attributes from earlier
1435 * definition in internal subset
1436 */
1437 ret->attributes = oldAttributes;
1438 }
1439
1440 /*
1441 * Finish to fill the structure.
1442 */
1443 ret->etype = type;
1444 /*
1445 * Avoid a stupid copy when called by the parser
1446 * and flag it by setting a special parent value
1447 * so the parser doesn't unallocate it.
1448 */
1449 if ((ctxt != NULL) && (ctxt->flags & XML_VCTXT_USE_PCTXT)) {
1450 ret->content = content;
1451 if (content != NULL)
1452 content->parent = (xmlElementContentPtr) 1;
1453 } else {
1454 ret->content = xmlCopyDocElementContent(dtd->doc, content);
1455 }
1456
1457 /*
1458 * Link it to the DTD
1459 */
1460 ret->parent = dtd;
1461 ret->doc = dtd->doc;
1462 if (dtd->last == NULL) {
1463 dtd->children = dtd->last = (xmlNodePtr) ret;
1464 } else {
1465 dtd->last->next = (xmlNodePtr) ret;
1466 ret->prev = dtd->last;
1467 dtd->last = (xmlNodePtr) ret;
1468 }
1469 if (uqname != NULL)
1470 xmlFree(uqname);
1471 return(ret);
1472}
1473
1474static void
1476 xmlFreeElement((xmlElementPtr) elem);
1477}
1478
1485void
1488}
1489
1490#ifdef LIBXML_TREE_ENABLED
1499static void *
1500xmlCopyElement(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
1501 xmlElementPtr elem = (xmlElementPtr) payload;
1502 xmlElementPtr cur;
1503
1504 cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
1505 if (cur == NULL) {
1506 xmlVErrMemory(NULL, "malloc failed");
1507 return(NULL);
1508 }
1509 memset(cur, 0, sizeof(xmlElement));
1510 cur->type = XML_ELEMENT_DECL;
1511 cur->etype = elem->etype;
1512 if (elem->name != NULL)
1513 cur->name = xmlStrdup(elem->name);
1514 else
1515 cur->name = NULL;
1516 if (elem->prefix != NULL)
1517 cur->prefix = xmlStrdup(elem->prefix);
1518 else
1519 cur->prefix = NULL;
1520 cur->content = xmlCopyElementContent(elem->content);
1521 /* TODO : rebuild the attribute list on the copy */
1522 cur->attributes = NULL;
1523 return(cur);
1524}
1525
1535xmlCopyElementTable(xmlElementTablePtr table) {
1536 return((xmlElementTablePtr) xmlHashCopy(table, xmlCopyElement));
1537}
1538#endif /* LIBXML_TREE_ENABLED */
1539
1540#ifdef LIBXML_OUTPUT_ENABLED
1549void
1550xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) {
1551 if ((buf == NULL) || (elem == NULL))
1552 return;
1553 switch (elem->etype) {
1554 case XML_ELEMENT_TYPE_EMPTY:
1555 xmlBufferWriteChar(buf, "<!ELEMENT ");
1556 if (elem->prefix != NULL) {
1557 xmlBufferWriteCHAR(buf, elem->prefix);
1558 xmlBufferWriteChar(buf, ":");
1559 }
1560 xmlBufferWriteCHAR(buf, elem->name);
1561 xmlBufferWriteChar(buf, " EMPTY>\n");
1562 break;
1563 case XML_ELEMENT_TYPE_ANY:
1564 xmlBufferWriteChar(buf, "<!ELEMENT ");
1565 if (elem->prefix != NULL) {
1566 xmlBufferWriteCHAR(buf, elem->prefix);
1567 xmlBufferWriteChar(buf, ":");
1568 }
1569 xmlBufferWriteCHAR(buf, elem->name);
1570 xmlBufferWriteChar(buf, " ANY>\n");
1571 break;
1572 case XML_ELEMENT_TYPE_MIXED:
1573 xmlBufferWriteChar(buf, "<!ELEMENT ");
1574 if (elem->prefix != NULL) {
1575 xmlBufferWriteCHAR(buf, elem->prefix);
1576 xmlBufferWriteChar(buf, ":");
1577 }
1578 xmlBufferWriteCHAR(buf, elem->name);
1579 xmlBufferWriteChar(buf, " ");
1580 xmlDumpElementContent(buf, elem->content);
1581 xmlBufferWriteChar(buf, ">\n");
1582 break;
1583 case XML_ELEMENT_TYPE_ELEMENT:
1584 xmlBufferWriteChar(buf, "<!ELEMENT ");
1585 if (elem->prefix != NULL) {
1586 xmlBufferWriteCHAR(buf, elem->prefix);
1587 xmlBufferWriteChar(buf, ":");
1588 }
1589 xmlBufferWriteCHAR(buf, elem->name);
1590 xmlBufferWriteChar(buf, " ");
1591 xmlDumpElementContent(buf, elem->content);
1592 xmlBufferWriteChar(buf, ">\n");
1593 break;
1594 default:
1595 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
1596 "Internal: ELEMENT struct corrupted invalid type\n",
1597 NULL);
1598 }
1599}
1600
1609static void
1610xmlDumpElementDeclScan(void *elem, void *buf,
1611 const xmlChar *name ATTRIBUTE_UNUSED) {
1612 xmlDumpElementDecl((xmlBufferPtr) buf, (xmlElementPtr) elem);
1613}
1614
1622void
1623xmlDumpElementTable(xmlBufferPtr buf, xmlElementTablePtr table) {
1624 if ((buf == NULL) || (table == NULL))
1625 return;
1626 xmlHashScan(table, xmlDumpElementDeclScan, buf);
1627}
1628#endif /* LIBXML_OUTPUT_ENABLED */
1629
1639xmlEnumerationPtr
1641 xmlEnumerationPtr ret;
1642
1643 ret = (xmlEnumerationPtr) xmlMalloc(sizeof(xmlEnumeration));
1644 if (ret == NULL) {
1645 xmlVErrMemory(NULL, "malloc failed");
1646 return(NULL);
1647 }
1648 memset(ret, 0, sizeof(xmlEnumeration));
1649
1650 if (name != NULL)
1651 ret->name = xmlStrdup(name);
1652 return(ret);
1653}
1654
1661void
1662xmlFreeEnumeration(xmlEnumerationPtr cur) {
1663 if (cur == NULL) return;
1664
1665 if (cur->next != NULL) xmlFreeEnumeration(cur->next);
1666
1667 if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
1668 xmlFree(cur);
1669}
1670
1671#ifdef LIBXML_TREE_ENABLED
1681xmlEnumerationPtr
1682xmlCopyEnumeration(xmlEnumerationPtr cur) {
1683 xmlEnumerationPtr ret;
1684
1685 if (cur == NULL) return(NULL);
1686 ret = xmlCreateEnumeration((xmlChar *) cur->name);
1687 if (ret == NULL) return(NULL);
1688
1689 if (cur->next != NULL) ret->next = xmlCopyEnumeration(cur->next);
1690 else ret->next = NULL;
1691
1692 return(ret);
1693}
1694#endif /* LIBXML_TREE_ENABLED */
1695
1696#ifdef LIBXML_OUTPUT_ENABLED
1704static void
1705xmlDumpEnumeration(xmlBufferPtr buf, xmlEnumerationPtr cur) {
1706 if ((buf == NULL) || (cur == NULL))
1707 return;
1708
1709 xmlBufferWriteCHAR(buf, cur->name);
1710 if (cur->next == NULL)
1711 xmlBufferWriteChar(buf, ")");
1712 else {
1713 xmlBufferWriteChar(buf, " | ");
1714 xmlDumpEnumeration(buf, cur->next);
1715 }
1716}
1717#endif /* LIBXML_OUTPUT_ENABLED */
1718
1719#ifdef LIBXML_VALID_ENABLED
1731static int
1732xmlScanIDAttributeDecl(xmlValidCtxtPtr ctxt, xmlElementPtr elem, int err) {
1733 xmlAttributePtr cur;
1734 int ret = 0;
1735
1736 if (elem == NULL) return(0);
1737 cur = elem->attributes;
1738 while (cur != NULL) {
1739 if (cur->atype == XML_ATTRIBUTE_ID) {
1740 ret ++;
1741 if ((ret > 1) && (err))
1742 xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_MULTIPLE_ID,
1743 "Element %s has too many ID attributes defined : %s\n",
1744 elem->name, cur->name, NULL);
1745 }
1746 cur = cur->nexth;
1747 }
1748 return(ret);
1749}
1750#endif /* LIBXML_VALID_ENABLED */
1751
1758static void
1759xmlFreeAttribute(xmlAttributePtr attr) {
1760 xmlDictPtr dict;
1761
1762 if (attr == NULL) return;
1763 if (attr->doc != NULL)
1764 dict = attr->doc->dict;
1765 else
1766 dict = NULL;
1767 xmlUnlinkNode((xmlNodePtr) attr);
1768 if (attr->tree != NULL)
1769 xmlFreeEnumeration(attr->tree);
1770 if (dict) {
1771 if ((attr->elem != NULL) && (!xmlDictOwns(dict, attr->elem)))
1772 xmlFree((xmlChar *) attr->elem);
1773 if ((attr->name != NULL) && (!xmlDictOwns(dict, attr->name)))
1774 xmlFree((xmlChar *) attr->name);
1775 if ((attr->prefix != NULL) && (!xmlDictOwns(dict, attr->prefix)))
1776 xmlFree((xmlChar *) attr->prefix);
1777 if ((attr->defaultValue != NULL) &&
1778 (!xmlDictOwns(dict, attr->defaultValue)))
1779 xmlFree((xmlChar *) attr->defaultValue);
1780 } else {
1781 if (attr->elem != NULL)
1782 xmlFree((xmlChar *) attr->elem);
1783 if (attr->name != NULL)
1784 xmlFree((xmlChar *) attr->name);
1785 if (attr->defaultValue != NULL)
1786 xmlFree((xmlChar *) attr->defaultValue);
1787 if (attr->prefix != NULL)
1788 xmlFree((xmlChar *) attr->prefix);
1789 }
1790 xmlFree(attr);
1791}
1792
1793
1811xmlAttributePtr
1813 xmlDtdPtr dtd, const xmlChar *elem,
1814 const xmlChar *name, const xmlChar *ns,
1815 xmlAttributeType type, xmlAttributeDefault def,
1816 const xmlChar *defaultValue, xmlEnumerationPtr tree) {
1817 xmlAttributePtr ret;
1819 xmlElementPtr elemDef;
1820 xmlDictPtr dict = NULL;
1821
1822 if (dtd == NULL) {
1824 return(NULL);
1825 }
1826 if (name == NULL) {
1828 return(NULL);
1829 }
1830 if (elem == NULL) {
1832 return(NULL);
1833 }
1834 if (dtd->doc != NULL)
1835 dict = dtd->doc->dict;
1836
1837#ifdef LIBXML_VALID_ENABLED
1838 /*
1839 * Check the type and possibly the default value.
1840 */
1841 switch (type) {
1842 case XML_ATTRIBUTE_CDATA:
1843 break;
1844 case XML_ATTRIBUTE_ID:
1845 break;
1846 case XML_ATTRIBUTE_IDREF:
1847 break;
1848 case XML_ATTRIBUTE_IDREFS:
1849 break;
1850 case XML_ATTRIBUTE_ENTITY:
1851 break;
1852 case XML_ATTRIBUTE_ENTITIES:
1853 break;
1854 case XML_ATTRIBUTE_NMTOKEN:
1855 break;
1856 case XML_ATTRIBUTE_NMTOKENS:
1857 break;
1858 case XML_ATTRIBUTE_ENUMERATION:
1859 break;
1860 case XML_ATTRIBUTE_NOTATION:
1861 break;
1862 default:
1863 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
1864 "Internal: ATTRIBUTE struct corrupted invalid type\n",
1865 NULL);
1867 return(NULL);
1868 }
1869 if ((defaultValue != NULL) &&
1870 (!xmlValidateAttributeValueInternal(dtd->doc, type, defaultValue))) {
1871 xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ATTRIBUTE_DEFAULT,
1872 "Attribute %s of %s: invalid default value\n",
1873 elem, name, defaultValue);
1874 defaultValue = NULL;
1875 if (ctxt != NULL)
1876 ctxt->valid = 0;
1877 }
1878#endif /* LIBXML_VALID_ENABLED */
1879
1880 /*
1881 * Check first that an attribute defined in the external subset wasn't
1882 * already defined in the internal subset
1883 */
1884 if ((dtd->doc != NULL) && (dtd->doc->extSubset == dtd) &&
1885 (dtd->doc->intSubset != NULL) &&
1886 (dtd->doc->intSubset->attributes != NULL)) {
1887 ret = xmlHashLookup3(dtd->doc->intSubset->attributes, name, ns, elem);
1888 if (ret != NULL) {
1890 return(NULL);
1891 }
1892 }
1893
1894 /*
1895 * Create the Attribute table if needed.
1896 */
1897 table = (xmlAttributeTablePtr) dtd->attributes;
1898 if (table == NULL) {
1899 table = xmlHashCreateDict(0, dict);
1900 dtd->attributes = (void *) table;
1901 }
1902 if (table == NULL) {
1903 xmlVErrMemory(ctxt,
1904 "xmlAddAttributeDecl: Table creation failed!\n");
1906 return(NULL);
1907 }
1908
1909
1910 ret = (xmlAttributePtr) xmlMalloc(sizeof(xmlAttribute));
1911 if (ret == NULL) {
1912 xmlVErrMemory(ctxt, "malloc failed");
1914 return(NULL);
1915 }
1916 memset(ret, 0, sizeof(xmlAttribute));
1917 ret->type = XML_ATTRIBUTE_DECL;
1918
1919 /*
1920 * fill the structure.
1921 */
1922 ret->atype = type;
1923 /*
1924 * doc must be set before possible error causes call
1925 * to xmlFreeAttribute (because it's used to check on
1926 * dict use)
1927 */
1928 ret->doc = dtd->doc;
1929 if (dict) {
1930 ret->name = xmlDictLookup(dict, name, -1);
1931 ret->prefix = xmlDictLookup(dict, ns, -1);
1932 ret->elem = xmlDictLookup(dict, elem, -1);
1933 } else {
1934 ret->name = xmlStrdup(name);
1935 ret->prefix = xmlStrdup(ns);
1936 ret->elem = xmlStrdup(elem);
1937 }
1938 ret->def = def;
1939 ret->tree = tree;
1940 if (defaultValue != NULL) {
1941 if (dict)
1942 ret->defaultValue = xmlDictLookup(dict, defaultValue, -1);
1943 else
1944 ret->defaultValue = xmlStrdup(defaultValue);
1945 }
1946
1947 /*
1948 * Validity Check:
1949 * Search the DTD for previous declarations of the ATTLIST
1950 */
1951 if (xmlHashAddEntry3(table, ret->name, ret->prefix, ret->elem, ret) < 0) {
1952#ifdef LIBXML_VALID_ENABLED
1953 /*
1954 * The attribute is already defined in this DTD.
1955 */
1956 xmlErrValidWarning(ctxt, (xmlNodePtr) dtd, XML_DTD_ATTRIBUTE_REDEFINED,
1957 "Attribute %s of element %s: already defined\n",
1958 name, elem, NULL);
1959#endif /* LIBXML_VALID_ENABLED */
1961 return(NULL);
1962 }
1963
1964 /*
1965 * Validity Check:
1966 * Multiple ID per element
1967 */
1968 elemDef = xmlGetDtdElementDesc2(ctxt, dtd, elem, 1);
1969 if (elemDef != NULL) {
1970
1971#ifdef LIBXML_VALID_ENABLED
1972 if ((type == XML_ATTRIBUTE_ID) &&
1973 (xmlScanIDAttributeDecl(NULL, elemDef, 1) != 0)) {
1974 xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_MULTIPLE_ID,
1975 "Element %s has too may ID attributes defined : %s\n",
1976 elem, name, NULL);
1977 if (ctxt != NULL)
1978 ctxt->valid = 0;
1979 }
1980#endif /* LIBXML_VALID_ENABLED */
1981
1982 /*
1983 * Insert namespace default def first they need to be
1984 * processed first.
1985 */
1986 if ((xmlStrEqual(ret->name, BAD_CAST "xmlns")) ||
1987 ((ret->prefix != NULL &&
1988 (xmlStrEqual(ret->prefix, BAD_CAST "xmlns"))))) {
1989 ret->nexth = elemDef->attributes;
1990 elemDef->attributes = ret;
1991 } else {
1992 xmlAttributePtr tmp = elemDef->attributes;
1993
1994 while ((tmp != NULL) &&
1995 ((xmlStrEqual(tmp->name, BAD_CAST "xmlns")) ||
1996 ((ret->prefix != NULL &&
1997 (xmlStrEqual(ret->prefix, BAD_CAST "xmlns")))))) {
1998 if (tmp->nexth == NULL)
1999 break;
2000 tmp = tmp->nexth;
2001 }
2002 if (tmp != NULL) {
2003 ret->nexth = tmp->nexth;
2004 tmp->nexth = ret;
2005 } else {
2006 ret->nexth = elemDef->attributes;
2007 elemDef->attributes = ret;
2008 }
2009 }
2010 }
2011
2012 /*
2013 * Link it to the DTD
2014 */
2015 ret->parent = dtd;
2016 if (dtd->last == NULL) {
2017 dtd->children = dtd->last = (xmlNodePtr) ret;
2018 } else {
2019 dtd->last->next = (xmlNodePtr) ret;
2020 ret->prev = dtd->last;
2021 dtd->last = (xmlNodePtr) ret;
2022 }
2023 return(ret);
2024}
2025
2026static void
2028 xmlFreeAttribute((xmlAttributePtr) attr);
2029}
2030
2037void
2040}
2041
2042#ifdef LIBXML_TREE_ENABLED
2051static void *
2052xmlCopyAttribute(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
2053 xmlAttributePtr attr = (xmlAttributePtr) payload;
2054 xmlAttributePtr cur;
2055
2056 cur = (xmlAttributePtr) xmlMalloc(sizeof(xmlAttribute));
2057 if (cur == NULL) {
2058 xmlVErrMemory(NULL, "malloc failed");
2059 return(NULL);
2060 }
2061 memset(cur, 0, sizeof(xmlAttribute));
2062 cur->type = XML_ATTRIBUTE_DECL;
2063 cur->atype = attr->atype;
2064 cur->def = attr->def;
2065 cur->tree = xmlCopyEnumeration(attr->tree);
2066 if (attr->elem != NULL)
2067 cur->elem = xmlStrdup(attr->elem);
2068 if (attr->name != NULL)
2069 cur->name = xmlStrdup(attr->name);
2070 if (attr->prefix != NULL)
2071 cur->prefix = xmlStrdup(attr->prefix);
2072 if (attr->defaultValue != NULL)
2073 cur->defaultValue = xmlStrdup(attr->defaultValue);
2074 return(cur);
2075}
2076
2086xmlCopyAttributeTable(xmlAttributeTablePtr table) {
2087 return((xmlAttributeTablePtr) xmlHashCopy(table, xmlCopyAttribute));
2088}
2089#endif /* LIBXML_TREE_ENABLED */
2090
2091#ifdef LIBXML_OUTPUT_ENABLED
2100void
2101xmlDumpAttributeDecl(xmlBufferPtr buf, xmlAttributePtr attr) {
2102 if ((buf == NULL) || (attr == NULL))
2103 return;
2104 xmlBufferWriteChar(buf, "<!ATTLIST ");
2105 xmlBufferWriteCHAR(buf, attr->elem);
2106 xmlBufferWriteChar(buf, " ");
2107 if (attr->prefix != NULL) {
2108 xmlBufferWriteCHAR(buf, attr->prefix);
2109 xmlBufferWriteChar(buf, ":");
2110 }
2111 xmlBufferWriteCHAR(buf, attr->name);
2112 switch (attr->atype) {
2113 case XML_ATTRIBUTE_CDATA:
2114 xmlBufferWriteChar(buf, " CDATA");
2115 break;
2116 case XML_ATTRIBUTE_ID:
2117 xmlBufferWriteChar(buf, " ID");
2118 break;
2119 case XML_ATTRIBUTE_IDREF:
2120 xmlBufferWriteChar(buf, " IDREF");
2121 break;
2122 case XML_ATTRIBUTE_IDREFS:
2123 xmlBufferWriteChar(buf, " IDREFS");
2124 break;
2125 case XML_ATTRIBUTE_ENTITY:
2126 xmlBufferWriteChar(buf, " ENTITY");
2127 break;
2128 case XML_ATTRIBUTE_ENTITIES:
2129 xmlBufferWriteChar(buf, " ENTITIES");
2130 break;
2131 case XML_ATTRIBUTE_NMTOKEN:
2132 xmlBufferWriteChar(buf, " NMTOKEN");
2133 break;
2134 case XML_ATTRIBUTE_NMTOKENS:
2135 xmlBufferWriteChar(buf, " NMTOKENS");
2136 break;
2137 case XML_ATTRIBUTE_ENUMERATION:
2138 xmlBufferWriteChar(buf, " (");
2139 xmlDumpEnumeration(buf, attr->tree);
2140 break;
2141 case XML_ATTRIBUTE_NOTATION:
2142 xmlBufferWriteChar(buf, " NOTATION (");
2143 xmlDumpEnumeration(buf, attr->tree);
2144 break;
2145 default:
2146 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
2147 "Internal: ATTRIBUTE struct corrupted invalid type\n",
2148 NULL);
2149 }
2150 switch (attr->def) {
2151 case XML_ATTRIBUTE_NONE:
2152 break;
2153 case XML_ATTRIBUTE_REQUIRED:
2154 xmlBufferWriteChar(buf, " #REQUIRED");
2155 break;
2156 case XML_ATTRIBUTE_IMPLIED:
2157 xmlBufferWriteChar(buf, " #IMPLIED");
2158 break;
2159 case XML_ATTRIBUTE_FIXED:
2160 xmlBufferWriteChar(buf, " #FIXED");
2161 break;
2162 default:
2163 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
2164 "Internal: ATTRIBUTE struct corrupted invalid def\n",
2165 NULL);
2166 }
2167 if (attr->defaultValue != NULL) {
2168 xmlBufferWriteChar(buf, " ");
2169 xmlBufferWriteQuotedString(buf, attr->defaultValue);
2170 }
2171 xmlBufferWriteChar(buf, ">\n");
2172}
2173
2181static void
2182xmlDumpAttributeDeclScan(void *attr, void *buf,
2183 const xmlChar *name ATTRIBUTE_UNUSED) {
2184 xmlDumpAttributeDecl((xmlBufferPtr) buf, (xmlAttributePtr) attr);
2185}
2186
2194void
2195xmlDumpAttributeTable(xmlBufferPtr buf, xmlAttributeTablePtr table) {
2196 if ((buf == NULL) || (table == NULL))
2197 return;
2198 xmlHashScan(table, xmlDumpAttributeDeclScan, buf);
2199}
2200#endif /* LIBXML_OUTPUT_ENABLED */
2201
2202/************************************************************************
2203 * *
2204 * NOTATIONs *
2205 * *
2206 ************************************************************************/
2213static void
2214xmlFreeNotation(xmlNotationPtr nota) {
2215 if (nota == NULL) return;
2216 if (nota->name != NULL)
2217 xmlFree((xmlChar *) nota->name);
2218 if (nota->PublicID != NULL)
2219 xmlFree((xmlChar *) nota->PublicID);
2220 if (nota->SystemID != NULL)
2221 xmlFree((xmlChar *) nota->SystemID);
2222 xmlFree(nota);
2223}
2224
2225
2238xmlNotationPtr
2240 const xmlChar *name,
2241 const xmlChar *PublicID, const xmlChar *SystemID) {
2242 xmlNotationPtr ret;
2244
2245 if (dtd == NULL) {
2246 return(NULL);
2247 }
2248 if (name == NULL) {
2249 return(NULL);
2250 }
2251 if ((PublicID == NULL) && (SystemID == NULL)) {
2252 return(NULL);
2253 }
2254
2255 /*
2256 * Create the Notation table if needed.
2257 */
2258 table = (xmlNotationTablePtr) dtd->notations;
2259 if (table == NULL) {
2260 xmlDictPtr dict = NULL;
2261 if (dtd->doc != NULL)
2262 dict = dtd->doc->dict;
2263
2264 dtd->notations = table = xmlHashCreateDict(0, dict);
2265 }
2266 if (table == NULL) {
2267 xmlVErrMemory(ctxt,
2268 "xmlAddNotationDecl: Table creation failed!\n");
2269 return(NULL);
2270 }
2271
2272 ret = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation));
2273 if (ret == NULL) {
2274 xmlVErrMemory(ctxt, "malloc failed");
2275 return(NULL);
2276 }
2277 memset(ret, 0, sizeof(xmlNotation));
2278
2279 /*
2280 * fill the structure.
2281 */
2282 ret->name = xmlStrdup(name);
2283 if (SystemID != NULL)
2284 ret->SystemID = xmlStrdup(SystemID);
2285 if (PublicID != NULL)
2286 ret->PublicID = xmlStrdup(PublicID);
2287
2288 /*
2289 * Validity Check:
2290 * Check the DTD for previous declarations of the ATTLIST
2291 */
2292 if (xmlHashAddEntry(table, name, ret)) {
2293#ifdef LIBXML_VALID_ENABLED
2294 xmlErrValid(NULL, XML_DTD_NOTATION_REDEFINED,
2295 "xmlAddNotationDecl: %s already defined\n",
2296 (const char *) name);
2297#endif /* LIBXML_VALID_ENABLED */
2299 return(NULL);
2300 }
2301 return(ret);
2302}
2303
2304static void
2306 xmlFreeNotation((xmlNotationPtr) nota);
2307}
2308
2315void
2318}
2319
2320#ifdef LIBXML_TREE_ENABLED
2329static void *
2330xmlCopyNotation(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
2331 xmlNotationPtr nota = (xmlNotationPtr) payload;
2332 xmlNotationPtr cur;
2333
2334 cur = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation));
2335 if (cur == NULL) {
2336 xmlVErrMemory(NULL, "malloc failed");
2337 return(NULL);
2338 }
2339 if (nota->name != NULL)
2340 cur->name = xmlStrdup(nota->name);
2341 else
2342 cur->name = NULL;
2343 if (nota->PublicID != NULL)
2344 cur->PublicID = xmlStrdup(nota->PublicID);
2345 else
2346 cur->PublicID = NULL;
2347 if (nota->SystemID != NULL)
2348 cur->SystemID = xmlStrdup(nota->SystemID);
2349 else
2350 cur->SystemID = NULL;
2351 return(cur);
2352}
2353
2363xmlCopyNotationTable(xmlNotationTablePtr table) {
2364 return((xmlNotationTablePtr) xmlHashCopy(table, xmlCopyNotation));
2365}
2366#endif /* LIBXML_TREE_ENABLED */
2367
2368#ifdef LIBXML_OUTPUT_ENABLED
2376void
2377xmlDumpNotationDecl(xmlBufferPtr buf, xmlNotationPtr nota) {
2378 if ((buf == NULL) || (nota == NULL))
2379 return;
2380 xmlBufferWriteChar(buf, "<!NOTATION ");
2381 xmlBufferWriteCHAR(buf, nota->name);
2382 if (nota->PublicID != NULL) {
2383 xmlBufferWriteChar(buf, " PUBLIC ");
2384 xmlBufferWriteQuotedString(buf, nota->PublicID);
2385 if (nota->SystemID != NULL) {
2386 xmlBufferWriteChar(buf, " ");
2387 xmlBufferWriteQuotedString(buf, nota->SystemID);
2388 }
2389 } else {
2390 xmlBufferWriteChar(buf, " SYSTEM ");
2391 xmlBufferWriteQuotedString(buf, nota->SystemID);
2392 }
2393 xmlBufferWriteChar(buf, " >\n");
2394}
2395
2403static void
2404xmlDumpNotationDeclScan(void *nota, void *buf,
2405 const xmlChar *name ATTRIBUTE_UNUSED) {
2406 xmlDumpNotationDecl((xmlBufferPtr) buf, (xmlNotationPtr) nota);
2407}
2408
2416void
2417xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
2418 if ((buf == NULL) || (table == NULL))
2419 return;
2420 xmlHashScan(table, xmlDumpNotationDeclScan, buf);
2421}
2422#endif /* LIBXML_OUTPUT_ENABLED */
2423
2424/************************************************************************
2425 * *
2426 * IDs *
2427 * *
2428 ************************************************************************/
2436#define DICT_FREE(str) \
2437 if ((str) && ((!dict) || \
2438 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
2439 xmlFree((char *)(str));
2440
2447static void
2449 xmlChar *dst;
2450 const xmlChar *src;
2451
2452 if (str == NULL)
2453 return;
2454 src = str;
2455 dst = str;
2456
2457 while (*src == 0x20) src++;
2458 while (*src != 0) {
2459 if (*src == 0x20) {
2460 while (*src == 0x20) src++;
2461 if (*src != 0)
2462 *dst++ = 0x20;
2463 } else {
2464 *dst++ = *src++;
2465 }
2466 }
2467 *dst = 0;
2468}
2469
2470static int
2472 xmlParserCtxtPtr pctxt;
2473
2474 if (ctxt == NULL)
2475 return(0);
2476 if ((ctxt->flags & XML_VCTXT_USE_PCTXT) == 0)
2477 return(0);
2478 pctxt = ctxt->userData;
2479 return(pctxt->parseMode == XML_PARSE_READER);
2480}
2481
2488static void
2489xmlFreeID(xmlIDPtr id) {
2490 xmlDictPtr dict = NULL;
2491
2492 if (id == NULL) return;
2493
2494 if (id->doc != NULL)
2495 dict = id->doc->dict;
2496
2497 if (id->value != NULL)
2498 DICT_FREE(id->value)
2499 if (id->name != NULL)
2500 DICT_FREE(id->name)
2501 xmlFree(id);
2502}
2503
2504
2516xmlIDPtr
2517xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
2518 xmlAttrPtr attr) {
2519 xmlIDPtr ret;
2521
2522 if (doc == NULL) {
2523 return(NULL);
2524 }
2525 if ((value == NULL) || (value[0] == 0)) {
2526 return(NULL);
2527 }
2528 if (attr == NULL) {
2529 return(NULL);
2530 }
2531
2532 /*
2533 * Create the ID table if needed.
2534 */
2535 table = (xmlIDTablePtr) doc->ids;
2536 if (table == NULL) {
2537 doc->ids = table = xmlHashCreateDict(0, doc->dict);
2538 }
2539 if (table == NULL) {
2540 xmlVErrMemory(ctxt,
2541 "xmlAddID: Table creation failed!\n");
2542 return(NULL);
2543 }
2544
2545 ret = (xmlIDPtr) xmlMalloc(sizeof(xmlID));
2546 if (ret == NULL) {
2547 xmlVErrMemory(ctxt, "malloc failed");
2548 return(NULL);
2549 }
2550
2551 /*
2552 * fill the structure.
2553 */
2554 ret->value = xmlStrdup(value);
2555 ret->doc = doc;
2556 if (xmlIsStreaming(ctxt)) {
2557 /*
2558 * Operating in streaming mode, attr is gonna disappear
2559 */
2560 if (doc->dict != NULL)
2561 ret->name = xmlDictLookup(doc->dict, attr->name, -1);
2562 else
2563 ret->name = xmlStrdup(attr->name);
2564 ret->attr = NULL;
2565 } else {
2566 ret->attr = attr;
2567 ret->name = NULL;
2568 }
2569 ret->lineno = xmlGetLineNo(attr->parent);
2570
2571 if (xmlHashAddEntry(table, value, ret) < 0) {
2572#ifdef LIBXML_VALID_ENABLED
2573 /*
2574 * The id is already defined in this DTD.
2575 */
2576 if (ctxt != NULL) {
2577 xmlErrValidNode(ctxt, attr->parent, XML_DTD_ID_REDEFINED,
2578 "ID %s already defined\n", value, NULL, NULL);
2579 }
2580#endif /* LIBXML_VALID_ENABLED */
2581 xmlFreeID(ret);
2582 return(NULL);
2583 }
2584 if (attr != NULL)
2585 attr->atype = XML_ATTRIBUTE_ID;
2586 return(ret);
2587}
2588
2589static void
2591 xmlFreeID((xmlIDPtr) id);
2592}
2593
2600void
2603}
2604
2618int
2619xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
2620 if ((attr == NULL) || (attr->name == NULL)) return(0);
2621 if ((attr->ns != NULL) && (attr->ns->prefix != NULL) &&
2622 (!strcmp((char *) attr->name, "id")) &&
2623 (!strcmp((char *) attr->ns->prefix, "xml")))
2624 return(1);
2625 if (doc == NULL) return(0);
2626 if ((doc->intSubset == NULL) && (doc->extSubset == NULL) &&
2627 (doc->type != XML_HTML_DOCUMENT_NODE)) {
2628 return(0);
2629 } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
2630 if ((xmlStrEqual(BAD_CAST "id", attr->name)) ||
2631 ((xmlStrEqual(BAD_CAST "name", attr->name)) &&
2632 ((elem == NULL) || (xmlStrEqual(elem->name, BAD_CAST "a")))))
2633 return(1);
2634 return(0);
2635 } else if (elem == NULL) {
2636 return(0);
2637 } else {
2638 xmlAttributePtr attrDecl = NULL;
2639
2640 xmlChar felem[50], fattr[50];
2641 xmlChar *fullelemname, *fullattrname;
2642
2643 fullelemname = (elem->ns != NULL && elem->ns->prefix != NULL) ?
2644 xmlBuildQName(elem->name, elem->ns->prefix, felem, 50) :
2645 (xmlChar *)elem->name;
2646
2647 fullattrname = (attr->ns != NULL && attr->ns->prefix != NULL) ?
2648 xmlBuildQName(attr->name, attr->ns->prefix, fattr, 50) :
2649 (xmlChar *)attr->name;
2650
2651 if (fullelemname != NULL && fullattrname != NULL) {
2652 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullelemname,
2653 fullattrname);
2654 if ((attrDecl == NULL) && (doc->extSubset != NULL))
2655 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullelemname,
2656 fullattrname);
2657 }
2658
2659 if ((fullattrname != fattr) && (fullattrname != attr->name))
2660 xmlFree(fullattrname);
2661 if ((fullelemname != felem) && (fullelemname != elem->name))
2662 xmlFree(fullelemname);
2663
2664 if ((attrDecl != NULL) && (attrDecl->atype == XML_ATTRIBUTE_ID))
2665 return(1);
2666 }
2667 return(0);
2668}
2669
2679int
2680xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
2682 xmlIDPtr id;
2683 xmlChar *ID;
2684
2685 if (doc == NULL) return(-1);
2686 if (attr == NULL) return(-1);
2687
2688 table = (xmlIDTablePtr) doc->ids;
2689 if (table == NULL)
2690 return(-1);
2691
2692 ID = xmlNodeListGetString(doc, attr->children, 1);
2693 if (ID == NULL)
2694 return(-1);
2696
2697 id = xmlHashLookup(table, ID);
2698 if (id == NULL || id->attr != attr) {
2699 xmlFree(ID);
2700 return(-1);
2701 }
2702
2704 xmlFree(ID);
2705 attr->atype = 0;
2706 return(0);
2707}
2708
2718xmlAttrPtr
2719xmlGetID(xmlDocPtr doc, const xmlChar *ID) {
2721 xmlIDPtr id;
2722
2723 if (doc == NULL) {
2724 return(NULL);
2725 }
2726
2727 if (ID == NULL) {
2728 return(NULL);
2729 }
2730
2731 table = (xmlIDTablePtr) doc->ids;
2732 if (table == NULL)
2733 return(NULL);
2734
2735 id = xmlHashLookup(table, ID);
2736 if (id == NULL)
2737 return(NULL);
2738 if (id->attr == NULL) {
2739 /*
2740 * We are operating on a stream, return a well known reference
2741 * since the attribute node doesn't exist anymore
2742 */
2743 return((xmlAttrPtr) doc);
2744 }
2745 return(id->attr);
2746}
2747
2748/************************************************************************
2749 * *
2750 * Refs *
2751 * *
2752 ************************************************************************/
2753typedef struct xmlRemoveMemo_t
2754{
2756 xmlAttrPtr ap;
2758
2760
2761typedef struct xmlValidateMemo_t
2762{
2766
2768
2775static void
2777 xmlRefPtr ref = (xmlRefPtr)xmlLinkGetData(lk);
2778 if (ref == NULL) return;
2779 if (ref->value != NULL)
2780 xmlFree((xmlChar *)ref->value);
2781 if (ref->name != NULL)
2782 xmlFree((xmlChar *)ref->name);
2783 xmlFree(ref);
2784}
2785
2792static void
2794 xmlListPtr list_ref = (xmlListPtr) payload;
2795 if (list_ref == NULL) return;
2796 xmlListDelete(list_ref);
2797}
2798
2806static int
2807xmlWalkRemoveRef(const void *data, void *user)
2808{
2809 xmlAttrPtr attr0 = ((xmlRefPtr)data)->attr;
2810 xmlAttrPtr attr1 = ((xmlRemoveMemoPtr)user)->ap;
2811 xmlListPtr ref_list = ((xmlRemoveMemoPtr)user)->l;
2812
2813 if (attr0 == attr1) { /* Matched: remove and terminate walk */
2814 xmlListRemoveFirst(ref_list, (void *)data);
2815 return 0;
2816 }
2817 return 1;
2818}
2819
2827static int
2829 const void *data1 ATTRIBUTE_UNUSED)
2830{
2831 return (0);
2832}
2833
2847xmlRefPtr
2848xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
2849 xmlAttrPtr attr) {
2850 xmlRefPtr ret;
2852 xmlListPtr ref_list;
2853
2854 if (doc == NULL) {
2855 return(NULL);
2856 }
2857 if (value == NULL) {
2858 return(NULL);
2859 }
2860 if (attr == NULL) {
2861 return(NULL);
2862 }
2863
2864 /*
2865 * Create the Ref table if needed.
2866 */
2867 table = (xmlRefTablePtr) doc->refs;
2868 if (table == NULL) {
2869 doc->refs = table = xmlHashCreateDict(0, doc->dict);
2870 }
2871 if (table == NULL) {
2872 xmlVErrMemory(ctxt,
2873 "xmlAddRef: Table creation failed!\n");
2874 return(NULL);
2875 }
2876
2877 ret = (xmlRefPtr) xmlMalloc(sizeof(xmlRef));
2878 if (ret == NULL) {
2879 xmlVErrMemory(ctxt, "malloc failed");
2880 return(NULL);
2881 }
2882
2883 /*
2884 * fill the structure.
2885 */
2886 ret->value = xmlStrdup(value);
2887 if (xmlIsStreaming(ctxt)) {
2888 /*
2889 * Operating in streaming mode, attr is gonna disappear
2890 */
2891 ret->name = xmlStrdup(attr->name);
2892 ret->attr = NULL;
2893 } else {
2894 ret->name = NULL;
2895 ret->attr = attr;
2896 }
2897 ret->lineno = xmlGetLineNo(attr->parent);
2898
2899 /* To add a reference :-
2900 * References are maintained as a list of references,
2901 * Lookup the entry, if no entry create new nodelist
2902 * Add the owning node to the NodeList
2903 * Return the ref
2904 */
2905
2906 if (NULL == (ref_list = xmlHashLookup(table, value))) {
2907 if (NULL == (ref_list = xmlListCreate(xmlFreeRef, xmlDummyCompare))) {
2908 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
2909 "xmlAddRef: Reference list creation failed!\n",
2910 NULL);
2911 goto failed;
2912 }
2913 if (xmlHashAddEntry(table, value, ref_list) < 0) {
2914 xmlListDelete(ref_list);
2915 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
2916 "xmlAddRef: Reference list insertion failed!\n",
2917 NULL);
2918 goto failed;
2919 }
2920 }
2921 if (xmlListAppend(ref_list, ret) != 0) {
2922 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
2923 "xmlAddRef: Reference list insertion failed!\n",
2924 NULL);
2925 goto failed;
2926 }
2927 return(ret);
2928failed:
2929 if (ret != NULL) {
2930 if (ret->value != NULL)
2931 xmlFree((char *)ret->value);
2932 if (ret->name != NULL)
2933 xmlFree((char *)ret->name);
2934 xmlFree(ret);
2935 }
2936 return(NULL);
2937}
2938
2947void
2950}
2951
2966int
2967xmlIsRef(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
2968 if (attr == NULL)
2969 return(0);
2970 if (doc == NULL) {
2971 doc = attr->doc;
2972 if (doc == NULL) return(0);
2973 }
2974
2975 if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) {
2976 return(0);
2977 } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
2978 /* TODO @@@ */
2979 return(0);
2980 } else {
2981 xmlAttributePtr attrDecl;
2982
2983 if (elem == NULL) return(0);
2984 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, attr->name);
2985 if ((attrDecl == NULL) && (doc->extSubset != NULL))
2986 attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
2987 elem->name, attr->name);
2988
2989 if ((attrDecl != NULL) &&
2990 (attrDecl->atype == XML_ATTRIBUTE_IDREF ||
2991 attrDecl->atype == XML_ATTRIBUTE_IDREFS))
2992 return(1);
2993 }
2994 return(0);
2995}
2996
3008int
3009xmlRemoveRef(xmlDocPtr doc, xmlAttrPtr attr) {
3010 xmlListPtr ref_list;
3012 xmlChar *ID;
3014
3015 if (doc == NULL) return(-1);
3016 if (attr == NULL) return(-1);
3017
3018 table = (xmlRefTablePtr) doc->refs;
3019 if (table == NULL)
3020 return(-1);
3021
3022 ID = xmlNodeListGetString(doc, attr->children, 1);
3023 if (ID == NULL)
3024 return(-1);
3025
3026 ref_list = xmlHashLookup(table, ID);
3027 if(ref_list == NULL) {
3028 xmlFree(ID);
3029 return (-1);
3030 }
3031
3032 /* At this point, ref_list refers to a list of references which
3033 * have the same key as the supplied attr. Our list of references
3034 * is ordered by reference address and we don't have that information
3035 * here to use when removing. We'll have to walk the list and
3036 * check for a matching attribute, when we find one stop the walk
3037 * and remove the entry.
3038 * The list is ordered by reference, so that means we don't have the
3039 * key. Passing the list and the reference to the walker means we
3040 * will have enough data to be able to remove the entry.
3041 */
3042 target.l = ref_list;
3043 target.ap = attr;
3044
3045 /* Remove the supplied attr from our list */
3046 xmlListWalk(ref_list, xmlWalkRemoveRef, &target);
3047
3048 /*If the list is empty then remove the list entry in the hash */
3049 if (xmlListEmpty(ref_list))
3051 xmlFree(ID);
3052 return(0);
3053}
3054
3067xmlGetRefs(xmlDocPtr doc, const xmlChar *ID) {
3069
3070 if (doc == NULL) {
3071 return(NULL);
3072 }
3073
3074 if (ID == NULL) {
3075 return(NULL);
3076 }
3077
3078 table = (xmlRefTablePtr) doc->refs;
3079 if (table == NULL)
3080 return(NULL);
3081
3082 return (xmlHashLookup(table, ID));
3083}
3084
3085/************************************************************************
3086 * *
3087 * Routines for validity checking *
3088 * *
3089 ************************************************************************/
3090
3101xmlElementPtr
3102xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name) {
3104 xmlElementPtr cur;
3105 xmlChar *uqname = NULL, *prefix = NULL;
3106
3107 if ((dtd == NULL) || (name == NULL)) return(NULL);
3108 if (dtd->elements == NULL)
3109 return(NULL);
3110 table = (xmlElementTablePtr) dtd->elements;
3111
3112 uqname = xmlSplitQName2(name, &prefix);
3113 if (uqname != NULL)
3114 name = uqname;
3116 if (prefix != NULL) xmlFree(prefix);
3117 if (uqname != NULL) xmlFree(uqname);
3118 return(cur);
3119}
3131static xmlElementPtr
3133 int create) {
3135 xmlElementPtr cur;
3136 xmlChar *uqname = NULL, *prefix = NULL;
3137
3138 if (dtd == NULL) return(NULL);
3139 if (dtd->elements == NULL) {
3140 xmlDictPtr dict = NULL;
3141
3142 if (dtd->doc != NULL)
3143 dict = dtd->doc->dict;
3144
3145 if (!create)
3146 return(NULL);
3147 /*
3148 * Create the Element table if needed.
3149 */
3150 table = (xmlElementTablePtr) dtd->elements;
3151 if (table == NULL) {
3152 table = xmlHashCreateDict(0, dict);
3153 dtd->elements = (void *) table;
3154 }
3155 if (table == NULL) {
3156 xmlVErrMemory(ctxt, "element table allocation failed");
3157 return(NULL);
3158 }
3159 }
3160 table = (xmlElementTablePtr) dtd->elements;
3161
3162 uqname = xmlSplitQName2(name, &prefix);
3163 if (uqname != NULL)
3164 name = uqname;
3166 if ((cur == NULL) && (create)) {
3167 cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
3168 if (cur == NULL) {
3169 xmlVErrMemory(ctxt, "malloc failed");
3170 goto error;
3171 }
3172 memset(cur, 0, sizeof(xmlElement));
3173 cur->type = XML_ELEMENT_DECL;
3174
3175 /*
3176 * fill the structure.
3177 */
3178 cur->name = xmlStrdup(name);
3179 cur->prefix = xmlStrdup(prefix);
3180 cur->etype = XML_ELEMENT_TYPE_UNDEFINED;
3181
3182 if (xmlHashAddEntry2(table, name, prefix, cur) < 0) {
3183 xmlVErrMemory(ctxt, "adding entry failed");
3185 cur = NULL;
3186 }
3187 }
3188error:
3189 if (prefix != NULL) xmlFree(prefix);
3190 if (uqname != NULL) xmlFree(uqname);
3191 return(cur);
3192}
3193
3205xmlElementPtr
3206xmlGetDtdQElementDesc(xmlDtdPtr dtd, const xmlChar *name,
3207 const xmlChar *prefix) {
3209
3210 if (dtd == NULL) return(NULL);
3211 if (dtd->elements == NULL) return(NULL);
3212 table = (xmlElementTablePtr) dtd->elements;
3213
3214 return(xmlHashLookup2(table, name, prefix));
3215}
3216
3229xmlAttributePtr
3230xmlGetDtdAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name) {
3232 xmlAttributePtr cur;
3233 xmlChar *uqname = NULL, *prefix = NULL;
3234
3235 if (dtd == NULL) return(NULL);
3236 if (dtd->attributes == NULL) return(NULL);
3237
3238 table = (xmlAttributeTablePtr) dtd->attributes;
3239 if (table == NULL)
3240 return(NULL);
3241
3242 uqname = xmlSplitQName2(name, &prefix);
3243
3244 if (uqname != NULL) {
3245 cur = xmlHashLookup3(table, uqname, prefix, elem);
3246 if (prefix != NULL) xmlFree(prefix);
3247 if (uqname != NULL) xmlFree(uqname);
3248 } else
3250 return(cur);
3251}
3252
3266xmlAttributePtr
3267xmlGetDtdQAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name,
3268 const xmlChar *prefix) {
3270
3271 if (dtd == NULL) return(NULL);
3272 if (dtd->attributes == NULL) return(NULL);
3273 table = (xmlAttributeTablePtr) dtd->attributes;
3274
3275 return(xmlHashLookup3(table, name, prefix, elem));
3276}
3277
3288xmlNotationPtr
3289xmlGetDtdNotationDesc(xmlDtdPtr dtd, const xmlChar *name) {
3291
3292 if (dtd == NULL) return(NULL);
3293 if (dtd->notations == NULL) return(NULL);
3294 table = (xmlNotationTablePtr) dtd->notations;
3295
3296 return(xmlHashLookup(table, name));
3297}
3298
3299#if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
3312int
3313xmlValidateNotationUse(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
3314 const xmlChar *notationName) {
3315 xmlNotationPtr notaDecl;
3316 if ((doc == NULL) || (doc->intSubset == NULL) ||
3317 (notationName == NULL)) return(-1);
3318
3319 notaDecl = xmlGetDtdNotationDesc(doc->intSubset, notationName);
3320 if ((notaDecl == NULL) && (doc->extSubset != NULL))
3321 notaDecl = xmlGetDtdNotationDesc(doc->extSubset, notationName);
3322
3323 if ((notaDecl == NULL) && (ctxt != NULL)) {
3324 xmlErrValidNode(ctxt, (xmlNodePtr) doc, XML_DTD_UNKNOWN_NOTATION,
3325 "NOTATION %s is not declared\n",
3326 notationName, NULL, NULL);
3327 return(0);
3328 }
3329 return(1);
3330}
3331#endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */
3332
3344int
3345xmlIsMixedElement(xmlDocPtr doc, const xmlChar *name) {
3346 xmlElementPtr elemDecl;
3347
3348 if ((doc == NULL) || (doc->intSubset == NULL)) return(-1);
3349
3350 elemDecl = xmlGetDtdElementDesc(doc->intSubset, name);
3351 if ((elemDecl == NULL) && (doc->extSubset != NULL))
3352 elemDecl = xmlGetDtdElementDesc(doc->extSubset, name);
3353 if (elemDecl == NULL) return(-1);
3354 switch (elemDecl->etype) {
3355 case XML_ELEMENT_TYPE_UNDEFINED:
3356 return(-1);
3357 case XML_ELEMENT_TYPE_ELEMENT:
3358 return(0);
3359 case XML_ELEMENT_TYPE_EMPTY:
3360 /*
3361 * return 1 for EMPTY since we want VC error to pop up
3362 * on <empty> </empty> for example
3363 */
3364 case XML_ELEMENT_TYPE_ANY:
3365 case XML_ELEMENT_TYPE_MIXED:
3366 return(1);
3367 }
3368 return(1);
3369}
3370
3371#ifdef LIBXML_VALID_ENABLED
3372
3373static int
3374xmlIsDocNameStartChar(xmlDocPtr doc, int c) {
3375 if ((doc == NULL) || (doc->properties & XML_DOC_OLD10) == 0) {
3376 /*
3377 * Use the new checks of production [4] [4a] amd [5] of the
3378 * Update 5 of XML-1.0
3379 */
3380 if (((c >= 'a') && (c <= 'z')) ||
3381 ((c >= 'A') && (c <= 'Z')) ||
3382 (c == '_') || (c == ':') ||
3383 ((c >= 0xC0) && (c <= 0xD6)) ||
3384 ((c >= 0xD8) && (c <= 0xF6)) ||
3385 ((c >= 0xF8) && (c <= 0x2FF)) ||
3386 ((c >= 0x370) && (c <= 0x37D)) ||
3387 ((c >= 0x37F) && (c <= 0x1FFF)) ||
3388 ((c >= 0x200C) && (c <= 0x200D)) ||
3389 ((c >= 0x2070) && (c <= 0x218F)) ||
3390 ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3391 ((c >= 0x3001) && (c <= 0xD7FF)) ||
3392 ((c >= 0xF900) && (c <= 0xFDCF)) ||
3393 ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3394 ((c >= 0x10000) && (c <= 0xEFFFF)))
3395 return(1);
3396 } else {
3397 if (IS_LETTER(c) || (c == '_') || (c == ':'))
3398 return(1);
3399 }
3400 return(0);
3401}
3402
3403static int
3404xmlIsDocNameChar(xmlDocPtr doc, int c) {
3405 if ((doc == NULL) || (doc->properties & XML_DOC_OLD10) == 0) {
3406 /*
3407 * Use the new checks of production [4] [4a] amd [5] of the
3408 * Update 5 of XML-1.0
3409 */
3410 if (((c >= 'a') && (c <= 'z')) ||
3411 ((c >= 'A') && (c <= 'Z')) ||
3412 ((c >= '0') && (c <= '9')) || /* !start */
3413 (c == '_') || (c == ':') ||
3414 (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3415 ((c >= 0xC0) && (c <= 0xD6)) ||
3416 ((c >= 0xD8) && (c <= 0xF6)) ||
3417 ((c >= 0xF8) && (c <= 0x2FF)) ||
3418 ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3419 ((c >= 0x370) && (c <= 0x37D)) ||
3420 ((c >= 0x37F) && (c <= 0x1FFF)) ||
3421 ((c >= 0x200C) && (c <= 0x200D)) ||
3422 ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3423 ((c >= 0x2070) && (c <= 0x218F)) ||
3424 ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3425 ((c >= 0x3001) && (c <= 0xD7FF)) ||
3426 ((c >= 0xF900) && (c <= 0xFDCF)) ||
3427 ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3428 ((c >= 0x10000) && (c <= 0xEFFFF)))
3429 return(1);
3430 } else {
3431 if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3432 (c == '.') || (c == '-') ||
3433 (c == '_') || (c == ':') ||
3434 (IS_COMBINING(c)) ||
3435 (IS_EXTENDER(c)))
3436 return(1);
3437 }
3438 return(0);
3439}
3440
3451static int
3452xmlValidateNameValueInternal(xmlDocPtr doc, const xmlChar *value) {
3453 const xmlChar *cur;
3454 int val, len;
3455
3456 if (value == NULL) return(0);
3457 cur = value;
3459 cur += len;
3460 if (!xmlIsDocNameStartChar(doc, val))
3461 return(0);
3462
3464 cur += len;
3465 while (xmlIsDocNameChar(doc, val)) {
3467 cur += len;
3468 }
3469
3470 if (val != 0) return(0);
3471
3472 return(1);
3473}
3474
3484int
3485xmlValidateNameValue(const xmlChar *value) {
3486 return(xmlValidateNameValueInternal(NULL, value));
3487}
3488
3499static int
3500xmlValidateNamesValueInternal(xmlDocPtr doc, const xmlChar *value) {
3501 const xmlChar *cur;
3502 int val, len;
3503
3504 if (value == NULL) return(0);
3505 cur = value;
3507 cur += len;
3508
3509 if (!xmlIsDocNameStartChar(doc, val))
3510 return(0);
3511
3513 cur += len;
3514 while (xmlIsDocNameChar(doc, val)) {
3516 cur += len;
3517 }
3518
3519 /* Should not test IS_BLANK(val) here -- see erratum E20*/
3520 while (val == 0x20) {
3521 while (val == 0x20) {
3523 cur += len;
3524 }
3525
3526 if (!xmlIsDocNameStartChar(doc, val))
3527 return(0);
3528
3530 cur += len;
3531
3532 while (xmlIsDocNameChar(doc, val)) {
3534 cur += len;
3535 }
3536 }
3537
3538 if (val != 0) return(0);
3539
3540 return(1);
3541}
3542
3552int
3553xmlValidateNamesValue(const xmlChar *value) {
3554 return(xmlValidateNamesValueInternal(NULL, value));
3555}
3556
3569static int
3570xmlValidateNmtokenValueInternal(xmlDocPtr doc, const xmlChar *value) {
3571 const xmlChar *cur;
3572 int val, len;
3573
3574 if (value == NULL) return(0);
3575 cur = value;
3577 cur += len;
3578
3579 if (!xmlIsDocNameChar(doc, val))
3580 return(0);
3581
3583 cur += len;
3584 while (xmlIsDocNameChar(doc, val)) {
3586 cur += len;
3587 }
3588
3589 if (val != 0) return(0);
3590
3591 return(1);
3592}
3593
3605int
3606xmlValidateNmtokenValue(const xmlChar *value) {
3607 return(xmlValidateNmtokenValueInternal(NULL, value));
3608}
3609
3622static int
3623xmlValidateNmtokensValueInternal(xmlDocPtr doc, const xmlChar *value) {
3624 const xmlChar *cur;
3625 int val, len;
3626
3627 if (value == NULL) return(0);
3628 cur = value;
3630 cur += len;
3631
3632 while (IS_BLANK(val)) {
3634 cur += len;
3635 }
3636
3637 if (!xmlIsDocNameChar(doc, val))
3638 return(0);
3639
3640 while (xmlIsDocNameChar(doc, val)) {
3642 cur += len;
3643 }
3644
3645 /* Should not test IS_BLANK(val) here -- see erratum E20*/
3646 while (val == 0x20) {
3647 while (val == 0x20) {
3649 cur += len;
3650 }
3651 if (val == 0) return(1);
3652
3653 if (!xmlIsDocNameChar(doc, val))
3654 return(0);
3655
3657 cur += len;
3658
3659 while (xmlIsDocNameChar(doc, val)) {
3661 cur += len;
3662 }
3663 }
3664
3665 if (val != 0) return(0);
3666
3667 return(1);
3668}
3669
3681int
3682xmlValidateNmtokensValue(const xmlChar *value) {
3683 return(xmlValidateNmtokensValueInternal(NULL, value));
3684}
3685
3701int
3702xmlValidateNotationDecl(xmlValidCtxtPtr ctxt ATTRIBUTE_UNUSED, xmlDocPtr doc ATTRIBUTE_UNUSED,
3703 xmlNotationPtr nota ATTRIBUTE_UNUSED) {
3704 int ret = 1;
3705
3706 return(ret);
3707}
3708
3720static int
3721xmlValidateAttributeValueInternal(xmlDocPtr doc, xmlAttributeType type,
3722 const xmlChar *value) {
3723 switch (type) {
3724 case XML_ATTRIBUTE_ENTITIES:
3725 case XML_ATTRIBUTE_IDREFS:
3726 return(xmlValidateNamesValueInternal(doc, value));
3727 case XML_ATTRIBUTE_ENTITY:
3728 case XML_ATTRIBUTE_IDREF:
3729 case XML_ATTRIBUTE_ID:
3730 case XML_ATTRIBUTE_NOTATION:
3731 return(xmlValidateNameValueInternal(doc, value));
3732 case XML_ATTRIBUTE_NMTOKENS:
3733 case XML_ATTRIBUTE_ENUMERATION:
3734 return(xmlValidateNmtokensValueInternal(doc, value));
3735 case XML_ATTRIBUTE_NMTOKEN:
3736 return(xmlValidateNmtokenValueInternal(doc, value));
3737 case XML_ATTRIBUTE_CDATA:
3738 break;
3739 }
3740 return(1);
3741}
3742
3767int
3768xmlValidateAttributeValue(xmlAttributeType type, const xmlChar *value) {
3769 return(xmlValidateAttributeValueInternal(NULL, type, value));
3770}
3771
3801static int
3802xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
3803 const xmlChar *name, xmlAttributeType type, const xmlChar *value) {
3804 int ret = 1;
3805 switch (type) {
3806 case XML_ATTRIBUTE_IDREFS:
3807 case XML_ATTRIBUTE_IDREF:
3808 case XML_ATTRIBUTE_ID:
3809 case XML_ATTRIBUTE_NMTOKENS:
3810 case XML_ATTRIBUTE_ENUMERATION:
3811 case XML_ATTRIBUTE_NMTOKEN:
3812 case XML_ATTRIBUTE_CDATA:
3813 break;
3814 case XML_ATTRIBUTE_ENTITY: {
3815 xmlEntityPtr ent;
3816
3817 ent = xmlGetDocEntity(doc, value);
3818 /* yeah it's a bit messy... */
3819 if ((ent == NULL) && (doc->standalone == 1)) {
3820 doc->standalone = 0;
3821 ent = xmlGetDocEntity(doc, value);
3822 }
3823 if (ent == NULL) {
3824 xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3826 "ENTITY attribute %s reference an unknown entity \"%s\"\n",
3827 name, value, NULL);
3828 ret = 0;
3829 } else if (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
3830 xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3832 "ENTITY attribute %s reference an entity \"%s\" of wrong type\n",
3833 name, value, NULL);
3834 ret = 0;
3835 }
3836 break;
3837 }
3838 case XML_ATTRIBUTE_ENTITIES: {
3839 xmlChar *dup, *nam = NULL, *cur, save;
3840 xmlEntityPtr ent;
3841
3842 dup = xmlStrdup(value);
3843 if (dup == NULL)
3844 return(0);
3845 cur = dup;
3846 while (*cur != 0) {
3847 nam = cur;
3848 while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
3849 save = *cur;
3850 *cur = 0;
3851 ent = xmlGetDocEntity(doc, nam);
3852 if (ent == NULL) {
3853 xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3855 "ENTITIES attribute %s reference an unknown entity \"%s\"\n",
3856 name, nam, NULL);
3857 ret = 0;
3858 } else if (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
3859 xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3861 "ENTITIES attribute %s reference an entity \"%s\" of wrong type\n",
3862 name, nam, NULL);
3863 ret = 0;
3864 }
3865 if (save == 0)
3866 break;
3867 *cur = save;
3868 while (IS_BLANK_CH(*cur)) cur++;
3869 }
3870 xmlFree(dup);
3871 break;
3872 }
3873 case XML_ATTRIBUTE_NOTATION: {
3874 xmlNotationPtr nota;
3875
3876 nota = xmlGetDtdNotationDesc(doc->intSubset, value);
3877 if ((nota == NULL) && (doc->extSubset != NULL))
3878 nota = xmlGetDtdNotationDesc(doc->extSubset, value);
3879
3880 if (nota == NULL) {
3881 xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3883 "NOTATION attribute %s reference an unknown notation \"%s\"\n",
3884 name, value, NULL);
3885 ret = 0;
3886 }
3887 break;
3888 }
3889 }
3890 return(ret);
3891}
3892
3917xmlChar *
3918xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
3919 xmlNodePtr elem, const xmlChar *name, const xmlChar *value) {
3920 xmlChar *ret;
3921 xmlAttributePtr attrDecl = NULL;
3922 int extsubset = 0;
3923
3924 if (doc == NULL) return(NULL);
3925 if (elem == NULL) return(NULL);
3926 if (name == NULL) return(NULL);
3927 if (value == NULL) return(NULL);
3928
3929 if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
3930 xmlChar fn[50];
3932
3933 fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
3934 if (fullname == NULL)
3935 return(NULL);
3936 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, name);
3937 if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
3938 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname, name);
3939 if (attrDecl != NULL)
3940 extsubset = 1;
3941 }
3942 if ((fullname != fn) && (fullname != elem->name))
3944 }
3945 if ((attrDecl == NULL) && (doc->intSubset != NULL))
3946 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name);
3947 if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
3948 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, name);
3949 if (attrDecl != NULL)
3950 extsubset = 1;
3951 }
3952
3953 if (attrDecl == NULL)
3954 return(NULL);
3955 if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
3956 return(NULL);
3957
3958 ret = xmlStrdup(value);
3959 if (ret == NULL)
3960 return(NULL);
3962 if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) {
3963 xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE,
3964"standalone: %s on %s value had to be normalized based on external subset declaration\n",
3965 name, elem->name, NULL);
3966 ctxt->valid = 0;
3967 }
3968 return(ret);
3969}
3970
3990xmlChar *
3991xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
3992 const xmlChar *name, const xmlChar *value) {
3993 xmlChar *ret;
3994 xmlAttributePtr attrDecl = NULL;
3995
3996 if (doc == NULL) return(NULL);
3997 if (elem == NULL) return(NULL);
3998 if (name == NULL) return(NULL);
3999 if (value == NULL) return(NULL);
4000
4001 if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
4002 xmlChar fn[50];
4004
4005 fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
4006 if (fullname == NULL)
4007 return(NULL);
4008 if ((fullname != fn) && (fullname != elem->name))
4010 }
4011 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name);
4012 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4013 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, name);
4014
4015 if (attrDecl == NULL)
4016 return(NULL);
4017 if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
4018 return(NULL);
4019
4020 ret = xmlStrdup(value);
4021 if (ret == NULL)
4022 return(NULL);
4024 return(ret);
4025}
4026
4027static void
4028xmlValidateAttributeIdCallback(void *payload, void *data,
4029 const xmlChar *name ATTRIBUTE_UNUSED) {
4030 xmlAttributePtr attr = (xmlAttributePtr) payload;
4031 int *count = (int *) data;
4032 if (attr->atype == XML_ATTRIBUTE_ID) (*count)++;
4033}
4034
4053int
4054xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
4055 xmlAttributePtr attr) {
4056 int ret = 1;
4057 int val;
4058 CHECK_DTD;
4059 if(attr == NULL) return(1);
4060
4061 /* Attribute Default Legal */
4062 /* Enumeration */
4063 if (attr->defaultValue != NULL) {
4064 val = xmlValidateAttributeValueInternal(doc, attr->atype,
4065 attr->defaultValue);
4066 if (val == 0) {
4067 xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ATTRIBUTE_DEFAULT,
4068 "Syntax of default value for attribute %s of %s is not valid\n",
4069 attr->name, attr->elem, NULL);
4070 }
4071 ret &= val;
4072 }
4073
4074 /* ID Attribute Default */
4075 if ((attr->atype == XML_ATTRIBUTE_ID)&&
4076 (attr->def != XML_ATTRIBUTE_IMPLIED) &&
4077 (attr->def != XML_ATTRIBUTE_REQUIRED)) {
4078 xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_FIXED,
4079 "ID attribute %s of %s is not valid must be #IMPLIED or #REQUIRED\n",
4080 attr->name, attr->elem, NULL);
4081 ret = 0;
4082 }
4083
4084 /* One ID per Element Type */
4085 if (attr->atype == XML_ATTRIBUTE_ID) {
4086 int nbId;
4087
4088 /* the trick is that we parse DtD as their own internal subset */
4089 xmlElementPtr elem = xmlGetDtdElementDesc(doc->intSubset,
4090 attr->elem);
4091 if (elem != NULL) {
4092 nbId = xmlScanIDAttributeDecl(NULL, elem, 0);
4093 } else {
4095
4096 /*
4097 * The attribute may be declared in the internal subset and the
4098 * element in the external subset.
4099 */
4100 nbId = 0;
4101 if (doc->intSubset != NULL) {
4102 table = (xmlAttributeTablePtr) doc->intSubset->attributes;
4103 xmlHashScan3(table, NULL, NULL, attr->elem,
4104 xmlValidateAttributeIdCallback, &nbId);
4105 }
4106 }
4107 if (nbId > 1) {
4108
4109 xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
4110 "Element %s has %d ID attribute defined in the internal subset : %s\n",
4111 attr->elem, nbId, attr->name);
4112 } else if (doc->extSubset != NULL) {
4113 int extId = 0;
4114 elem = xmlGetDtdElementDesc(doc->extSubset, attr->elem);
4115 if (elem != NULL) {
4116 extId = xmlScanIDAttributeDecl(NULL, elem, 0);
4117 }
4118 if (extId > 1) {
4119 xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
4120 "Element %s has %d ID attribute defined in the external subset : %s\n",
4121 attr->elem, extId, attr->name);
4122 } else if (extId + nbId > 1) {
4123 xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
4124"Element %s has ID attributes defined in the internal and external subset : %s\n",
4125 attr->elem, attr->name, NULL);
4126 }
4127 }
4128 }
4129
4130 /* Validity Constraint: Enumeration */
4131 if ((attr->defaultValue != NULL) && (attr->tree != NULL)) {
4132 xmlEnumerationPtr tree = attr->tree;
4133 while (tree != NULL) {
4134 if (xmlStrEqual(tree->name, attr->defaultValue)) break;
4135 tree = tree->next;
4136 }
4137 if (tree == NULL) {
4138 xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ATTRIBUTE_VALUE,
4139"Default value \"%s\" for attribute %s of %s is not among the enumerated set\n",
4140 attr->defaultValue, attr->name, attr->elem);
4141 ret = 0;
4142 }
4143 }
4144
4145 return(ret);
4146}
4147
4164int
4165xmlValidateElementDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
4166 xmlElementPtr elem) {
4167 int ret = 1;
4168 xmlElementPtr tst;
4169
4170 CHECK_DTD;
4171
4172 if (elem == NULL) return(1);
4173
4174#if 0
4175#ifdef LIBXML_REGEXP_ENABLED
4176 /* Build the regexp associated to the content model */
4177 ret = xmlValidBuildContentModel(ctxt, elem);
4178#endif
4179#endif
4180
4181 /* No Duplicate Types */
4182 if (elem->etype == XML_ELEMENT_TYPE_MIXED) {
4183 xmlElementContentPtr cur, next;
4184 const xmlChar *name;
4185
4186 cur = elem->content;
4187 while (cur != NULL) {
4188 if (cur->type != XML_ELEMENT_CONTENT_OR) break;
4189 if (cur->c1 == NULL) break;
4190 if (cur->c1->type == XML_ELEMENT_CONTENT_ELEMENT) {
4191 name = cur->c1->name;
4192 next = cur->c2;
4193 while (next != NULL) {
4194 if (next->type == XML_ELEMENT_CONTENT_ELEMENT) {
4195 if ((xmlStrEqual(next->name, name)) &&
4196 (xmlStrEqual(next->prefix, cur->c1->prefix))) {
4197 if (cur->c1->prefix == NULL) {
4198 xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4199 "Definition of %s has duplicate references of %s\n",
4200 elem->name, name, NULL);
4201 } else {
4202 xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4203 "Definition of %s has duplicate references of %s:%s\n",
4204 elem->name, cur->c1->prefix, name);
4205 }
4206 ret = 0;
4207 }
4208 break;
4209 }
4210 if (next->c1 == NULL) break;
4211 if (next->c1->type != XML_ELEMENT_CONTENT_ELEMENT) break;
4212 if ((xmlStrEqual(next->c1->name, name)) &&
4213 (xmlStrEqual(next->c1->prefix, cur->c1->prefix))) {
4214 if (cur->c1->prefix == NULL) {
4215 xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4216 "Definition of %s has duplicate references to %s\n",
4217 elem->name, name, NULL);
4218 } else {
4219 xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4220 "Definition of %s has duplicate references to %s:%s\n",
4221 elem->name, cur->c1->prefix, name);
4222 }
4223 ret = 0;
4224 }
4225 next = next->c2;
4226 }
4227 }
4228 cur = cur->c2;
4229 }
4230 }
4231
4232 /* VC: Unique Element Type Declaration */
4233 tst = xmlGetDtdElementDesc(doc->intSubset, elem->name);
4234 if ((tst != NULL ) && (tst != elem) &&
4235 ((tst->prefix == elem->prefix) ||
4236 (xmlStrEqual(tst->prefix, elem->prefix))) &&
4237 (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
4238 xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED,
4239 "Redefinition of element %s\n",
4240 elem->name, NULL, NULL);
4241 ret = 0;
4242 }
4243 tst = xmlGetDtdElementDesc(doc->extSubset, elem->name);
4244 if ((tst != NULL ) && (tst != elem) &&
4245 ((tst->prefix == elem->prefix) ||
4246 (xmlStrEqual(tst->prefix, elem->prefix))) &&
4247 (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
4248 xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED,
4249 "Redefinition of element %s\n",
4250 elem->name, NULL, NULL);
4251 ret = 0;
4252 }
4253 /* One ID per Element Type
4254 * already done when registering the attribute
4255 if (xmlScanIDAttributeDecl(ctxt, elem) > 1) {
4256 ret = 0;
4257 } */
4258 return(ret);
4259}
4260
4286int
4287xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
4288 xmlNodePtr elem, xmlAttrPtr attr, const xmlChar *value)
4289{
4290 xmlAttributePtr attrDecl = NULL;
4291 int val;
4292 int ret = 1;
4293
4294 CHECK_DTD;
4295 if ((elem == NULL) || (elem->name == NULL)) return(0);
4296 if ((attr == NULL) || (attr->name == NULL)) return(0);
4297
4298 if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
4299 xmlChar fn[50];
4301
4302 fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
4303 if (fullname == NULL)
4304 return(0);
4305 if (attr->ns != NULL) {
4306 attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
4307 attr->name, attr->ns->prefix);
4308 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4309 attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
4310 attr->name, attr->ns->prefix);
4311 } else {
4312 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, attr->name);
4313 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4314 attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
4315 fullname, attr->name);
4316 }
4317 if ((fullname != fn) && (fullname != elem->name))
4319 }
4320 if (attrDecl == NULL) {
4321 if (attr->ns != NULL) {
4322 attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
4323 attr->name, attr->ns->prefix);
4324 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4325 attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
4326 attr->name, attr->ns->prefix);
4327 } else {
4328 attrDecl = xmlGetDtdAttrDesc(doc->intSubset,
4329 elem->name, attr->name);
4330 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4331 attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
4332 elem->name, attr->name);
4333 }
4334 }
4335
4336
4337 /* Validity Constraint: Attribute Value Type */
4338 if (attrDecl == NULL) {
4339 xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE,
4340 "No declaration for attribute %s of element %s\n",
4341 attr->name, elem->name, NULL);
4342 return(0);
4343 }
4344 attr->atype = attrDecl->atype;
4345
4346 val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
4347 if (val == 0) {
4348 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4349 "Syntax of value for attribute %s of %s is not valid\n",
4350 attr->name, elem->name, NULL);
4351 ret = 0;
4352 }
4353
4354 /* Validity constraint: Fixed Attribute Default */
4355 if (attrDecl->def == XML_ATTRIBUTE_FIXED) {
4356 if (!xmlStrEqual(value, attrDecl->defaultValue)) {
4357 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT,
4358 "Value for attribute %s of %s is different from default \"%s\"\n",
4359 attr->name, elem->name, attrDecl->defaultValue);
4360 ret = 0;
4361 }
4362 }
4363
4364 /* Validity Constraint: ID uniqueness */
4365 if (attrDecl->atype == XML_ATTRIBUTE_ID) {
4366 if (xmlAddID(ctxt, doc, value, attr) == NULL)
4367 ret = 0;
4368 }
4369
4370 if ((attrDecl->atype == XML_ATTRIBUTE_IDREF) ||
4371 (attrDecl->atype == XML_ATTRIBUTE_IDREFS)) {
4372 if (xmlAddRef(ctxt, doc, value, attr) == NULL)
4373 ret = 0;
4374 }
4375
4376 /* Validity Constraint: Notation Attributes */
4377 if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
4378 xmlEnumerationPtr tree = attrDecl->tree;
4379 xmlNotationPtr nota;
4380
4381 /* First check that the given NOTATION was declared */
4382 nota = xmlGetDtdNotationDesc(doc->intSubset, value);
4383 if (nota == NULL)
4384 nota = xmlGetDtdNotationDesc(doc->extSubset, value);
4385
4386 if (nota == NULL) {
4387 xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION,
4388 "Value \"%s\" for attribute %s of %s is not a declared Notation\n",
4389 value, attr->name, elem->name);
4390 ret = 0;
4391 }
4392
4393 /* Second, verify that it's among the list */
4394 while (tree != NULL) {
4395 if (xmlStrEqual(tree->name, value)) break;
4396 tree = tree->next;
4397 }
4398 if (tree == NULL) {
4399 xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE,
4400"Value \"%s\" for attribute %s of %s is not among the enumerated notations\n",
4401 value, attr->name, elem->name);
4402 ret = 0;
4403 }
4404 }
4405
4406 /* Validity Constraint: Enumeration */
4407 if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) {
4408 xmlEnumerationPtr tree = attrDecl->tree;
4409 while (tree != NULL) {
4410 if (xmlStrEqual(tree->name, value)) break;
4411 tree = tree->next;
4412 }
4413 if (tree == NULL) {
4414 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4415 "Value \"%s\" for attribute %s of %s is not among the enumerated set\n",
4416 value, attr->name, elem->name);
4417 ret = 0;
4418 }
4419 }
4420
4421 /* Fixed Attribute Default */
4422 if ((attrDecl->def == XML_ATTRIBUTE_FIXED) &&
4423 (!xmlStrEqual(attrDecl->defaultValue, value))) {
4424 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4425 "Value for attribute %s of %s must be \"%s\"\n",
4426 attr->name, elem->name, attrDecl->defaultValue);
4427 ret = 0;
4428 }
4429
4430 /* Extra check for the attribute value */
4431 ret &= xmlValidateAttributeValue2(ctxt, doc, attr->name,
4432 attrDecl->atype, value);
4433
4434 return(ret);
4435}
4436
4463int
4464xmlValidateOneNamespace(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
4465xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) {
4466 /* xmlElementPtr elemDecl; */
4467 xmlAttributePtr attrDecl = NULL;
4468 int val;
4469 int ret = 1;
4470
4471 CHECK_DTD;
4472 if ((elem == NULL) || (elem->name == NULL)) return(0);
4473 if ((ns == NULL) || (ns->href == NULL)) return(0);
4474
4475 if (prefix != NULL) {
4476 xmlChar fn[50];
4478
4479 fullname = xmlBuildQName(elem->name, prefix, fn, 50);
4480 if (fullname == NULL) {
4481 xmlVErrMemory(ctxt, "Validating namespace");
4482 return(0);
4483 }
4484 if (ns->prefix != NULL) {
4485 attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
4486 ns->prefix, BAD_CAST "xmlns");
4487 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4488 attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
4489 ns->prefix, BAD_CAST "xmlns");
4490 } else {
4491 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname,
4492 BAD_CAST "xmlns");
4493 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4494 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname,
4495 BAD_CAST "xmlns");
4496 }
4497 if ((fullname != fn) && (fullname != elem->name))
4499 }
4500 if (attrDecl == NULL) {
4501 if (ns->prefix != NULL) {
4502 attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
4503 ns->prefix, BAD_CAST "xmlns");
4504 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4505 attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
4506 ns->prefix, BAD_CAST "xmlns");
4507 } else {
4508 attrDecl = xmlGetDtdAttrDesc(doc->intSubset,
4509 elem->name, BAD_CAST "xmlns");
4510 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4511 attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
4512 elem->name, BAD_CAST "xmlns");
4513 }
4514 }
4515
4516
4517 /* Validity Constraint: Attribute Value Type */
4518 if (attrDecl == NULL) {
4519 if (ns->prefix != NULL) {
4520 xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE,
4521 "No declaration for attribute xmlns:%s of element %s\n",
4522 ns->prefix, elem->name, NULL);
4523 } else {
4524 xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE,
4525 "No declaration for attribute xmlns of element %s\n",
4526 elem->name, NULL, NULL);
4527 }
4528 return(0);
4529 }
4530
4531 val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
4532 if (val == 0) {
4533 if (ns->prefix != NULL) {
4534 xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_DEFAULT,
4535 "Syntax of value for attribute xmlns:%s of %s is not valid\n",
4536 ns->prefix, elem->name, NULL);
4537 } else {
4538 xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_DEFAULT,
4539 "Syntax of value for attribute xmlns of %s is not valid\n",
4540 elem->name, NULL, NULL);
4541 }
4542 ret = 0;
4543 }
4544
4545 /* Validity constraint: Fixed Attribute Default */
4546 if (attrDecl->def == XML_ATTRIBUTE_FIXED) {
4547 if (!xmlStrEqual(value, attrDecl->defaultValue)) {
4548 if (ns->prefix != NULL) {
4549 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT,
4550 "Value for attribute xmlns:%s of %s is different from default \"%s\"\n",
4551 ns->prefix, elem->name, attrDecl->defaultValue);
4552 } else {
4553 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT,
4554 "Value for attribute xmlns of %s is different from default \"%s\"\n",
4555 elem->name, attrDecl->defaultValue, NULL);
4556 }
4557 ret = 0;
4558 }
4559 }
4560
4561 /*
4562 * Casting ns to xmlAttrPtr is wrong. We'd need separate functions
4563 * xmlAddID and xmlAddRef for namespace declarations, but it makes
4564 * no practical sense to use ID types anyway.
4565 */
4566#if 0
4567 /* Validity Constraint: ID uniqueness */
4568 if (attrDecl->atype == XML_ATTRIBUTE_ID) {
4569 if (xmlAddID(ctxt, doc, value, (xmlAttrPtr) ns) == NULL)
4570 ret = 0;
4571 }
4572
4573 if ((attrDecl->atype == XML_ATTRIBUTE_IDREF) ||
4574 (attrDecl->atype == XML_ATTRIBUTE_IDREFS)) {
4575 if (xmlAddRef(ctxt, doc, value, (xmlAttrPtr) ns) == NULL)
4576 ret = 0;
4577 }
4578#endif
4579
4580 /* Validity Constraint: Notation Attributes */
4581 if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
4582 xmlEnumerationPtr tree = attrDecl->tree;
4583 xmlNotationPtr nota;
4584
4585 /* First check that the given NOTATION was declared */
4586 nota = xmlGetDtdNotationDesc(doc->intSubset, value);
4587 if (nota == NULL)
4588 nota = xmlGetDtdNotationDesc(doc->extSubset, value);
4589
4590 if (nota == NULL) {
4591 if (ns->prefix != NULL) {
4592 xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION,
4593 "Value \"%s\" for attribute xmlns:%s of %s is not a declared Notation\n",
4594 value, ns->prefix, elem->name);
4595 } else {
4596 xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION,
4597 "Value \"%s\" for attribute xmlns of %s is not a declared Notation\n",
4598 value, elem->name, NULL);
4599 }
4600 ret = 0;
4601 }
4602
4603 /* Second, verify that it's among the list */
4604 while (tree != NULL) {
4605 if (xmlStrEqual(tree->name, value)) break;
4606 tree = tree->next;
4607 }
4608 if (tree == NULL) {
4609 if (ns->prefix != NULL) {
4610 xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE,
4611"Value \"%s\" for attribute xmlns:%s of %s is not among the enumerated notations\n",
4612 value, ns->prefix, elem->name);
4613 } else {
4614 xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE,
4615"Value \"%s\" for attribute xmlns of %s is not among the enumerated notations\n",
4616 value, elem->name, NULL);
4617 }
4618 ret = 0;
4619 }
4620 }
4621
4622 /* Validity Constraint: Enumeration */
4623 if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) {
4624 xmlEnumerationPtr tree = attrDecl->tree;
4625 while (tree != NULL) {
4626 if (xmlStrEqual(tree->name, value)) break;
4627 tree = tree->next;
4628 }
4629 if (tree == NULL) {
4630 if (ns->prefix != NULL) {
4631 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4632"Value \"%s\" for attribute xmlns:%s of %s is not among the enumerated set\n",
4633 value, ns->prefix, elem->name);
4634 } else {
4635 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4636"Value \"%s\" for attribute xmlns of %s is not among the enumerated set\n",
4637 value, elem->name, NULL);
4638 }
4639 ret = 0;
4640 }
4641 }
4642
4643 /* Fixed Attribute Default */
4644 if ((attrDecl->def == XML_ATTRIBUTE_FIXED) &&
4645 (!xmlStrEqual(attrDecl->defaultValue, value))) {
4646 if (ns->prefix != NULL) {
4647 xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE,
4648 "Value for attribute xmlns:%s of %s must be \"%s\"\n",
4649 ns->prefix, elem->name, attrDecl->defaultValue);
4650 } else {
4651 xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE,
4652 "Value for attribute xmlns of %s must be \"%s\"\n",
4653 elem->name, attrDecl->defaultValue, NULL);
4654 }
4655 ret = 0;
4656 }
4657
4658 /* Extra check for the attribute value */
4659 if (ns->prefix != NULL) {
4660 ret &= xmlValidateAttributeValue2(ctxt, doc, ns->prefix,
4661 attrDecl->atype, value);
4662 } else {
4663 ret &= xmlValidateAttributeValue2(ctxt, doc, BAD_CAST "xmlns",
4664 attrDecl->atype, value);
4665 }
4666
4667 return(ret);
4668}
4669
4670#ifndef LIBXML_REGEXP_ENABLED
4681static xmlNodePtr
4682xmlValidateSkipIgnorable(xmlNodePtr child) {
4683 while (child != NULL) {
4684 switch (child->type) {
4685 /* These things are ignored (skipped) during validation. */
4686 case XML_PI_NODE:
4687 case XML_COMMENT_NODE:
4688 case XML_XINCLUDE_START:
4689 case XML_XINCLUDE_END:
4690 child = child->next;
4691 break;
4692 case XML_TEXT_NODE:
4693 if (xmlIsBlankNode(child))
4694 child = child->next;
4695 else
4696 return(child);
4697 break;
4698 /* keep current node */
4699 default:
4700 return(child);
4701 }
4702 }
4703 return(child);
4704}
4705
4717static int
4718xmlValidateElementType(xmlValidCtxtPtr ctxt) {
4719 int ret = -1;
4720 int determinist = 1;
4721
4722 NODE = xmlValidateSkipIgnorable(NODE);
4723 if ((NODE == NULL) && (CONT == NULL))
4724 return(1);
4725 if ((NODE == NULL) &&
4726 ((CONT->ocur == XML_ELEMENT_CONTENT_MULT) ||
4727 (CONT->ocur == XML_ELEMENT_CONTENT_OPT))) {
4728 return(1);
4729 }
4730 if (CONT == NULL) return(-1);
4731 if ((NODE != NULL) && (NODE->type == XML_ENTITY_REF_NODE))
4732 return(-2);
4733
4734 /*
4735 * We arrive here when more states need to be examined
4736 */
4737cont:
4738
4739 /*
4740 * We just recovered from a rollback generated by a possible
4741 * epsilon transition, go directly to the analysis phase
4742 */
4743 if (STATE == ROLLBACK_PARENT) {
4744 ret = 1;
4745 goto analyze;
4746 }
4747
4748 /*
4749 * we may have to save a backup state here. This is the equivalent
4750 * of handling epsilon transition in NFAs.
4751 */
4752 if ((CONT != NULL) &&
4753 ((CONT->parent == NULL) ||
4754 (CONT->parent == (xmlElementContentPtr) 1) ||
4755 (CONT->parent->type != XML_ELEMENT_CONTENT_OR)) &&
4756 ((CONT->ocur == XML_ELEMENT_CONTENT_MULT) ||
4757 (CONT->ocur == XML_ELEMENT_CONTENT_OPT) ||
4758 ((CONT->ocur == XML_ELEMENT_CONTENT_PLUS) && (OCCURRENCE)))) {
4759 if (vstateVPush(ctxt, CONT, NODE, DEPTH, OCCURS, ROLLBACK_PARENT) < 0)
4760 return(0);
4761 }
4762
4763
4764 /*
4765 * Check first if the content matches
4766 */
4767 switch (CONT->type) {
4768 case XML_ELEMENT_CONTENT_PCDATA:
4769 if (NODE == NULL) {
4770 ret = 0;
4771 break;
4772 }
4773 if (NODE->type == XML_TEXT_NODE) {
4774 /*
4775 * go to next element in the content model
4776 * skipping ignorable elems
4777 */
4778 do {
4779 NODE = NODE->next;
4780 NODE = xmlValidateSkipIgnorable(NODE);
4781 if ((NODE != NULL) &&
4782 (NODE->type == XML_ENTITY_REF_NODE))
4783 return(-2);
4784 } while ((NODE != NULL) &&
4785 ((NODE->type != XML_ELEMENT_NODE) &&
4786 (NODE->type != XML_TEXT_NODE) &&
4787 (NODE->type != XML_CDATA_SECTION_NODE)));
4788 ret = 1;
4789 break;
4790 } else {
4791 ret = 0;
4792 break;
4793 }
4794 break;
4795 case XML_ELEMENT_CONTENT_ELEMENT:
4796 if (NODE == NULL) {
4797 ret = 0;
4798 break;
4799 }
4800 ret = ((NODE->type == XML_ELEMENT_NODE) &&
4801 (xmlStrEqual(NODE->name, CONT->name)));
4802 if (ret == 1) {
4803 if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) {
4804 ret = (CONT->prefix == NULL);
4805 } else if (CONT->prefix == NULL) {
4806 ret = 0;
4807 } else {
4808 ret = xmlStrEqual(NODE->ns->prefix, CONT->prefix);
4809 }
4810 }
4811 if (ret == 1) {
4812 /*
4813 * go to next element in the content model
4814 * skipping ignorable elems
4815 */
4816 do {
4817 NODE = NODE->next;
4818 NODE = xmlValidateSkipIgnorable(NODE);
4819 if ((NODE != NULL) &&
4820 (NODE->type == XML_ENTITY_REF_NODE))
4821 return(-2);
4822 } while ((NODE != NULL) &&
4823 ((NODE->type != XML_ELEMENT_NODE) &&
4824 (NODE->type != XML_TEXT_NODE) &&
4825 (NODE->type != XML_CDATA_SECTION_NODE)));
4826 } else {
4827 ret = 0;
4828 break;
4829 }
4830 break;
4831 case XML_ELEMENT_CONTENT_OR:
4832 /*
4833 * Small optimization.
4834 */
4835 if (CONT->c1->type == XML_ELEMENT_CONTENT_ELEMENT) {
4836 if ((NODE == NULL) ||
4837 (!xmlStrEqual(NODE->name, CONT->c1->name))) {
4838 DEPTH++;
4839 CONT = CONT->c2;
4840 goto cont;
4841 }
4842 if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) {
4843 ret = (CONT->c1->prefix == NULL);
4844 } else if (CONT->c1->prefix == NULL) {
4845 ret = 0;
4846 } else {
4847 ret = xmlStrEqual(NODE->ns->prefix, CONT->c1->prefix);
4848 }
4849 if (ret == 0) {
4850 DEPTH++;
4851 CONT = CONT->c2;
4852 goto cont;
4853 }
4854 }
4855
4856 /*
4857 * save the second branch 'or' branch
4858 */
4859 if (vstateVPush(ctxt, CONT->c2, NODE, DEPTH + 1,
4860 OCCURS, ROLLBACK_OR) < 0)
4861 return(-1);
4862 DEPTH++;
4863 CONT = CONT->c1;
4864 goto cont;
4865 case XML_ELEMENT_CONTENT_SEQ:
4866 /*
4867 * Small optimization.
4868 */
4869 if ((CONT->c1->type == XML_ELEMENT_CONTENT_ELEMENT) &&
4870 ((CONT->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
4871 (CONT->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
4872 if ((NODE == NULL) ||
4873 (!xmlStrEqual(NODE->name, CONT->c1->name))) {
4874 DEPTH++;
4875 CONT = CONT->c2;
4876 goto cont;
4877 }
4878 if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) {
4879 ret = (CONT->c1->prefix == NULL);
4880 } else if (CONT->c1->prefix == NULL) {
4881 ret = 0;
4882 } else {
4883 ret = xmlStrEqual(NODE->ns->prefix, CONT->c1->prefix);
4884 }
4885 if (ret == 0) {
4886 DEPTH++;
4887 CONT = CONT->c2;
4888 goto cont;
4889 }
4890 }
4891 DEPTH++;
4892 CONT = CONT->c1;
4893 goto cont;
4894 }
4895
4896 /*
4897 * At this point handle going up in the tree
4898 */
4899 if (ret == -1) {
4900 return(ret);
4901 }
4902analyze:
4903 while (CONT != NULL) {
4904 /*
4905 * First do the analysis depending on the occurrence model at
4906 * this level.
4907 */
4908 if (ret == 0) {
4909 switch (CONT->ocur) {
4910 xmlNodePtr cur;
4911
4912 case XML_ELEMENT_CONTENT_ONCE:
4913 cur = ctxt->vstate->node;
4914 if (vstateVPop(ctxt) < 0 ) {
4915 return(0);
4916 }
4917 if (cur != ctxt->vstate->node)
4918 determinist = -3;
4919 goto cont;
4920 case XML_ELEMENT_CONTENT_PLUS:
4921 if (OCCURRENCE == 0) {
4922 cur = ctxt->vstate->node;
4923 if (vstateVPop(ctxt) < 0 ) {
4924 return(0);
4925 }
4926 if (cur != ctxt->vstate->node)
4927 determinist = -3;
4928 goto cont;
4929 }
4930 ret = 1;
4931 break;
4932 case XML_ELEMENT_CONTENT_MULT:
4933 ret = 1;
4934 break;
4935 case XML_ELEMENT_CONTENT_OPT:
4936 ret = 1;
4937 break;
4938 }
4939 } else {
4940 switch (CONT->ocur) {
4941 case XML_ELEMENT_CONTENT_OPT:
4942 ret = 1;
4943 break;
4944 case XML_ELEMENT_CONTENT_ONCE:
4945 ret = 1;
4946 break;
4947 case XML_ELEMENT_CONTENT_PLUS:
4948 if (STATE == ROLLBACK_PARENT) {
4949 ret = 1;
4950 break;
4951 }
4952 if (NODE == NULL) {
4953 ret = 1;
4954 break;
4955 }
4956 SET_OCCURRENCE;
4957 goto cont;
4958 case XML_ELEMENT_CONTENT_MULT:
4959 if (STATE == ROLLBACK_PARENT) {
4960 ret = 1;
4961 break;
4962 }
4963 if (NODE == NULL) {
4964 ret = 1;
4965 break;
4966 }
4967 /* SET_OCCURRENCE; */
4968 goto cont;
4969 }
4970 }
4971 STATE = 0;
4972
4973 /*
4974 * Then act accordingly at the parent level
4975 */
4976 RESET_OCCURRENCE;
4977 if ((CONT->parent == NULL) ||
4978 (CONT->parent == (xmlElementContentPtr) 1))
4979 break;
4980
4981 switch (CONT->parent->type) {
4982 case XML_ELEMENT_CONTENT_PCDATA:
4983 return(-1);
4984 case XML_ELEMENT_CONTENT_ELEMENT:
4985 return(-1);
4986 case XML_ELEMENT_CONTENT_OR:
4987 if (ret == 1) {
4988 CONT = CONT->parent;
4989 DEPTH--;
4990 } else {
4991 CONT = CONT->parent;
4992 DEPTH--;
4993 }
4994 break;
4995 case XML_ELEMENT_CONTENT_SEQ:
4996 if (ret == 0) {
4997 CONT = CONT->parent;
4998 DEPTH--;
4999 } else if (CONT == CONT->parent->c1) {
5000 CONT = CONT->parent->c2;
5001 goto cont;
5002 } else {
5003 CONT = CONT->parent;
5004 DEPTH--;
5005 }
5006 }
5007 }
5008 if (NODE != NULL) {
5009 xmlNodePtr cur;
5010
5011 cur = ctxt->vstate->node;
5012 if (vstateVPop(ctxt) < 0 ) {
5013 return(0);
5014 }
5015 if (cur != ctxt->vstate->node)
5016 determinist = -3;
5017 goto cont;
5018 }
5019 if (ret == 0) {
5020 xmlNodePtr cur;
5021
5022 cur = ctxt->vstate->node;
5023 if (vstateVPop(ctxt) < 0 ) {
5024 return(0);
5025 }
5026 if (cur != ctxt->vstate->node)
5027 determinist = -3;
5028 goto cont;
5029 }
5030 return(determinist);
5031}
5032#endif
5033
5044static void
5045xmlSnprintfElements(char *buf, int size, xmlNodePtr node, int glob) {
5046 xmlNodePtr cur;
5047 int len;
5048
5049 if (node == NULL) return;
5050 if (glob) strcat(buf, "(");
5051 cur = node;
5052 while (cur != NULL) {
5053 len = strlen(buf);
5054 if (size - len < 50) {
5055 if ((size - len > 4) && (buf[len - 1] != '.'))
5056 strcat(buf, " ...");
5057 return;
5058 }
5059 switch (cur->type) {
5060 case XML_ELEMENT_NODE:
5061 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
5062 if (size - len < xmlStrlen(cur->ns->prefix) + 10) {
5063 if ((size - len > 4) && (buf[len - 1] != '.'))
5064 strcat(buf, " ...");
5065 return;
5066 }
5067 strcat(buf, (char *) cur->ns->prefix);
5068 strcat(buf, ":");
5069 }
5070 if (size - len < xmlStrlen(cur->name) + 10) {
5071 if ((size - len > 4) && (buf[len - 1] != '.'))
5072 strcat(buf, " ...");
5073 return;
5074 }
5075 strcat(buf, (char *) cur->name);
5076 if (cur->next != NULL)
5077 strcat(buf, " ");
5078 break;
5079 case XML_TEXT_NODE:
5080 if (xmlIsBlankNode(cur))
5081 break;
5082 /* Falls through. */
5083 case XML_CDATA_SECTION_NODE:
5084 case XML_ENTITY_REF_NODE:
5085 strcat(buf, "CDATA");
5086 if (cur->next != NULL)
5087 strcat(buf, " ");
5088 break;
5089 case XML_ATTRIBUTE_NODE:
5090 case XML_DOCUMENT_NODE:
5091 case XML_HTML_DOCUMENT_NODE:
5092 case XML_DOCUMENT_TYPE_NODE:
5093 case XML_DOCUMENT_FRAG_NODE:
5094 case XML_NOTATION_NODE:
5095 case XML_NAMESPACE_DECL:
5096 strcat(buf, "???");
5097 if (cur->next != NULL)
5098 strcat(buf, " ");
5099 break;
5100 case XML_ENTITY_NODE:
5101 case XML_PI_NODE:
5102 case XML_DTD_NODE:
5103 case XML_COMMENT_NODE:
5104 case XML_ELEMENT_DECL:
5105 case XML_ATTRIBUTE_DECL:
5106 case XML_ENTITY_DECL:
5107 case XML_XINCLUDE_START:
5108 case XML_XINCLUDE_END:
5109 break;
5110 }
5111 cur = cur->next;
5112 }
5113 if (glob) strcat(buf, ")");
5114}
5115
5129static int
5130xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child,
5131 xmlElementPtr elemDecl, int warn, xmlNodePtr parent) {
5132 int ret = 1;
5133#ifndef LIBXML_REGEXP_ENABLED
5134 xmlNodePtr repl = NULL, last = NULL, tmp;
5135#endif
5136 xmlNodePtr cur;
5137 xmlElementContentPtr cont;
5138 const xmlChar *name;
5139
5140 if ((elemDecl == NULL) || (parent == NULL) || (ctxt == NULL))
5141 return(-1);
5142 cont = elemDecl->content;
5143 name = elemDecl->name;
5144
5145#ifdef LIBXML_REGEXP_ENABLED
5146 /* Build the regexp associated to the content model */
5147 if (elemDecl->contModel == NULL)
5148 ret = xmlValidBuildContentModel(ctxt, elemDecl);
5149 if (elemDecl->contModel == NULL) {
5150 return(-1);
5151 } else {
5152 xmlRegExecCtxtPtr exec;
5153
5154 if (!xmlRegexpIsDeterminist(elemDecl->contModel)) {
5155 return(-1);
5156 }
5157 ctxt->nodeMax = 0;
5158 ctxt->nodeNr = 0;
5159 ctxt->nodeTab = NULL;
5160 exec = xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL);
5161 if (exec != NULL) {
5162 cur = child;
5163 while (cur != NULL) {
5164 switch (cur->type) {
5165 case XML_ENTITY_REF_NODE:
5166 /*
5167 * Push the current node to be able to roll back
5168 * and process within the entity
5169 */
5170 if ((cur->children != NULL) &&
5171 (cur->children->children != NULL)) {
5172 nodeVPush(ctxt, cur);
5173 cur = cur->children->children;
5174 continue;
5175 }
5176 break;
5177 case XML_TEXT_NODE:
5178 if (xmlIsBlankNode(cur))
5179 break;
5180 ret = 0;
5181 goto fail;
5182 case XML_CDATA_SECTION_NODE:
5183 /* TODO */
5184 ret = 0;
5185 goto fail;
5186 case XML_ELEMENT_NODE:
5187 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
5188 xmlChar fn[50];
5190
5191 fullname = xmlBuildQName(cur->name,
5192 cur->ns->prefix, fn, 50);
5193 if (fullname == NULL) {
5194 ret = -1;
5195 goto fail;
5196 }
5197 ret = xmlRegExecPushString(exec, fullname, NULL);
5198 if ((fullname != fn) && (fullname != cur->name))
5200 } else {
5201 ret = xmlRegExecPushString(exec, cur->name, NULL);
5202 }
5203 break;
5204 default:
5205 break;
5206 }
5207 /*
5208 * Switch to next element
5209 */
5210 cur = cur->next;
5211 while (cur == NULL) {
5212 cur = nodeVPop(ctxt);
5213 if (cur == NULL)
5214 break;
5215 cur = cur->next;
5216 }
5217 }
5218 ret = xmlRegExecPushString(exec, NULL, NULL);
5219fail:
5220 xmlRegFreeExecCtxt(exec);
5221 }
5222 }
5223#else /* LIBXML_REGEXP_ENABLED */
5224 /*
5225 * Allocate the stack
5226 */
5227 ctxt->vstateMax = 8;
5228 ctxt->vstateTab = (xmlValidState *) xmlMalloc(
5229 ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
5230 if (ctxt->vstateTab == NULL) {
5231 xmlVErrMemory(ctxt, "malloc failed");
5232 return(-1);
5233 }
5234 /*
5235 * The first entry in the stack is reserved to the current state
5236 */
5237 ctxt->nodeMax = 0;
5238 ctxt->nodeNr = 0;
5239 ctxt->nodeTab = NULL;
5240 ctxt->vstate = &ctxt->vstateTab[0];
5241 ctxt->vstateNr = 1;
5242 CONT = cont;
5243 NODE = child;
5244 DEPTH = 0;
5245 OCCURS = 0;
5246 STATE = 0;
5247 ret = xmlValidateElementType(ctxt);
5248 if ((ret == -3) && (warn)) {
5249 char expr[5000];
5250 expr[0] = 0;
5251 xmlSnprintfElementContent(expr, 5000, elemDecl->content, 1);
5252 xmlErrValidNode(ctxt, (xmlNodePtr) elemDecl,
5254 "Content model of %s is not deterministic: %s\n",
5256 } else if (ret == -2) {
5257 /*
5258 * An entities reference appeared at this level.
5259 * Build a minimal representation of this node content
5260 * sufficient to run the validation process on it
5261 */
5262 cur = child;
5263 while (cur != NULL) {
5264 switch (cur->type) {
5265 case XML_ENTITY_REF_NODE:
5266 /*
5267 * Push the current node to be able to roll back
5268 * and process within the entity
5269 */
5270 if ((cur->children != NULL) &&
5271 (cur->children->children != NULL)) {
5272 nodeVPush(ctxt, cur);
5273 cur = cur->children->children;
5274 continue;
5275 }
5276 break;
5277 case XML_TEXT_NODE:
5278 if (xmlIsBlankNode(cur))
5279 break;
5280 /* no break on purpose */
5281 case XML_CDATA_SECTION_NODE:
5282 /* no break on purpose */
5283 case XML_ELEMENT_NODE:
5284 /*
5285 * Allocate a new node and minimally fills in
5286 * what's required
5287 */
5288 tmp = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
5289 if (tmp == NULL) {
5290 xmlVErrMemory(ctxt, "malloc failed");
5291 xmlFreeNodeList(repl);
5292 ret = -1;
5293 goto done;
5294 }
5295 tmp->type = cur->type;
5296 tmp->name = cur->name;
5297 tmp->ns = cur->ns;
5298 tmp->next = NULL;
5299 tmp->content = NULL;
5300 if (repl == NULL)
5301 repl = last = tmp;
5302 else {
5303 last->next = tmp;
5304 last = tmp;
5305 }
5306 if (cur->type == XML_CDATA_SECTION_NODE) {
5307 /*
5308 * E59 spaces in CDATA does not match the
5309 * nonterminal S
5310 */
5311 tmp->content = xmlStrdup(BAD_CAST "CDATA");
5312 }
5313 break;
5314 default:
5315 break;
5316 }
5317 /*
5318 * Switch to next element
5319 */
5320 cur = cur->next;
5321 while (cur == NULL) {
5322 cur = nodeVPop(ctxt);
5323 if (cur == NULL)
5324 break;
5325 cur = cur->next;
5326 }
5327 }
5328
5329 /*
5330 * Relaunch the validation
5331 */
5332 ctxt->vstate = &ctxt->vstateTab[0];
5333 ctxt->vstateNr = 1;
5334 CONT = cont;
5335 NODE = repl;
5336 DEPTH = 0;
5337 OCCURS = 0;
5338 STATE = 0;
5339 ret = xmlValidateElementType(ctxt);
5340 }
5341#endif /* LIBXML_REGEXP_ENABLED */
5342 if ((warn) && ((ret != 1) && (ret != -3))) {
5343 if (ctxt != NULL) {
5344 char expr[5000];
5345 char list[5000];
5346
5347 expr[0] = 0;
5348 xmlSnprintfElementContent(&expr[0], 5000, cont, 1);
5349 list[0] = 0;
5350#ifndef LIBXML_REGEXP_ENABLED
5351 if (repl != NULL)
5352 xmlSnprintfElements(&list[0], 5000, repl, 1);
5353 else
5354#endif /* LIBXML_REGEXP_ENABLED */
5355 xmlSnprintfElements(&list[0], 5000, child, 1);
5356
5357 if (name != NULL) {
5358 xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5359 "Element %s content does not follow the DTD, expecting %s, got %s\n",
5361 } else {
5362 xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5363 "Element content does not follow the DTD, expecting %s, got %s\n",
5365 }
5366 } else {
5367 if (name != NULL) {
5368 xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5369 "Element %s content does not follow the DTD\n",
5370 name, NULL, NULL);
5371 } else {
5372 xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5373 "Element content does not follow the DTD\n",
5374 NULL, NULL, NULL);
5375 }
5376 }
5377 ret = 0;
5378 }
5379 if (ret == -3)
5380 ret = 1;
5381
5382#ifndef LIBXML_REGEXP_ENABLED
5383done:
5384 /*
5385 * Deallocate the copy if done, and free up the validation stack
5386 */
5387 while (repl != NULL) {
5388 tmp = repl->next;
5389 xmlFree(repl);
5390 repl = tmp;
5391 }
5392 ctxt->vstateMax = 0;
5393 if (ctxt->vstateTab != NULL) {
5394 xmlFree(ctxt->vstateTab);
5395 ctxt->vstateTab = NULL;
5396 }
5397#endif
5398 ctxt->nodeMax = 0;
5399 ctxt->nodeNr = 0;
5400 if (ctxt->nodeTab != NULL) {
5401 xmlFree(ctxt->nodeTab);
5402 ctxt->nodeTab = NULL;
5403 }
5404 return(ret);
5405
5406}
5407
5418static int
5419xmlValidateOneCdataElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
5420 xmlNodePtr elem) {
5421 int ret = 1;
5422 xmlNodePtr cur, child;
5423
5424 if ((ctxt == NULL) || (doc == NULL) || (elem == NULL) ||
5425 (elem->type != XML_ELEMENT_NODE))
5426 return(0);
5427
5428 child = elem->children;
5429
5430 cur = child;
5431 while (cur != NULL) {
5432 switch (cur->type) {
5433 case XML_ENTITY_REF_NODE:
5434 /*
5435 * Push the current node to be able to roll back
5436 * and process within the entity
5437 */
5438 if ((cur->children != NULL) &&
5439 (cur->children->children != NULL)) {
5440 nodeVPush(ctxt, cur);
5441 cur = cur->children->children;
5442 continue;
5443 }
5444 break;
5445 case XML_COMMENT_NODE:
5446 case XML_PI_NODE:
5447 case XML_TEXT_NODE:
5448 case XML_CDATA_SECTION_NODE:
5449 break;
5450 default:
5451 ret = 0;
5452 goto done;
5453 }
5454 /*
5455 * Switch to next element
5456 */
5457 cur = cur->next;
5458 while (cur == NULL) {
5459 cur = nodeVPop(ctxt);
5460 if (cur == NULL)
5461 break;
5462 cur = cur->next;
5463 }
5464 }
5465done:
5466 ctxt->nodeMax = 0;
5467 ctxt->nodeNr = 0;
5468 if (ctxt->nodeTab != NULL) {
5469 xmlFree(ctxt->nodeTab);
5470 ctxt->nodeTab = NULL;
5471 }
5472 return(ret);
5473}
5474
5475#ifdef LIBXML_REGEXP_ENABLED
5486static int
5487xmlValidateCheckMixed(xmlValidCtxtPtr ctxt,
5488 xmlElementContentPtr cont, const xmlChar *qname) {
5489 const xmlChar *name;
5490 int plen;
5491 name = xmlSplitQName3(qname, &plen);
5492
5493 if (name == NULL) {
5494 while (cont != NULL) {
5495 if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
5496 if ((cont->prefix == NULL) && (xmlStrEqual(cont->name, qname)))
5497 return(1);
5498 } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
5499 (cont->c1 != NULL) &&
5500 (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
5501 if ((cont->c1->prefix == NULL) &&
5502 (xmlStrEqual(cont->c1->name, qname)))
5503 return(1);
5504 } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
5505 (cont->c1 == NULL) ||
5506 (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
5507 xmlErrValid(NULL, XML_DTD_MIXED_CORRUPT,
5508 "Internal: MIXED struct corrupted\n",
5509 NULL);
5510 break;
5511 }
5512 cont = cont->c2;
5513 }
5514 } else {
5515 while (cont != NULL) {
5516 if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
5517 if ((cont->prefix != NULL) &&
5518 (xmlStrncmp(cont->prefix, qname, plen) == 0) &&
5519 (xmlStrEqual(cont->name, name)))
5520 return(1);
5521 } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
5522 (cont->c1 != NULL) &&
5523 (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
5524 if ((cont->c1->prefix != NULL) &&
5525 (xmlStrncmp(cont->c1->prefix, qname, plen) == 0) &&
5526 (xmlStrEqual(cont->c1->name, name)))
5527 return(1);
5528 } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
5529 (cont->c1 == NULL) ||
5530 (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
5531 xmlErrValid(ctxt, XML_DTD_MIXED_CORRUPT,
5532 "Internal: MIXED struct corrupted\n",
5533 NULL);
5534 break;
5535 }
5536 cont = cont->c2;
5537 }
5538 }
5539 return(0);
5540}
5541#endif /* LIBXML_REGEXP_ENABLED */
5542
5555static xmlElementPtr
5556xmlValidGetElemDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
5557 xmlNodePtr elem, int *extsubset) {
5558 xmlElementPtr elemDecl = NULL;
5559 const xmlChar *prefix = NULL;
5560
5561 if ((ctxt == NULL) || (doc == NULL) ||
5562 (elem == NULL) || (elem->name == NULL))
5563 return(NULL);
5564 if (extsubset != NULL)
5565 *extsubset = 0;
5566
5567 /*
5568 * Fetch the declaration for the qualified name
5569 */
5570 if ((elem->ns != NULL) && (elem->ns->prefix != NULL))
5571 prefix = elem->ns->prefix;
5572
5573 if (prefix != NULL) {
5574 elemDecl = xmlGetDtdQElementDesc(doc->intSubset,
5575 elem->name, prefix);
5576 if ((elemDecl == NULL) && (doc->extSubset != NULL)) {
5577 elemDecl = xmlGetDtdQElementDesc(doc->extSubset,
5578 elem->name, prefix);
5579 if ((elemDecl != NULL) && (extsubset != NULL))
5580 *extsubset = 1;
5581 }
5582 }
5583
5584 /*
5585 * Fetch the declaration for the non qualified name
5586 * This is "non-strict" validation should be done on the
5587 * full QName but in that case being flexible makes sense.
5588 */
5589 if (elemDecl == NULL) {
5590 elemDecl = xmlGetDtdElementDesc(doc->intSubset, elem->name);
5591 if ((elemDecl == NULL) && (doc->extSubset != NULL)) {
5592 elemDecl = xmlGetDtdElementDesc(doc->extSubset, elem->name);
5593 if ((elemDecl != NULL) && (extsubset != NULL))
5594 *extsubset = 1;
5595 }
5596 }
5597 if (elemDecl == NULL) {
5598 xmlErrValidNode(ctxt, elem,
5600 "No declaration for element %s\n",
5601 elem->name, NULL, NULL);
5602 }
5603 return(elemDecl);
5604}
5605
5606#ifdef LIBXML_REGEXP_ENABLED
5618int
5619xmlValidatePushElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
5620 xmlNodePtr elem, const xmlChar *qname) {
5621 int ret = 1;
5622 xmlElementPtr eDecl;
5623 int extsubset = 0;
5624
5625 if (ctxt == NULL)
5626 return(0);
5627/* printf("PushElem %s\n", qname); */
5628 if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) {
5629 xmlValidStatePtr state = ctxt->vstate;
5630 xmlElementPtr elemDecl;
5631
5632 /*
5633 * Check the new element against the content model of the new elem.
5634 */
5635 if (state->elemDecl != NULL) {
5636 elemDecl = state->elemDecl;
5637
5638 switch(elemDecl->etype) {
5639 case XML_ELEMENT_TYPE_UNDEFINED:
5640 ret = 0;
5641 break;
5642 case XML_ELEMENT_TYPE_EMPTY:
5643 xmlErrValidNode(ctxt, state->node,
5645 "Element %s was declared EMPTY this one has content\n",
5646 state->node->name, NULL, NULL);
5647 ret = 0;
5648 break;
5649 case XML_ELEMENT_TYPE_ANY:
5650 /* I don't think anything is required then */
5651 break;
5652 case XML_ELEMENT_TYPE_MIXED:
5653 /* simple case of declared as #PCDATA */
5654 if ((elemDecl->content != NULL) &&
5655 (elemDecl->content->type ==
5656 XML_ELEMENT_CONTENT_PCDATA)) {
5657 xmlErrValidNode(ctxt, state->node,
5659 "Element %s was declared #PCDATA but contains non text nodes\n",
5660 state->node->name, NULL, NULL);
5661 ret = 0;
5662 } else {
5663 ret = xmlValidateCheckMixed(ctxt, elemDecl->content,
5664 qname);
5665 if (ret != 1) {
5666 xmlErrValidNode(ctxt, state->node,
5668 "Element %s is not declared in %s list of possible children\n",
5669 qname, state->node->name, NULL);
5670 }
5671 }
5672 break;
5673 case XML_ELEMENT_TYPE_ELEMENT:
5674 /*
5675 * TODO:
5676 * VC: Standalone Document Declaration
5677 * - element types with element content, if white space
5678 * occurs directly within any instance of those types.
5679 */
5680 if (state->exec != NULL) {
5681 ret = xmlRegExecPushString(state->exec, qname, NULL);
5682 if (ret < 0) {
5683 xmlErrValidNode(ctxt, state->node,
5685 "Element %s content does not follow the DTD, Misplaced %s\n",
5686 state->node->name, qname, NULL);
5687 ret = 0;
5688 } else {
5689 ret = 1;
5690 }
5691 }
5692 break;
5693 }
5694 }
5695 }
5696 eDecl = xmlValidGetElemDecl(ctxt, doc, elem, &extsubset);
5697 vstateVPush(ctxt, eDecl, elem);
5698 return(ret);
5699}
5700
5711int
5712xmlValidatePushCData(xmlValidCtxtPtr ctxt, const xmlChar *data, int len) {
5713 int ret = 1;
5714
5715/* printf("CDATA %s %d\n", data, len); */
5716 if (ctxt == NULL)
5717 return(0);
5718 if (len <= 0)
5719 return(ret);
5720 if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) {
5721 xmlValidStatePtr state = ctxt->vstate;
5722 xmlElementPtr elemDecl;
5723
5724 /*
5725 * Check the new element against the content model of the new elem.
5726 */
5727 if (state->elemDecl != NULL) {
5728 elemDecl = state->elemDecl;
5729
5730 switch(elemDecl->etype) {
5731 case XML_ELEMENT_TYPE_UNDEFINED:
5732 ret = 0;
5733 break;
5734 case XML_ELEMENT_TYPE_EMPTY:
5735 xmlErrValidNode(ctxt, state->node,
5737 "Element %s was declared EMPTY this one has content\n",
5738 state->node->name, NULL, NULL);
5739 ret = 0;
5740 break;
5741 case XML_ELEMENT_TYPE_ANY:
5742 break;
5743 case XML_ELEMENT_TYPE_MIXED:
5744 break;
5745 case XML_ELEMENT_TYPE_ELEMENT: {
5746 int i;
5747
5748 for (i = 0;i < len;i++) {
5749 if (!IS_BLANK_CH(data[i])) {
5750 xmlErrValidNode(ctxt, state->node,
5752 "Element %s content does not follow the DTD, Text not allowed\n",
5753 state->node->name, NULL, NULL);
5754 ret = 0;
5755 goto done;
5756 }
5757 }
5758 /*
5759 * TODO:
5760 * VC: Standalone Document Declaration
5761 * element types with element content, if white space
5762 * occurs directly within any instance of those types.
5763 */
5764 break;
5765 }
5766 }
5767 }
5768 }
5769done:
5770 return(ret);
5771}
5772
5784int
5785xmlValidatePopElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc ATTRIBUTE_UNUSED,
5786 xmlNodePtr elem ATTRIBUTE_UNUSED,
5787 const xmlChar *qname ATTRIBUTE_UNUSED) {
5788 int ret = 1;
5789
5790 if (ctxt == NULL)
5791 return(0);
5792/* printf("PopElem %s\n", qname); */
5793 if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) {
5794 xmlValidStatePtr state = ctxt->vstate;
5795 xmlElementPtr elemDecl;
5796
5797 /*
5798 * Check the new element against the content model of the new elem.
5799 */
5800 if (state->elemDecl != NULL) {
5801 elemDecl = state->elemDecl;
5802
5803 if (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT) {
5804 if (state->exec != NULL) {
5805 ret = xmlRegExecPushString(state->exec, NULL, NULL);
5806 if (ret <= 0) {
5807 xmlErrValidNode(ctxt, state->node,
5809 "Element %s content does not follow the DTD, Expecting more children\n",
5810 state->node->name, NULL,NULL);
5811 ret = 0;
5812 } else {
5813 /*
5814 * previous validation errors should not generate
5815 * a new one here
5816 */
5817 ret = 1;
5818 }
5819 }
5820 }
5821 }
5822 vstateVPop(ctxt);
5823 }
5824 return(ret);
5825}
5826#endif /* LIBXML_REGEXP_ENABLED */
5827
5846int
5847xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
5848 xmlNodePtr elem) {
5849 xmlElementPtr elemDecl = NULL;
5850 xmlElementContentPtr cont;
5851 xmlAttributePtr attr;
5852 xmlNodePtr child;
5853 int ret = 1, tmp;
5854 const xmlChar *name;
5855 int extsubset = 0;
5856
5857 CHECK_DTD;
5858
5859 if (elem == NULL) return(0);
5860 switch (elem->type) {
5861 case XML_ATTRIBUTE_NODE:
5862 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5863 "Attribute element not expected\n", NULL, NULL ,NULL);
5864 return(0);
5865 case XML_TEXT_NODE:
5866 if (elem->children != NULL) {
5867 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5868 "Text element has children !\n",
5869 NULL,NULL,NULL);
5870 return(0);
5871 }
5872 if (elem->ns != NULL) {
5873 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5874 "Text element has namespace !\n",
5875 NULL,NULL,NULL);
5876 return(0);
5877 }
5878 if (elem->content == NULL) {
5879 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5880 "Text element has no content !\n",
5881 NULL,NULL,NULL);
5882 return(0);
5883 }
5884 return(1);
5885 case XML_XINCLUDE_START:
5886 case XML_XINCLUDE_END:
5887 return(1);
5888 case XML_CDATA_SECTION_NODE:
5889 case XML_ENTITY_REF_NODE:
5890 case XML_PI_NODE:
5891 case XML_COMMENT_NODE:
5892 return(1);
5893 case XML_ENTITY_NODE:
5894 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5895 "Entity element not expected\n", NULL, NULL ,NULL);
5896 return(0);
5897 case XML_NOTATION_NODE:
5898 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5899 "Notation element not expected\n", NULL, NULL ,NULL);
5900 return(0);
5901 case XML_DOCUMENT_NODE:
5902 case XML_DOCUMENT_TYPE_NODE:
5903 case XML_DOCUMENT_FRAG_NODE:
5904 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5905 "Document element not expected\n", NULL, NULL ,NULL);
5906 return(0);
5907 case XML_HTML_DOCUMENT_NODE:
5908 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5909 "HTML Document not expected\n", NULL, NULL ,NULL);
5910 return(0);
5911 case XML_ELEMENT_NODE:
5912 break;
5913 default:
5914 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5915 "unknown element type\n", NULL, NULL ,NULL);
5916 return(0);
5917 }
5918
5919 /*
5920 * Fetch the declaration
5921 */
5922 elemDecl = xmlValidGetElemDecl(ctxt, doc, elem, &extsubset);
5923 if (elemDecl == NULL)
5924 return(0);
5925
5926 /*
5927 * If vstateNr is not zero that means continuous validation is
5928 * activated, do not try to check the content model at that level.
5929 */
5930 if (ctxt->vstateNr == 0) {
5931 /* Check that the element content matches the definition */
5932 switch (elemDecl->etype) {
5933 case XML_ELEMENT_TYPE_UNDEFINED:
5934 xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ELEM,
5935 "No declaration for element %s\n",
5936 elem->name, NULL, NULL);
5937 return(0);
5938 case XML_ELEMENT_TYPE_EMPTY:
5939 if (elem->children != NULL) {
5940 xmlErrValidNode(ctxt, elem, XML_DTD_NOT_EMPTY,
5941 "Element %s was declared EMPTY this one has content\n",
5942 elem->name, NULL, NULL);
5943 ret = 0;
5944 }
5945 break;
5946 case XML_ELEMENT_TYPE_ANY:
5947 /* I don't think anything is required then */
5948 break;
5949 case XML_ELEMENT_TYPE_MIXED:
5950
5951 /* simple case of declared as #PCDATA */
5952 if ((elemDecl->content != NULL) &&
5953 (elemDecl->content->type == XML_ELEMENT_CONTENT_PCDATA)) {
5954 ret = xmlValidateOneCdataElement(ctxt, doc, elem);
5955 if (!ret) {
5956 xmlErrValidNode(ctxt, elem, XML_DTD_NOT_PCDATA,
5957 "Element %s was declared #PCDATA but contains non text nodes\n",
5958 elem->name, NULL, NULL);
5959 }
5960 break;
5961 }
5962 child = elem->children;
5963 /* Hum, this start to get messy */
5964 while (child != NULL) {
5965 if (child->type == XML_ELEMENT_NODE) {
5966 name = child->name;
5967 if ((child->ns != NULL) && (child->ns->prefix != NULL)) {
5968 xmlChar fn[50];
5970
5971 fullname = xmlBuildQName(child->name, child->ns->prefix,
5972 fn, 50);
5973 if (fullname == NULL)
5974 return(0);
5975 cont = elemDecl->content;
5976 while (cont != NULL) {
5977 if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
5978 if (xmlStrEqual(cont->name, fullname))
5979 break;
5980 } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
5981 (cont->c1 != NULL) &&
5982 (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
5983 if (xmlStrEqual(cont->c1->name, fullname))
5984 break;
5985 } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
5986 (cont->c1 == NULL) ||
5987 (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
5988 xmlErrValid(NULL, XML_DTD_MIXED_CORRUPT,
5989 "Internal: MIXED struct corrupted\n",
5990 NULL);
5991 break;
5992 }
5993 cont = cont->c2;
5994 }
5995 if ((fullname != fn) && (fullname != child->name))
5997 if (cont != NULL)
5998 goto child_ok;
5999 }
6000 cont = elemDecl->content;
6001 while (cont != NULL) {
6002 if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
6003 if (xmlStrEqual(cont->name, name)) break;
6004 } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
6005 (cont->c1 != NULL) &&
6006 (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)) {
6007 if (xmlStrEqual(cont->c1->name, name)) break;
6008 } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
6009 (cont->c1 == NULL) ||
6010 (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)) {
6011 xmlErrValid(ctxt, XML_DTD_MIXED_CORRUPT,
6012 "Internal: MIXED struct corrupted\n",
6013 NULL);
6014 break;
6015 }
6016 cont = cont->c2;
6017 }
6018 if (cont == NULL) {
6019 xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_CHILD,
6020 "Element %s is not declared in %s list of possible children\n",
6021 name, elem->name, NULL);
6022 ret = 0;
6023 }
6024 }
6025child_ok:
6026 child = child->next;
6027 }
6028 break;
6029 case XML_ELEMENT_TYPE_ELEMENT:
6030 if ((doc->standalone == 1) && (extsubset == 1)) {
6031 /*
6032 * VC: Standalone Document Declaration
6033 * - element types with element content, if white space
6034 * occurs directly within any instance of those types.
6035 */
6036 child = elem->children;
6037 while (child != NULL) {
6038 if (child->type == XML_TEXT_NODE) {
6039 const xmlChar *content = child->content;
6040
6041 while (IS_BLANK_CH(*content))
6042 content++;
6043 if (*content == 0) {
6044 xmlErrValidNode(ctxt, elem,
6046"standalone: %s declared in the external subset contains white spaces nodes\n",
6047 elem->name, NULL, NULL);
6048 ret = 0;
6049 break;
6050 }
6051 }
6052 child =child->next;
6053 }
6054 }
6055 child = elem->children;
6056 cont = elemDecl->content;
6057 tmp = xmlValidateElementContent(ctxt, child, elemDecl, 1, elem);
6058 if (tmp <= 0)
6059 ret = tmp;
6060 break;
6061 }
6062 } /* not continuous */
6063
6064 /* [ VC: Required Attribute ] */
6065 attr = elemDecl->attributes;
6066 while (attr != NULL) {
6067 if (attr->def == XML_ATTRIBUTE_REQUIRED) {
6068 int qualified = -1;
6069
6070 if ((attr->prefix == NULL) &&
6071 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) {
6072 xmlNsPtr ns;
6073
6074 ns = elem->nsDef;
6075 while (ns != NULL) {
6076 if (ns->prefix == NULL)
6077 goto found;
6078 ns = ns->next;
6079 }
6080 } else if (xmlStrEqual(attr->prefix, BAD_CAST "xmlns")) {
6081 xmlNsPtr ns;
6082
6083 ns = elem->nsDef;
6084 while (ns != NULL) {
6085 if (xmlStrEqual(attr->name, ns->prefix))
6086 goto found;
6087 ns = ns->next;
6088 }
6089 } else {
6090 xmlAttrPtr attrib;
6091
6092 attrib = elem->properties;
6093 while (attrib != NULL) {
6094 if (xmlStrEqual(attrib->name, attr->name)) {
6095 if (attr->prefix != NULL) {
6096 xmlNsPtr nameSpace = attrib->ns;
6097
6098 if (nameSpace == NULL)
6099 nameSpace = elem->ns;
6100 /*
6101 * qualified names handling is problematic, having a
6102 * different prefix should be possible but DTDs don't
6103 * allow to define the URI instead of the prefix :-(
6104 */
6105 if (nameSpace == NULL) {
6106 if (qualified < 0)
6107 qualified = 0;
6108 } else if (!xmlStrEqual(nameSpace->prefix,
6109 attr->prefix)) {
6110 if (qualified < 1)
6111 qualified = 1;
6112 } else
6113 goto found;
6114 } else {
6115 /*
6116 * We should allow applications to define namespaces
6117 * for their application even if the DTD doesn't
6118 * carry one, otherwise, basically we would always
6119 * break.
6120 */
6121 goto found;
6122 }
6123 }
6124 attrib = attrib->next;
6125 }
6126 }
6127 if (qualified == -1) {
6128 if (attr->prefix == NULL) {
6129 xmlErrValidNode(ctxt, elem, XML_DTD_MISSING_ATTRIBUTE,
6130 "Element %s does not carry attribute %s\n",
6131 elem->name, attr->name, NULL);
6132 ret = 0;
6133 } else {
6134 xmlErrValidNode(ctxt, elem, XML_DTD_MISSING_ATTRIBUTE,
6135 "Element %s does not carry attribute %s:%s\n",
6136 elem->name, attr->prefix,attr->name);
6137 ret = 0;
6138 }
6139 } else if (qualified == 0) {
6140 xmlErrValidWarning(ctxt, elem, XML_DTD_NO_PREFIX,
6141 "Element %s required attribute %s:%s has no prefix\n",
6142 elem->name, attr->prefix, attr->name);
6143 } else if (qualified == 1) {
6144 xmlErrValidWarning(ctxt, elem, XML_DTD_DIFFERENT_PREFIX,
6145 "Element %s required attribute %s:%s has different prefix\n",
6146 elem->name, attr->prefix, attr->name);
6147 }
6148 } else if (attr->def == XML_ATTRIBUTE_FIXED) {
6149 /*
6150 * Special tests checking #FIXED namespace declarations
6151 * have the right value since this is not done as an
6152 * attribute checking
6153 */
6154 if ((attr->prefix == NULL) &&
6155 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) {
6156 xmlNsPtr ns;
6157
6158 ns = elem->nsDef;
6159 while (ns != NULL) {
6160 if (ns->prefix == NULL) {
6161 if (!xmlStrEqual(attr->defaultValue, ns->href)) {
6162 xmlErrValidNode(ctxt, elem,
6164 "Element %s namespace name for default namespace does not match the DTD\n",
6165 elem->name, NULL, NULL);
6166 ret = 0;
6167 }
6168 goto found;
6169 }
6170 ns = ns->next;
6171 }
6172 } else if (xmlStrEqual(attr->prefix, BAD_CAST "xmlns")) {
6173 xmlNsPtr ns;
6174
6175 ns = elem->nsDef;
6176 while (ns != NULL) {
6177 if (xmlStrEqual(attr->name, ns->prefix)) {
6178 if (!xmlStrEqual(attr->defaultValue, ns->href)) {
6179 xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE,
6180 "Element %s namespace name for %s does not match the DTD\n",
6181 elem->name, ns->prefix, NULL);
6182 ret = 0;
6183 }
6184 goto found;
6185 }
6186 ns = ns->next;
6187 }
6188 }
6189 }
6190found:
6191 attr = attr->nexth;
6192 }
6193 return(ret);
6194}
6195
6210int
6211xmlValidateRoot(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6212 xmlNodePtr root;
6213 int ret;
6214
6215 if (doc == NULL) return(0);
6216
6217 root = xmlDocGetRootElement(doc);
6218 if ((root == NULL) || (root->name == NULL)) {
6219 xmlErrValid(ctxt, XML_DTD_NO_ROOT,
6220 "no root element\n", NULL);
6221 return(0);
6222 }
6223
6224 /*
6225 * When doing post validation against a separate DTD, those may
6226 * no internal subset has been generated
6227 */
6228 if ((doc->intSubset != NULL) &&
6229 (doc->intSubset->name != NULL)) {
6230 /*
6231 * Check first the document root against the NQName
6232 */
6233 if (!xmlStrEqual(doc->intSubset->name, root->name)) {
6234 if ((root->ns != NULL) && (root->ns->prefix != NULL)) {
6235 xmlChar fn[50];
6237
6238 fullname = xmlBuildQName(root->name, root->ns->prefix, fn, 50);
6239 if (fullname == NULL) {
6240 xmlVErrMemory(ctxt, NULL);
6241 return(0);
6242 }
6243 ret = xmlStrEqual(doc->intSubset->name, fullname);
6244 if ((fullname != fn) && (fullname != root->name))
6246 if (ret == 1)
6247 goto name_ok;
6248 }
6249 if ((xmlStrEqual(doc->intSubset->name, BAD_CAST "HTML")) &&
6250 (xmlStrEqual(root->name, BAD_CAST "html")))
6251 goto name_ok;
6252 xmlErrValidNode(ctxt, root, XML_DTD_ROOT_NAME,
6253 "root and DTD name do not match '%s' and '%s'\n",
6254 root->name, doc->intSubset->name, NULL);
6255 return(0);
6256 }
6257 }
6258name_ok:
6259 return(1);
6260}
6261
6262
6274int
6275xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr root) {
6276 xmlNodePtr elem;
6277 xmlAttrPtr attr;
6278 xmlNsPtr ns;
6279 const xmlChar *value;
6280 int ret = 1;
6281
6282 if (root == NULL) return(0);
6283
6284 CHECK_DTD;
6285
6286 elem = root;
6287 while (1) {
6288 ret &= xmlValidateOneElement(ctxt, doc, elem);
6289
6290 if (elem->type == XML_ELEMENT_NODE) {
6291 attr = elem->properties;
6292 while (attr != NULL) {
6293 value = xmlNodeListGetString(doc, attr->children, 0);
6294 ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value);
6295 if (value != NULL)
6296 xmlFree((char *)value);
6297 attr= attr->next;
6298 }
6299
6300 ns = elem->nsDef;
6301 while (ns != NULL) {
6302 if (elem->ns == NULL)
6303 ret &= xmlValidateOneNamespace(ctxt, doc, elem, NULL,
6304 ns, ns->href);
6305 else
6306 ret &= xmlValidateOneNamespace(ctxt, doc, elem,
6307 elem->ns->prefix, ns,
6308 ns->href);
6309 ns = ns->next;
6310 }
6311
6312 if (elem->children != NULL) {
6313 elem = elem->children;
6314 continue;
6315 }
6316 }
6317
6318 while (1) {
6319 if (elem == root)
6320 goto done;
6321 if (elem->next != NULL)
6322 break;
6323 elem = elem->parent;
6324 }
6325 elem = elem->next;
6326 }
6327
6328done:
6329 return(ret);
6330}
6331
6339static void
6340xmlValidateRef(xmlRefPtr ref, xmlValidCtxtPtr ctxt,
6341 const xmlChar *name) {
6342 xmlAttrPtr id;
6343 xmlAttrPtr attr;
6344
6345 if (ref == NULL)
6346 return;
6347 if ((ref->attr == NULL) && (ref->name == NULL))
6348 return;
6349 attr = ref->attr;
6350 if (attr == NULL) {
6351 xmlChar *dup, *str = NULL, *cur, save;
6352
6353 dup = xmlStrdup(name);
6354 if (dup == NULL) {
6355 ctxt->valid = 0;
6356 return;
6357 }
6358 cur = dup;
6359 while (*cur != 0) {
6360 str = cur;
6361 while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
6362 save = *cur;
6363 *cur = 0;
6364 id = xmlGetID(ctxt->doc, str);
6365 if (id == NULL) {
6366 xmlErrValidNodeNr(ctxt, NULL, XML_DTD_UNKNOWN_ID,
6367 "attribute %s line %d references an unknown ID \"%s\"\n",
6368 ref->name, ref->lineno, str);
6369 ctxt->valid = 0;
6370 }
6371 if (save == 0)
6372 break;
6373 *cur = save;
6374 while (IS_BLANK_CH(*cur)) cur++;
6375 }
6376 xmlFree(dup);
6377 } else if (attr->atype == XML_ATTRIBUTE_IDREF) {
6378 id = xmlGetID(ctxt->doc, name);
6379 if (id == NULL) {
6380 xmlErrValidNode(ctxt, attr->parent, XML_DTD_UNKNOWN_ID,
6381 "IDREF attribute %s references an unknown ID \"%s\"\n",
6382 attr->name, name, NULL);
6383 ctxt->valid = 0;
6384 }
6385 } else if (attr->atype == XML_ATTRIBUTE_IDREFS) {
6386 xmlChar *dup, *str = NULL, *cur, save;
6387
6388 dup = xmlStrdup(name);
6389 if (dup == NULL) {
6390 xmlVErrMemory(ctxt, "IDREFS split");
6391 ctxt->valid = 0;
6392 return;
6393 }
6394 cur = dup;
6395 while (*cur != 0) {
6396 str = cur;
6397 while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
6398 save = *cur;
6399 *cur = 0;
6400 id = xmlGetID(ctxt->doc, str);
6401 if (id == NULL) {
6402 xmlErrValidNode(ctxt, attr->parent, XML_DTD_UNKNOWN_ID,
6403 "IDREFS attribute %s references an unknown ID \"%s\"\n",
6404 attr->name, str, NULL);
6405 ctxt->valid = 0;
6406 }
6407 if (save == 0)
6408 break;
6409 *cur = save;
6410 while (IS_BLANK_CH(*cur)) cur++;
6411 }
6412 xmlFree(dup);
6413 }
6414}
6415
6423static int
6424xmlWalkValidateList(const void *data, void *user)
6425{
6427 xmlValidateRef((xmlRefPtr)data, memo->ctxt, memo->name);
6428 return 1;
6429}
6430
6438static void
6439xmlValidateCheckRefCallback(void *payload, void *data, const xmlChar *name) {
6440 xmlListPtr ref_list = (xmlListPtr) payload;
6442 xmlValidateMemo memo;
6443
6444 if (ref_list == NULL)
6445 return;
6446 memo.ctxt = ctxt;
6447 memo.name = name;
6448
6449 xmlListWalk(ref_list, xmlWalkValidateList, &memo);
6450
6451}
6452
6468int
6469xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6471 unsigned int save;
6472
6473 if (ctxt == NULL)
6474 return(0);
6475 if (doc == NULL) {
6476 xmlErrValid(ctxt, XML_DTD_NO_DOC,
6477 "xmlValidateDocumentFinal: doc == NULL\n", NULL);
6478 return(0);
6479 }
6480
6481 /* trick to get correct line id report */
6482 save = ctxt->flags;
6483 ctxt->flags &= ~XML_VCTXT_USE_PCTXT;
6484
6485 /*
6486 * Check all the NOTATION/NOTATIONS attributes
6487 */
6488 /*
6489 * Check all the ENTITY/ENTITIES attributes definition for validity
6490 */
6491 /*
6492 * Check all the IDREF/IDREFS attributes definition for validity
6493 */
6494 table = (xmlRefTablePtr) doc->refs;
6495 ctxt->doc = doc;
6496 ctxt->valid = 1;
6497 xmlHashScan(table, xmlValidateCheckRefCallback, ctxt);
6498
6499 ctxt->flags = save;
6500 return(ctxt->valid);
6501}
6502
6519int
6520xmlValidateDtd(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd) {
6521 int ret;
6522 xmlDtdPtr oldExt, oldInt;
6523 xmlNodePtr root;
6524
6525 if (dtd == NULL) return(0);
6526 if (doc == NULL) return(0);
6527 oldExt = doc->extSubset;
6528 oldInt = doc->intSubset;
6529 doc->extSubset = dtd;
6530 doc->intSubset = NULL;
6531 ret = xmlValidateRoot(ctxt, doc);
6532 if (ret == 0) {
6533 doc->extSubset = oldExt;
6534 doc->intSubset = oldInt;
6535 return(ret);
6536 }
6537 if (doc->ids != NULL) {
6538 xmlFreeIDTable(doc->ids);
6539 doc->ids = NULL;
6540 }
6541 if (doc->refs != NULL) {
6542 xmlFreeRefTable(doc->refs);
6543 doc->refs = NULL;
6544 }
6545 root = xmlDocGetRootElement(doc);
6546 ret = xmlValidateElement(ctxt, doc, root);
6547 ret &= xmlValidateDocumentFinal(ctxt, doc);
6548 doc->extSubset = oldExt;
6549 doc->intSubset = oldInt;
6550 return(ret);
6551}
6552
6553static void
6554xmlValidateNotationCallback(void *payload, void *data,
6555 const xmlChar *name ATTRIBUTE_UNUSED) {
6556 xmlEntityPtr cur = (xmlEntityPtr) payload;
6558 if (cur == NULL)
6559 return;
6561 xmlChar *notation = cur->content;
6562
6563 if (notation != NULL) {
6564 int ret;
6565
6566 ret = xmlValidateNotationUse(ctxt, cur->doc, notation);
6567 if (ret != 1) {
6568 ctxt->valid = 0;
6569 }
6570 }
6571 }
6572}
6573
6574static void
6575xmlValidateAttributeCallback(void *payload, void *data,
6576 const xmlChar *name ATTRIBUTE_UNUSED) {
6577 xmlAttributePtr cur = (xmlAttributePtr) payload;
6579 int ret;
6580 xmlDocPtr doc;
6581 xmlElementPtr elem = NULL;
6582
6583 if (cur == NULL)
6584 return;
6585 switch (cur->atype) {
6586 case XML_ATTRIBUTE_CDATA:
6587 case XML_ATTRIBUTE_ID:
6588 case XML_ATTRIBUTE_IDREF :
6589 case XML_ATTRIBUTE_IDREFS:
6590 case XML_ATTRIBUTE_NMTOKEN:
6591 case XML_ATTRIBUTE_NMTOKENS:
6592 case XML_ATTRIBUTE_ENUMERATION:
6593 break;
6594 case XML_ATTRIBUTE_ENTITY:
6595 case XML_ATTRIBUTE_ENTITIES:
6596 case XML_ATTRIBUTE_NOTATION:
6597 if (cur->defaultValue != NULL) {
6598
6599 ret = xmlValidateAttributeValue2(ctxt, ctxt->doc, cur->name,
6600 cur->atype, cur->defaultValue);
6601 if ((ret == 0) && (ctxt->valid == 1))
6602 ctxt->valid = 0;
6603 }
6604 if (cur->tree != NULL) {
6605 xmlEnumerationPtr tree = cur->tree;
6606 while (tree != NULL) {
6607 ret = xmlValidateAttributeValue2(ctxt, ctxt->doc,
6608 cur->name, cur->atype, tree->name);
6609 if ((ret == 0) && (ctxt->valid == 1))
6610 ctxt->valid = 0;
6611 tree = tree->next;
6612 }
6613 }
6614 }
6615 if (cur->atype == XML_ATTRIBUTE_NOTATION) {
6616 doc = cur->doc;
6617 if (cur->elem == NULL) {
6618 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
6619 "xmlValidateAttributeCallback(%s): internal error\n",
6620 (const char *) cur->name);
6621 return;
6622 }
6623
6624 if (doc != NULL)
6625 elem = xmlGetDtdElementDesc(doc->intSubset, cur->elem);
6626 if ((elem == NULL) && (doc != NULL))
6627 elem = xmlGetDtdElementDesc(doc->extSubset, cur->elem);
6628 if ((elem == NULL) && (cur->parent != NULL) &&
6629 (cur->parent->type == XML_DTD_NODE))
6630 elem = xmlGetDtdElementDesc((xmlDtdPtr) cur->parent, cur->elem);
6631 if (elem == NULL) {
6632 xmlErrValidNode(ctxt, NULL, XML_DTD_UNKNOWN_ELEM,
6633 "attribute %s: could not find decl for element %s\n",
6634 cur->name, cur->elem, NULL);
6635 return;
6636 }
6637 if (elem->etype == XML_ELEMENT_TYPE_EMPTY) {
6638 xmlErrValidNode(ctxt, NULL, XML_DTD_EMPTY_NOTATION,
6639 "NOTATION attribute %s declared for EMPTY element %s\n",
6640 cur->name, cur->elem, NULL);
6641 ctxt->valid = 0;
6642 }
6643 }
6644}
6645
6663int
6664xmlValidateDtdFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6665 xmlDtdPtr dtd;
6667 xmlEntitiesTablePtr entities;
6668
6669 if ((doc == NULL) || (ctxt == NULL)) return(0);
6670 if ((doc->intSubset == NULL) && (doc->extSubset == NULL))
6671 return(0);
6672 ctxt->doc = doc;
6673 ctxt->valid = 1;
6674 dtd = doc->intSubset;
6675 if ((dtd != NULL) && (dtd->attributes != NULL)) {
6676 table = (xmlAttributeTablePtr) dtd->attributes;
6677 xmlHashScan(table, xmlValidateAttributeCallback, ctxt);
6678 }
6679 if ((dtd != NULL) && (dtd->entities != NULL)) {
6680 entities = (xmlEntitiesTablePtr) dtd->entities;
6681 xmlHashScan(entities, xmlValidateNotationCallback, ctxt);
6682 }
6683 dtd = doc->extSubset;
6684 if ((dtd != NULL) && (dtd->attributes != NULL)) {
6685 table = (xmlAttributeTablePtr) dtd->attributes;
6686 xmlHashScan(table, xmlValidateAttributeCallback, ctxt);
6687 }
6688 if ((dtd != NULL) && (dtd->entities != NULL)) {
6689 entities = (xmlEntitiesTablePtr) dtd->entities;
6690 xmlHashScan(entities, xmlValidateNotationCallback, ctxt);
6691 }
6692 return(ctxt->valid);
6693}
6694
6709int
6710xmlValidateDocument(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6711 int ret;
6712 xmlNodePtr root;
6713
6714 if (doc == NULL)
6715 return(0);
6716 if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) {
6717 xmlErrValid(ctxt, XML_DTD_NO_DTD,
6718 "no DTD found!\n", NULL);
6719 return(0);
6720 }
6721 if ((doc->intSubset != NULL) && ((doc->intSubset->SystemID != NULL) ||
6722 (doc->intSubset->ExternalID != NULL)) && (doc->extSubset == NULL)) {
6723 xmlChar *sysID;
6724 if (doc->intSubset->SystemID != NULL) {
6725 sysID = xmlBuildURI(doc->intSubset->SystemID,
6726 doc->URL);
6727 if (sysID == NULL) {
6728 xmlErrValid(ctxt, XML_DTD_LOAD_ERROR,
6729 "Could not build URI for external subset \"%s\"\n",
6730 (const char *) doc->intSubset->SystemID);
6731 return 0;
6732 }
6733 } else
6734 sysID = NULL;
6735 doc->extSubset = xmlParseDTD(doc->intSubset->ExternalID,
6736 (const xmlChar *)sysID);
6737 if (sysID != NULL)
6738 xmlFree(sysID);
6739 if (doc->extSubset == NULL) {
6740 if (doc->intSubset->SystemID != NULL) {
6741 xmlErrValid(ctxt, XML_DTD_LOAD_ERROR,
6742 "Could not load the external subset \"%s\"\n",
6743 (const char *) doc->intSubset->SystemID);
6744 } else {
6745 xmlErrValid(ctxt, XML_DTD_LOAD_ERROR,
6746 "Could not load the external subset \"%s\"\n",
6747 (const char *) doc->intSubset->ExternalID);
6748 }
6749 return(0);
6750 }
6751 }
6752
6753 if (doc->ids != NULL) {
6754 xmlFreeIDTable(doc->ids);
6755 doc->ids = NULL;
6756 }
6757 if (doc->refs != NULL) {
6758 xmlFreeRefTable(doc->refs);
6759 doc->refs = NULL;
6760 }
6761 ret = xmlValidateDtdFinal(ctxt, doc);
6762 if (!xmlValidateRoot(ctxt, doc)) return(0);
6763
6764 root = xmlDocGetRootElement(doc);
6765 ret &= xmlValidateElement(ctxt, doc, root);
6766 ret &= xmlValidateDocumentFinal(ctxt, doc);
6767 return(ret);
6768}
6769
6770/************************************************************************
6771 * *
6772 * Routines for dynamic validation editing *
6773 * *
6774 ************************************************************************/
6775
6788int
6789xmlValidGetPotentialChildren(xmlElementContent *ctree,
6790 const xmlChar **names,
6791 int *len, int max) {
6792 int i;
6793
6794 if ((ctree == NULL) || (names == NULL) || (len == NULL))
6795 return(-1);
6796 if (*len >= max) return(*len);
6797
6798 switch (ctree->type) {
6799 case XML_ELEMENT_CONTENT_PCDATA:
6800 for (i = 0; i < *len;i++)
6801 if (xmlStrEqual(BAD_CAST "#PCDATA", names[i])) return(*len);
6802 names[(*len)++] = BAD_CAST "#PCDATA";
6803 break;
6804 case XML_ELEMENT_CONTENT_ELEMENT:
6805 for (i = 0; i < *len;i++)
6806 if (xmlStrEqual(ctree->name, names[i])) return(*len);
6807 names[(*len)++] = ctree->name;
6808 break;
6809 case XML_ELEMENT_CONTENT_SEQ:
6810 xmlValidGetPotentialChildren(ctree->c1, names, len, max);
6811 xmlValidGetPotentialChildren(ctree->c2, names, len, max);
6812 break;
6813 case XML_ELEMENT_CONTENT_OR:
6814 xmlValidGetPotentialChildren(ctree->c1, names, len, max);
6815 xmlValidGetPotentialChildren(ctree->c2, names, len, max);
6816 break;
6817 }
6818
6819 return(*len);
6820}
6821
6822/*
6823 * Dummy function to suppress messages while we try out valid elements
6824 */
6825static void xmlNoValidityErr(void *ctx ATTRIBUTE_UNUSED,
6826 const char *msg ATTRIBUTE_UNUSED, ...) {
6827 return;
6828}
6829
6855int
6856xmlValidGetValidElements(xmlNode *prev, xmlNode *next, const xmlChar **names,
6857 int max) {
6858 xmlValidCtxt vctxt;
6859 int nb_valid_elements = 0;
6860 const xmlChar *elements[256]={0};
6861 int nb_elements = 0, i;
6862 const xmlChar *name;
6863
6864 xmlNode *ref_node;
6865 xmlNode *parent;
6866 xmlNode *test_node;
6867
6868 xmlNode *prev_next;
6869 xmlNode *next_prev;
6870 xmlNode *parent_childs;
6871 xmlNode *parent_last;
6872
6873 xmlElement *element_desc;
6874
6875 if (prev == NULL && next == NULL)
6876 return(-1);
6877
6878 if (names == NULL) return(-1);
6879 if (max <= 0) return(-1);
6880
6881 memset(&vctxt, 0, sizeof (xmlValidCtxt));
6882 vctxt.error = xmlNoValidityErr; /* this suppresses err/warn output */
6883
6884 nb_valid_elements = 0;
6885 ref_node = prev ? prev : next;
6886 parent = ref_node->parent;
6887
6888 /*
6889 * Retrieves the parent element declaration
6890 */
6891 element_desc = xmlGetDtdElementDesc(parent->doc->intSubset,
6892 parent->name);
6893 if ((element_desc == NULL) && (parent->doc->extSubset != NULL))
6894 element_desc = xmlGetDtdElementDesc(parent->doc->extSubset,
6895 parent->name);
6896 if (element_desc == NULL) return(-1);
6897
6898 /*
6899 * Do a backup of the current tree structure
6900 */
6901 prev_next = prev ? prev->next : NULL;
6902 next_prev = next ? next->prev : NULL;
6903 parent_childs = parent->children;
6904 parent_last = parent->last;
6905
6906 /*
6907 * Creates a dummy node and insert it into the tree
6908 */
6909 test_node = xmlNewDocNode (ref_node->doc, NULL, BAD_CAST "<!dummy?>", NULL);
6910 if (test_node == NULL)
6911 return(-1);
6912
6913 test_node->parent = parent;
6914 test_node->prev = prev;
6915 test_node->next = next;
6916 name = test_node->name;
6917
6918 if (prev) prev->next = test_node;
6919 else parent->children = test_node;
6920
6921 if (next) next->prev = test_node;
6922 else parent->last = test_node;
6923
6924 /*
6925 * Insert each potential child node and check if the parent is
6926 * still valid
6927 */
6928 nb_elements = xmlValidGetPotentialChildren(element_desc->content,
6929 elements, &nb_elements, 256);
6930
6931 for (i = 0;i < nb_elements;i++) {
6932 test_node->name = elements[i];
6933 if (xmlValidateOneElement(&vctxt, parent->doc, parent)) {
6934 int j;
6935
6936 for (j = 0; j < nb_valid_elements;j++)
6937 if (xmlStrEqual(elements[i], names[j])) break;
6938 names[nb_valid_elements++] = elements[i];
6939 if (nb_valid_elements >= max) break;
6940 }
6941 }
6942
6943 /*
6944 * Restore the tree structure
6945 */
6946 if (prev) prev->next = prev_next;
6947 if (next) next->prev = next_prev;
6948 parent->children = parent_childs;
6949 parent->last = parent_last;
6950
6951 /*
6952 * Free up the dummy node
6953 */
6954 test_node->name = name;
6955 xmlFreeNode(test_node);
6956
6957 return(nb_valid_elements);
6958}
6959#endif /* LIBXML_VALID_ENABLED */
#define MAX_RECURSE
static int state
Definition: maze.c:121
#define msg(x)
Definition: auth_time.c:54
#define NODE
Definition: text.h:17
void user(int argc, const char *argv[])
Definition: cmds.c:1350
struct _root root
struct _tree tree
r l[0]
Definition: byte_order.h:168
Definition: list.h:37
#define NULL
Definition: types.h:112
#define IS_BLANK(c)
Definition: attributes.c:45
content
Definition: atl_ax.c:994
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
return ret
Definition: mutex.c:146
r parent
Definition: btrfs.c:3010
char ** glob(const char *v)
Definition: fake.c:36
FxCollectionEntry * cur
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLenum src
Definition: glext.h:6340
GLuint GLuint * names
Definition: glext.h:11545
GLsizeiptr size
Definition: glext.h:5919
const GLubyte * c
Definition: glext.h:8905
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLenum dst
Definition: glext.h:6340
GLuint GLfloat * val
Definition: glext.h:7180
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define ATTRIBUTE_UNUSED
Definition: i386-dis.c:36
@ extra
Definition: id3.c:95
#define dup
Definition: syshdrs.h:51
XMLPUBFUN xmlEntityPtr xmlGetDocEntity(const xmlDoc *doc, const xmlChar *name)
@ XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
Definition: entities.h:29
xmlEntitiesTable * xmlEntitiesTablePtr
Definition: entities.h:71
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
static BYTE int2[]
Definition: cert.c:3204
const char * fullname
Definition: shader.c:1766
static UINT UINT last
Definition: font.c:45
#define child_ok
Definition: debugger.c:37
static const struct access_res create[16]
Definition: package.c:7505
static size_t elem
Definition: string.c:71
static HWND child
Definition: cursoricon.c:298
#define IS_COMBINING(c)
#define IS_DIGIT(c)
#define IS_EXTENDER(c)
#define IS_LETTER(c)
XML_DEPRECATED XMLPUBFUN int xmlStringCurrentChar(xmlParserCtxtPtr ctxt, const xmlChar *cur, int *len)
#define IS_BLANK_CH(c)
static unsigned __int64 next
Definition: rand_nt.c:6
#define warn(...)
#define err(...)
const WCHAR * str
#define ID
Definition: ruserpass.c:36
strcat
Definition: string.h:92
int xmlDictOwns(xmlDictPtr dict, const xmlChar *str)
Definition: dict.c:376
const xmlChar * xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len)
Definition: dict.c:824
xmlReallocFunc xmlRealloc
Definition: globals.c:214
xmlFreeFunc xmlFree
Definition: globals.c:184
xmlMallocFunc xmlMalloc
Definition: globals.c:193
void xmlHashScan(xmlHashTablePtr hash, xmlHashScanner scan, void *data)
Definition: hash.c:898
void xmlHashFree(xmlHashTablePtr hash, xmlHashDeallocator dealloc)
Definition: hash.c:229
void * xmlHashLookup(xmlHashTablePtr hash, const xmlChar *key)
Definition: hash.c:739
void * xmlHashLookup2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2)
Definition: hash.c:754
int xmlHashRemoveEntry(xmlHashTablePtr hash, const xmlChar *key, xmlHashDeallocator dealloc)
Definition: hash.c:1102
int xmlHashRemoveEntry2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, xmlHashDeallocator dealloc)
Definition: hash.c:1121
int xmlHashAddEntry(xmlHashTablePtr hash, const xmlChar *key, void *payload)
Definition: hash.c:621
int xmlHashUpdateEntry(xmlHashTablePtr hash, const xmlChar *key, void *payload, xmlHashDeallocator dealloc)
Definition: hash.c:678
xmlHashTablePtr xmlHashCopy(xmlHashTablePtr hash, xmlHashCopier copy)
Definition: hash.c:1050
int xmlHashAddEntry2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, void *payload)
Definition: hash.c:639
int xmlHashAddEntry3(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, const xmlChar *key3, void *payload)
Definition: hash.c:659
xmlHashTablePtr xmlHashCreateDict(int size, xmlDictPtr dict)
Definition: hash.c:209
void * xmlHashLookup3(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, const xmlChar *key3)
Definition: hash.c:806
void xmlHashScan3(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, const xmlChar *key3, xmlHashScanner scan, void *data)
Definition: hash.c:969
XMLPUBFUN void xmlListWalk(xmlListPtr l, xmlListWalker walker, void *user)
Definition: list.c:676
xmlList * xmlListPtr
Definition: list.h:24
XMLPUBFUN int xmlListAppend(xmlListPtr l, void *data)
Definition: list.c:305
XMLPUBFUN void * xmlLinkGetData(xmlLinkPtr lk)
Definition: list.c:604
XMLPUBFUN int xmlListRemoveFirst(xmlListPtr l, void *data)
Definition: list.c:353
XMLPUBFUN void xmlListDelete(xmlListPtr l)
Definition: list.c:333
XMLPUBFUN xmlListPtr xmlListCreate(xmlListDeallocator deallocator, xmlListDataCompare compare)
Definition: list.c:188
XMLPUBFUN int xmlListEmpty(xmlListPtr l)
Definition: list.c:446
@ XML_PARSE_READER
Definition: parser.h:173
XML_HIDDEN void __xmlRaiseError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel, void *data, void *ctx, void *nod, int domain, int code, xmlErrorLevel level, const char *file, int line, const char *str1, const char *str2, const char *str3, int int1, int col, const char *msg,...) LIBXML_ATTR_FORMAT(16
XML_HIDDEN void xmlParserErrors const char const xmlChar const xmlChar * str2
Definition: parser.h:35
XML_HIDDEN void xmlParserErrors const char const xmlChar * str1
Definition: parser.h:35
#define XML_VCTXT_USE_PCTXT
Definition: parser.h:18
#define memset(x, y, z)
Definition: compat.h:39
Definition: userinit.h:57
Definition: dict.c:59
Definition: list.c:39
Definition: cookie.c:202
WCHAR * name
Definition: cookie.c:203
Definition: tftpd.h:126
char * name
Definition: compiler.c:66
struct define * next
Definition: compiler.c:65
Definition: query.h:86
Definition: fatfs.h:133
Definition: name.c:39
WCHAR * name
Definition: name.c:42
Definition: mxnamespace.c:38
BSTR prefix
Definition: mxnamespace.c:39
Definition: send.c:48
char name[1]
Definition: send.c:52
Definition: tools.h:99
xmlListPtr l
Definition: valid.c:2755
xmlAttrPtr ap
Definition: valid.c:2756
xmlValidCtxtPtr ctxt
Definition: valid.c:2763
const xmlChar * name
Definition: valid.c:2764
#define max(a, b)
Definition: svc.c:63
Character const *const prefix
Definition: tempnam.cpp:195
Definition: dlist.c:348
Definition: pdh_main.c:96
XMLPUBFUN xmlChar * xmlBuildURI(const xmlChar *URI, const xmlChar *base)
Definition: uri.c:1902
int xmlIsRef(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr)
Definition: valid.c:2967
static int xmlIsStreaming(xmlValidCtxtPtr ctxt)
Definition: valid.c:2471
static int xmlWalkRemoveRef(const void *data, void *user)
Definition: valid.c:2807
static void xmlVErrMemory(xmlValidCtxtPtr ctxt, const char *extra)
Definition: valid.c:56
#define DICT_FREE(str)
Definition: valid.c:2436
xmlRemoveMemo * xmlRemoveMemoPtr
Definition: valid.c:2759
int xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr)
Definition: valid.c:2619
void xmlSnprintfElementContent(char *buf, int size, xmlElementContentPtr content, int englob)
Definition: valid.c:1130
static void xmlFreeIDTableEntry(void *id, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: valid.c:2590
xmlValidateMemo * xmlValidateMemoPtr
Definition: valid.c:2767
static int xmlDummyCompare(const void *data0 ATTRIBUTE_UNUSED, const void *data1 ATTRIBUTE_UNUSED)
Definition: valid.c:2828
static xmlElementPtr xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name, int create)
Definition: valid.c:3132
xmlAttributePtr xmlGetDtdQAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name, const xmlChar *prefix)
Definition: valid.c:3267
xmlElementContentPtr xmlCopyElementContent(xmlElementContentPtr cur)
Definition: valid.c:922
void xmlFreeIDTable(xmlIDTablePtr table)
Definition: valid.c:2601
static void xmlFreeID(xmlIDPtr id)
Definition: valid.c:2489
xmlNotationPtr xmlAddNotationDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name, const xmlChar *PublicID, const xmlChar *SystemID)
Definition: valid.c:2239
static void xmlFreeNotation(xmlNotationPtr nota)
Definition: valid.c:2214
xmlElementPtr xmlGetDtdQElementDesc(xmlDtdPtr dtd, const xmlChar *name, const xmlChar *prefix)
Definition: valid.c:3206
xmlEnumerationPtr xmlCreateEnumeration(const xmlChar *name)
Definition: valid.c:1640
struct xmlValidateMemo_t xmlValidateMemo
xmlAttributePtr xmlGetDtdAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name)
Definition: valid.c:3230
xmlIDPtr xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr)
Definition: valid.c:2517
void xmlFreeEnumeration(xmlEnumerationPtr cur)
Definition: valid.c:1662
xmlElementContentPtr xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur)
Definition: valid.c:840
xmlElementContentPtr xmlNewDocElementContent(xmlDocPtr doc, const xmlChar *name, xmlElementContentType type)
Definition: valid.c:753
static void xmlFreeElementTableEntry(void *elem, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: valid.c:1475
void xmlFreeDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur)
Definition: valid.c:934
void xmlFreeRefTable(xmlRefTablePtr table)
Definition: valid.c:2948
static void xmlFreeRefTableEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: valid.c:2793
void xmlFreeNotationTable(xmlNotationTablePtr table)
Definition: valid.c:2316
static void xmlFreeElement(xmlElementPtr elem)
Definition: valid.c:1234
int xmlRemoveRef(xmlDocPtr doc, xmlAttrPtr attr)
Definition: valid.c:3009
xmlElementContentPtr xmlNewElementContent(const xmlChar *name, xmlElementContentType type)
Definition: valid.c:826
xmlListPtr xmlGetRefs(xmlDocPtr doc, const xmlChar *ID)
Definition: valid.c:3067
int xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr)
Definition: valid.c:2680
xmlElementPtr xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name, xmlElementTypeVal type, xmlElementContentPtr content)
Definition: valid.c:1263
void xmlFreeElementContent(xmlElementContentPtr cur)
Definition: valid.c:1000
void xmlFreeElementTable(xmlElementTablePtr table)
Definition: valid.c:1486
xmlNotationPtr xmlGetDtdNotationDesc(xmlDtdPtr dtd, const xmlChar *name)
Definition: valid.c:3289
int xmlIsMixedElement(xmlDocPtr doc, const xmlChar *name)
Definition: valid.c:3345
static void xmlFreeAttributeTableEntry(void *attr, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: valid.c:2027
xmlAttributePtr xmlAddAttributeDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name, const xmlChar *ns, xmlAttributeType type, xmlAttributeDefault def, const xmlChar *defaultValue, xmlEnumerationPtr tree)
Definition: valid.c:1812
static void xmlValidNormalizeString(xmlChar *str)
Definition: valid.c:2448
static void xmlFreeNotationTableEntry(void *nota, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: valid.c:2305
static void xmlFreeRef(xmlLinkPtr lk)
Definition: valid.c:2776
xmlAttrPtr xmlGetID(xmlDocPtr doc, const xmlChar *ID)
Definition: valid.c:2719
xmlRefPtr xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr)
Definition: valid.c:2848
xmlElementPtr xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name)
Definition: valid.c:3102
void xmlFreeAttributeTable(xmlAttributeTablePtr table)
Definition: valid.c:2038
struct xmlRemoveMemo_t xmlRemoveMemo
static void xmlFreeAttribute(xmlAttributePtr attr)
Definition: valid.c:1759
xmlRefTable * xmlRefTablePtr
Definition: valid.h:137
xmlIDTable * xmlIDTablePtr
Definition: valid.h:129
xmlAttributeTable * xmlAttributeTablePtr
Definition: valid.h:121
xmlElementTable * xmlElementTablePtr
Definition: valid.h:113
xmlValidState * xmlValidStatePtr
Definition: valid.h:31
xmlValidCtxt * xmlValidCtxtPtr
Definition: valid.h:68
xmlNotationTable * xmlNotationTablePtr
Definition: valid.h:105
struct _xmlValidState xmlValidState
Definition: valid.h:30
typedeftypedef void(*) typedef void(*) struct _xmlValidCtx xmlValidCtxt)
Definition: valid.h:67
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
void(*) typedef void(* xmlStructuredErrorFunc)(void *userData, const xmlError *error)
Definition: xmlerror.h:859
@ XML_ERR_WARNING
Definition: xmlerror.h:26
@ XML_ERR_ERROR
Definition: xmlerror.h:27
@ XML_ERR_FATAL
Definition: xmlerror.h:28
@ XML_FROM_VALID
Definition: xmlerror.h:60
void(* xmlGenericErrorFunc)(void *ctx, const char *msg,...) LIBXML_ATTR_FORMAT(2
Definition: xmlerror.h:848
xmlParserErrors
Definition: xmlerror.h:99
@ XML_DTD_LOAD_ERROR
Definition: xmlerror.h:237
@ XML_DTD_ATTRIBUTE_REDEFINED
Definition: xmlerror.h:221
@ XML_DTD_INVALID_CHILD
Definition: xmlerror.h:235
@ XML_DTD_UNKNOWN_ELEM
Definition: xmlerror.h:254
@ XML_DTD_MULTIPLE_ID
Definition: xmlerror.h:240
@ XML_DTD_DIFFERENT_PREFIX
Definition: xmlerror.h:226
@ XML_DTD_UNKNOWN_ID
Definition: xmlerror.h:256
@ XML_DTD_UNKNOWN_ATTRIBUTE
Definition: xmlerror.h:253
@ XML_DTD_CONTENT_MODEL
Definition: xmlerror.h:224
@ XML_DTD_NO_DTD
Definition: xmlerror.h:242
@ XML_DTD_NOT_STANDALONE
Definition: xmlerror.h:250
@ XML_DTD_INVALID_DEFAULT
Definition: xmlerror.h:236
@ XML_DTD_ID_SUBSET
Definition: xmlerror.h:234
@ XML_DTD_MIXED_CORRUPT
Definition: xmlerror.h:239
@ XML_DTD_EMPTY_NOTATION
Definition: xmlerror.h:230
@ XML_DTD_UNKNOWN_ENTITY
Definition: xmlerror.h:255
@ XML_DTD_NO_PREFIX
Definition: xmlerror.h:244
@ XML_DTD_ATTRIBUTE_DEFAULT
Definition: xmlerror.h:220
@ XML_DTD_NO_DOC
Definition: xmlerror.h:241
@ XML_DTD_ELEM_DEFAULT_NAMESPACE
Definition: xmlerror.h:227
@ XML_DTD_MISSING_ATTRIBUTE
Definition: xmlerror.h:238
@ XML_ERR_INTERNAL_ERROR
Definition: xmlerror.h:101
@ XML_DTD_CONTENT_ERROR
Definition: xmlerror.h:223
@ XML_DTD_CONTENT_NOT_DETERMINIST
Definition: xmlerror.h:225
@ XML_DTD_ROOT_NAME
Definition: xmlerror.h:251
@ XML_DTD_NO_ROOT
Definition: xmlerror.h:245
@ XML_DTD_ELEM_NAMESPACE
Definition: xmlerror.h:228
@ XML_DTD_NOT_PCDATA
Definition: xmlerror.h:249
@ XML_DTD_NOTATION_VALUE
Definition: xmlerror.h:247
@ XML_DTD_ELEM_REDEFINED
Definition: xmlerror.h:229
@ XML_DTD_ENTITY_TYPE
Definition: xmlerror.h:231
@ XML_DTD_ID_REDEFINED
Definition: xmlerror.h:233
@ XML_DTD_ATTRIBUTE_VALUE
Definition: xmlerror.h:222
@ XML_DTD_NOT_EMPTY
Definition: xmlerror.h:248
@ XML_DTD_NOTATION_REDEFINED
Definition: xmlerror.h:246
@ XML_DTD_STANDALONE_WHITE_SPACE
Definition: xmlerror.h:252
@ XML_ERR_NO_MEMORY
Definition: xmlerror.h:102
@ XML_DTD_UNKNOWN_NOTATION
Definition: xmlerror.h:257
@ XML_DTD_ID_FIXED
Definition: xmlerror.h:232
XMLPUBFUN xmlChar * xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:45
XMLPUBFUN int xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:428
XMLPUBFUN int xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len)
Definition: xmlstring.c:215
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:162
unsigned char xmlChar
Definition: xmlstring.h:28
XMLPUBFUN xmlChar * xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:69
#define LIBXML_ATTR_FORMAT(fmt, args)
Definition: xmlversion.h:472
#define const
Definition: zconf.h:233