ReactOS 0.4.15-dev-7834-g00c4b3d
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#include <libxml/globals.h>
25
27 int create);
28/* #define DEBUG_VALID_ALGO */
29/* #define DEBUG_REGEXP_ALGO */
30
31#define TODO \
32 xmlGenericError(xmlGenericErrorContext, \
33 "Unimplemented block at %s:%d\n", \
34 __FILE__, __LINE__);
35
36#ifdef LIBXML_VALID_ENABLED
37static int
38xmlValidateAttributeValueInternal(xmlDocPtr doc, xmlAttributeType type,
39 const xmlChar *value);
40#endif
41/************************************************************************
42 * *
43 * Error handling routines *
44 * *
45 ************************************************************************/
46
54static void
56{
57 xmlGenericErrorFunc channel = NULL;
58 xmlParserCtxtPtr pctxt = NULL;
59 void *data = NULL;
60
61 if (ctxt != NULL) {
62 channel = ctxt->error;
63 data = ctxt->userData;
64 /* Look up flag to detect if it is part of a parsing
65 context */
66 if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
67 long delta = (char *) ctxt - (char *) ctxt->userData;
68 if ((delta > 0) && (delta < 250))
69 pctxt = ctxt->userData;
70 }
71 }
72 if (extra)
73 __xmlRaiseError(NULL, channel, data,
75 XML_ERR_FATAL, NULL, 0, extra, NULL, NULL, 0, 0,
76 "Memory allocation failed : %s\n", extra);
77 else
78 __xmlRaiseError(NULL, channel, data,
80 XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0,
81 "Memory allocation failed\n");
82}
83
92static void LIBXML_ATTR_FORMAT(3,0)
93xmlErrValid(xmlValidCtxtPtr ctxt, xmlParserErrors error,
94 const char *msg, const char *extra)
95{
96 xmlGenericErrorFunc channel = NULL;
97 xmlParserCtxtPtr pctxt = NULL;
98 void *data = NULL;
99
100 if (ctxt != NULL) {
101 channel = ctxt->error;
102 data = ctxt->userData;
103 /* Look up flag to detect if it is part of a parsing
104 context */
105 if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
106 long delta = (char *) ctxt - (char *) ctxt->userData;
107 if ((delta > 0) && (delta < 250))
108 pctxt = ctxt->userData;
109 }
110 }
111 if (extra)
112 __xmlRaiseError(NULL, channel, data,
113 pctxt, NULL, XML_FROM_VALID, error,
114 XML_ERR_ERROR, NULL, 0, extra, NULL, NULL, 0, 0,
115 msg, extra);
116 else
117 __xmlRaiseError(NULL, channel, data,
118 pctxt, NULL, XML_FROM_VALID, error,
119 XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
120 "%s", msg);
121}
122
123#if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
135static void LIBXML_ATTR_FORMAT(4,0)
136xmlErrValidNode(xmlValidCtxtPtr ctxt,
138 const char *msg, const xmlChar * str1,
139 const xmlChar * str2, const xmlChar * str3)
140{
141 xmlStructuredErrorFunc schannel = NULL;
142 xmlGenericErrorFunc channel = NULL;
143 xmlParserCtxtPtr pctxt = NULL;
144 void *data = NULL;
145
146 if (ctxt != NULL) {
147 channel = ctxt->error;
148 data = ctxt->userData;
149 /* Look up flag to detect if it is part of a parsing
150 context */
151 if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
152 long delta = (char *) ctxt - (char *) ctxt->userData;
153 if ((delta > 0) && (delta < 250))
154 pctxt = ctxt->userData;
155 }
156 }
157 __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error,
159 (const char *) str1,
160 (const char *) str2,
161 (const char *) str3, 0, 0, msg, str1, str2, str3);
162}
163#endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */
164
165#ifdef LIBXML_VALID_ENABLED
177static void LIBXML_ATTR_FORMAT(4,0)
178xmlErrValidNodeNr(xmlValidCtxtPtr ctxt,
180 const char *msg, const xmlChar * str1,
181 int int2, const xmlChar * str3)
182{
183 xmlStructuredErrorFunc schannel = NULL;
184 xmlGenericErrorFunc channel = NULL;
185 xmlParserCtxtPtr pctxt = NULL;
186 void *data = NULL;
187
188 if (ctxt != NULL) {
189 channel = ctxt->error;
190 data = ctxt->userData;
191 /* Look up flag to detect if it is part of a parsing
192 context */
193 if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
194 long delta = (char *) ctxt - (char *) ctxt->userData;
195 if ((delta > 0) && (delta < 250))
196 pctxt = ctxt->userData;
197 }
198 }
199 __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error,
201 (const char *) str1,
202 (const char *) str3,
203 NULL, int2, 0, msg, str1, int2, str3);
204}
205
217static void LIBXML_ATTR_FORMAT(4,0)
218xmlErrValidWarning(xmlValidCtxtPtr ctxt,
220 const char *msg, const xmlChar * str1,
221 const xmlChar * str2, const xmlChar * str3)
222{
223 xmlStructuredErrorFunc schannel = NULL;
224 xmlGenericErrorFunc channel = NULL;
225 xmlParserCtxtPtr pctxt = NULL;
226 void *data = NULL;
227
228 if (ctxt != NULL) {
229 channel = ctxt->warning;
230 data = ctxt->userData;
231 /* Look up flag to detect if it is part of a parsing
232 context */
233 if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
234 long delta = (char *) ctxt - (char *) ctxt->userData;
235 if ((delta > 0) && (delta < 250))
236 pctxt = ctxt->userData;
237 }
238 }
239 __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error,
241 (const char *) str1,
242 (const char *) str2,
243 (const char *) str3, 0, 0, msg, str1, str2, str3);
244}
245
246
247
248#ifdef LIBXML_REGEXP_ENABLED
249/*
250 * If regexp are enabled we can do continuous validation without the
251 * need of a tree to validate the content model. this is done in each
252 * callbacks.
253 * Each xmlValidState represent the validation state associated to the
254 * set of nodes currently open from the document root to the current element.
255 */
256
257
258typedef struct _xmlValidState {
259 xmlElementPtr elemDecl; /* pointer to the content model */
260 xmlNodePtr node; /* pointer to the current node */
261 xmlRegExecCtxtPtr exec; /* regexp runtime */
262} _xmlValidState;
263
264
265static int
266vstateVPush(xmlValidCtxtPtr ctxt, xmlElementPtr elemDecl, xmlNodePtr node) {
267 if ((ctxt->vstateMax == 0) || (ctxt->vstateTab == NULL)) {
268 ctxt->vstateMax = 10;
269 ctxt->vstateTab = (xmlValidState *) xmlMalloc(ctxt->vstateMax *
270 sizeof(ctxt->vstateTab[0]));
271 if (ctxt->vstateTab == NULL) {
272 xmlVErrMemory(ctxt, "malloc failed");
273 return(-1);
274 }
275 }
276
277 if (ctxt->vstateNr >= ctxt->vstateMax) {
278 xmlValidState *tmp;
279
280 tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
281 2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
282 if (tmp == NULL) {
283 xmlVErrMemory(ctxt, "realloc failed");
284 return(-1);
285 }
286 ctxt->vstateMax *= 2;
287 ctxt->vstateTab = tmp;
288 }
289 ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr];
290 ctxt->vstateTab[ctxt->vstateNr].elemDecl = elemDecl;
291 ctxt->vstateTab[ctxt->vstateNr].node = node;
292 if ((elemDecl != NULL) && (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT)) {
293 if (elemDecl->contModel == NULL)
294 xmlValidBuildContentModel(ctxt, elemDecl);
295 if (elemDecl->contModel != NULL) {
296 ctxt->vstateTab[ctxt->vstateNr].exec =
297 xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL);
298 } else {
299 ctxt->vstateTab[ctxt->vstateNr].exec = NULL;
300 xmlErrValidNode(ctxt, (xmlNodePtr) elemDecl,
302 "Failed to build content model regexp for %s\n",
303 node->name, NULL, NULL);
304 }
305 }
306 return(ctxt->vstateNr++);
307}
308
309static int
310vstateVPop(xmlValidCtxtPtr ctxt) {
311 xmlElementPtr elemDecl;
312
313 if (ctxt->vstateNr < 1) return(-1);
314 ctxt->vstateNr--;
315 elemDecl = ctxt->vstateTab[ctxt->vstateNr].elemDecl;
316 ctxt->vstateTab[ctxt->vstateNr].elemDecl = NULL;
317 ctxt->vstateTab[ctxt->vstateNr].node = NULL;
318 if ((elemDecl != NULL) && (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT)) {
319 xmlRegFreeExecCtxt(ctxt->vstateTab[ctxt->vstateNr].exec);
320 }
321 ctxt->vstateTab[ctxt->vstateNr].exec = NULL;
322 if (ctxt->vstateNr >= 1)
323 ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr - 1];
324 else
325 ctxt->vstate = NULL;
326 return(ctxt->vstateNr);
327}
328
329#else /* not LIBXML_REGEXP_ENABLED */
330/*
331 * If regexp are not enabled, it uses a home made algorithm less
332 * complex and easier to
333 * debug/maintain than a generic NFA -> DFA state based algo. The
334 * only restriction is on the deepness of the tree limited by the
335 * size of the occurs bitfield
336 *
337 * this is the content of a saved state for rollbacks
338 */
339
340#define ROLLBACK_OR 0
341#define ROLLBACK_PARENT 1
342
343typedef struct _xmlValidState {
344 xmlElementContentPtr cont; /* pointer to the content model subtree */
345 xmlNodePtr node; /* pointer to the current node in the list */
346 long occurs;/* bitfield for multiple occurrences */
347 unsigned char depth; /* current depth in the overall tree */
348 unsigned char state; /* ROLLBACK_XXX */
349} _xmlValidState;
350
351#define MAX_RECURSE 25000
352#define MAX_DEPTH ((sizeof(_xmlValidState.occurs)) * 8)
353#define CONT ctxt->vstate->cont
354#define NODE ctxt->vstate->node
355#define DEPTH ctxt->vstate->depth
356#define OCCURS ctxt->vstate->occurs
357#define STATE ctxt->vstate->state
358
359#define OCCURRENCE (ctxt->vstate->occurs & (1 << DEPTH))
360#define PARENT_OCCURRENCE (ctxt->vstate->occurs & ((1 << DEPTH) - 1))
361
362#define SET_OCCURRENCE ctxt->vstate->occurs |= (1 << DEPTH)
363#define RESET_OCCURRENCE ctxt->vstate->occurs &= ((1 << DEPTH) - 1)
364
365static int
366vstateVPush(xmlValidCtxtPtr ctxt, xmlElementContentPtr cont,
367 xmlNodePtr node, unsigned char depth, long occurs,
368 unsigned char state) {
369 int i = ctxt->vstateNr - 1;
370
371 if (ctxt->vstateNr > MAX_RECURSE) {
372 return(-1);
373 }
374 if (ctxt->vstateTab == NULL) {
375 ctxt->vstateMax = 8;
376 ctxt->vstateTab = (xmlValidState *) xmlMalloc(
377 ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
378 if (ctxt->vstateTab == NULL) {
379 xmlVErrMemory(ctxt, "malloc failed");
380 return(-1);
381 }
382 }
383 if (ctxt->vstateNr >= ctxt->vstateMax) {
384 xmlValidState *tmp;
385
386 tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
387 2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
388 if (tmp == NULL) {
389 xmlVErrMemory(ctxt, "malloc failed");
390 return(-1);
391 }
392 ctxt->vstateMax *= 2;
393 ctxt->vstateTab = tmp;
394 ctxt->vstate = &ctxt->vstateTab[0];
395 }
396 /*
397 * Don't push on the stack a state already here
398 */
399 if ((i >= 0) && (ctxt->vstateTab[i].cont == cont) &&
400 (ctxt->vstateTab[i].node == node) &&
401 (ctxt->vstateTab[i].depth == depth) &&
402 (ctxt->vstateTab[i].occurs == occurs) &&
403 (ctxt->vstateTab[i].state == state))
404 return(ctxt->vstateNr);
405 ctxt->vstateTab[ctxt->vstateNr].cont = cont;
406 ctxt->vstateTab[ctxt->vstateNr].node = node;
407 ctxt->vstateTab[ctxt->vstateNr].depth = depth;
408 ctxt->vstateTab[ctxt->vstateNr].occurs = occurs;
409 ctxt->vstateTab[ctxt->vstateNr].state = state;
410 return(ctxt->vstateNr++);
411}
412
413static int
414vstateVPop(xmlValidCtxtPtr ctxt) {
415 if (ctxt->vstateNr <= 1) return(-1);
416 ctxt->vstateNr--;
417 ctxt->vstate = &ctxt->vstateTab[0];
418 ctxt->vstate->cont = ctxt->vstateTab[ctxt->vstateNr].cont;
419 ctxt->vstate->node = ctxt->vstateTab[ctxt->vstateNr].node;
420 ctxt->vstate->depth = ctxt->vstateTab[ctxt->vstateNr].depth;
421 ctxt->vstate->occurs = ctxt->vstateTab[ctxt->vstateNr].occurs;
422 ctxt->vstate->state = ctxt->vstateTab[ctxt->vstateNr].state;
423 return(ctxt->vstateNr);
424}
425
426#endif /* LIBXML_REGEXP_ENABLED */
427
428static int
429nodeVPush(xmlValidCtxtPtr ctxt, xmlNodePtr value)
430{
431 if (ctxt->nodeMax <= 0) {
432 ctxt->nodeMax = 4;
433 ctxt->nodeTab =
434 (xmlNodePtr *) xmlMalloc(ctxt->nodeMax *
435 sizeof(ctxt->nodeTab[0]));
436 if (ctxt->nodeTab == NULL) {
437 xmlVErrMemory(ctxt, "malloc failed");
438 ctxt->nodeMax = 0;
439 return (0);
440 }
441 }
442 if (ctxt->nodeNr >= ctxt->nodeMax) {
443 xmlNodePtr *tmp;
444 tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
445 ctxt->nodeMax * 2 * sizeof(ctxt->nodeTab[0]));
446 if (tmp == NULL) {
447 xmlVErrMemory(ctxt, "realloc failed");
448 return (0);
449 }
450 ctxt->nodeMax *= 2;
451 ctxt->nodeTab = tmp;
452 }
453 ctxt->nodeTab[ctxt->nodeNr] = value;
454 ctxt->node = value;
455 return (ctxt->nodeNr++);
456}
457static xmlNodePtr
458nodeVPop(xmlValidCtxtPtr ctxt)
459{
461
462 if (ctxt->nodeNr <= 0)
463 return (NULL);
464 ctxt->nodeNr--;
465 if (ctxt->nodeNr > 0)
466 ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
467 else
468 ctxt->node = NULL;
469 ret = ctxt->nodeTab[ctxt->nodeNr];
470 ctxt->nodeTab[ctxt->nodeNr] = NULL;
471 return (ret);
472}
473
474#ifdef DEBUG_VALID_ALGO
475static void
476xmlValidPrintNode(xmlNodePtr cur) {
477 if (cur == NULL) {
479 return;
480 }
481 switch (cur->type) {
482 case XML_ELEMENT_NODE:
484 break;
485 case XML_TEXT_NODE:
487 break;
490 break;
493 break;
494 case XML_PI_NODE:
495 xmlGenericError(xmlGenericErrorContext, "pi(%s) ", cur->name);
496 break;
497 case XML_COMMENT_NODE:
499 break;
502 break;
503 case XML_ENTITY_NODE:
505 break;
508 break;
511 break;
514 break;
517 break;
520 break;
521 case XML_DTD_NODE:
523 break;
524 case XML_ELEMENT_DECL:
526 break;
529 break;
530 case XML_ENTITY_DECL:
532 break;
535 break;
538 break;
539 case XML_XINCLUDE_END:
541 break;
542 }
543}
544
545static void
546xmlValidPrintNodeList(xmlNodePtr cur) {
547 if (cur == NULL)
549 while (cur != NULL) {
550 xmlValidPrintNode(cur);
551 cur = cur->next;
552 }
553}
554
555static void
556xmlValidDebug(xmlNodePtr cur, xmlElementContentPtr cont) {
557 char expr[5000];
558
559 expr[0] = 0;
561 xmlValidPrintNodeList(cur);
563 xmlSnprintfElementContent(expr, 5000, cont, 1);
565}
566
567static void
568xmlValidDebugState(xmlValidStatePtr state) {
570 if (state->cont == NULL)
572 else
573 switch (state->cont->type) {
576 break;
579 state->cont->name);
580 break;
583 break;
586 break;
587 }
588 xmlValidPrintNode(state->node);
590 state->depth, state->occurs, state->state);
591}
592
593static void
594xmlValidStateDebug(xmlValidCtxtPtr ctxt) {
595 int i, j;
596
598 xmlValidDebugState(ctxt->vstate);
600 ctxt->vstateNr - 1);
601 for (i = 0, j = ctxt->vstateNr - 1;(i < 3) && (j > 0);i++,j--)
602 xmlValidDebugState(&ctxt->vstateTab[j]);
604}
605
606/*****
607#define DEBUG_VALID_STATE(n,c) xmlValidDebug(n,c);
608 *****/
609
610#define DEBUG_VALID_STATE(n,c) xmlValidStateDebug(ctxt);
611#define DEBUG_VALID_MSG(m) \
612 xmlGenericError(xmlGenericErrorContext, "%s\n", m);
613
614#else
615#define DEBUG_VALID_STATE(n,c)
616#define DEBUG_VALID_MSG(m)
617#endif
618
619/* TODO: use hash table for accesses to elem and attribute definitions */
620
621
622#define CHECK_DTD \
623 if (doc == NULL) return(0); \
624 else if ((doc->intSubset == NULL) && \
625 (doc->extSubset == NULL)) return(0)
626
627#ifdef LIBXML_REGEXP_ENABLED
628
629/************************************************************************
630 * *
631 * Content model validation based on the regexps *
632 * *
633 ************************************************************************/
634
645static int
646xmlValidBuildAContentModel(xmlElementContentPtr content,
647 xmlValidCtxtPtr ctxt,
648 const xmlChar *name) {
649 if (content == NULL) {
650 xmlErrValidNode(ctxt, NULL, XML_ERR_INTERNAL_ERROR,
651 "Found NULL content in content model of %s\n",
652 name, NULL, NULL);
653 return(0);
654 }
655 switch (content->type) {
657 xmlErrValidNode(ctxt, NULL, XML_ERR_INTERNAL_ERROR,
658 "Found PCDATA in content model of %s\n",
659 name, NULL, NULL);
660 return(0);
661 break;
663 xmlAutomataStatePtr oldstate = ctxt->state;
664 xmlChar fn[50];
666
667 fullname = xmlBuildQName(content->name, content->prefix, fn, 50);
668 if (fullname == NULL) {
669 xmlVErrMemory(ctxt, "Building content model");
670 return(0);
671 }
672
673 switch (content->ocur) {
675 ctxt->state = xmlAutomataNewTransition(ctxt->am,
676 ctxt->state, NULL, fullname, NULL);
677 break;
679 ctxt->state = xmlAutomataNewTransition(ctxt->am,
680 ctxt->state, NULL, fullname, NULL);
681 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
682 break;
684 ctxt->state = xmlAutomataNewTransition(ctxt->am,
685 ctxt->state, NULL, fullname, NULL);
686 xmlAutomataNewTransition(ctxt->am, ctxt->state,
687 ctxt->state, fullname, NULL);
688 break;
690 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
691 ctxt->state, NULL);
692 xmlAutomataNewTransition(ctxt->am,
693 ctxt->state, ctxt->state, fullname, NULL);
694 break;
695 }
696 if ((fullname != fn) && (fullname != content->name))
698 break;
699 }
701 xmlAutomataStatePtr oldstate, oldend;
703
704 /*
705 * Simply iterate over the content
706 */
707 oldstate = ctxt->state;
708 ocur = content->ocur;
709 if (ocur != XML_ELEMENT_CONTENT_ONCE) {
710 ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
711 oldstate = ctxt->state;
712 }
713 do {
714 xmlValidBuildAContentModel(content->c1, ctxt, name);
715 content = content->c2;
716 } while ((content->type == XML_ELEMENT_CONTENT_SEQ) &&
718 xmlValidBuildAContentModel(content, ctxt, name);
719 oldend = ctxt->state;
720 ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL);
721 switch (ocur) {
723 break;
725 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
726 break;
728 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
729 xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
730 break;
732 xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
733 break;
734 }
735 break;
736 }
738 xmlAutomataStatePtr oldstate, oldend;
740
741 ocur = content->ocur;
742 if ((ocur == XML_ELEMENT_CONTENT_PLUS) ||
743 (ocur == XML_ELEMENT_CONTENT_MULT)) {
744 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
745 ctxt->state, NULL);
746 }
747 oldstate = ctxt->state;
748 oldend = xmlAutomataNewState(ctxt->am);
749
750 /*
751 * iterate over the subtypes and remerge the end with an
752 * epsilon transition
753 */
754 do {
755 ctxt->state = oldstate;
756 xmlValidBuildAContentModel(content->c1, ctxt, name);
757 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend);
758 content = content->c2;
759 } while ((content->type == XML_ELEMENT_CONTENT_OR) &&
761 ctxt->state = oldstate;
762 xmlValidBuildAContentModel(content, ctxt, name);
763 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend);
764 ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL);
765 switch (ocur) {
767 break;
769 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
770 break;
772 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
773 xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
774 break;
776 xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
777 break;
778 }
779 break;
780 }
781 default:
782 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
783 "ContentModel broken for element %s\n",
784 (const char *) name);
785 return(0);
786 }
787 return(1);
788}
799int
800xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) {
801
802 if ((ctxt == NULL) || (elem == NULL))
803 return(0);
804 if (elem->type != XML_ELEMENT_DECL)
805 return(0);
806 if (elem->etype != XML_ELEMENT_TYPE_ELEMENT)
807 return(1);
808 /* TODO: should we rebuild in this case ? */
809 if (elem->contModel != NULL) {
810 if (!xmlRegexpIsDeterminist(elem->contModel)) {
811 ctxt->valid = 0;
812 return(0);
813 }
814 return(1);
815 }
816
817 ctxt->am = xmlNewAutomata();
818 if (ctxt->am == NULL) {
819 xmlErrValidNode(ctxt, (xmlNodePtr) elem,
821 "Cannot create automata for element %s\n",
822 elem->name, NULL, NULL);
823 return(0);
824 }
825 ctxt->state = xmlAutomataGetInitState(ctxt->am);
826 xmlValidBuildAContentModel(elem->content, ctxt, elem->name);
827 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
828 elem->contModel = xmlAutomataCompile(ctxt->am);
829 if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
830 char expr[5000];
831 expr[0] = 0;
832 xmlSnprintfElementContent(expr, 5000, elem->content, 1);
833 xmlErrValidNode(ctxt, (xmlNodePtr) elem,
835 "Content model of %s is not determinist: %s\n",
836 elem->name, BAD_CAST expr, NULL);
837#ifdef DEBUG_REGEXP_ALGO
838 xmlRegexpPrint(stderr, elem->contModel);
839#endif
840 ctxt->valid = 0;
841 ctxt->state = NULL;
842 xmlFreeAutomata(ctxt->am);
843 ctxt->am = NULL;
844 return(0);
845 }
846 ctxt->state = NULL;
847 xmlFreeAutomata(ctxt->am);
848 ctxt->am = NULL;
849 return(1);
850}
851
852#endif /* LIBXML_REGEXP_ENABLED */
853
854/****************************************************************
855 * *
856 * Util functions for data allocation/deallocation *
857 * *
858 ****************************************************************/
859
867xmlValidCtxtPtr xmlNewValidCtxt(void) {
869
870 if ((ret = xmlMalloc(sizeof (xmlValidCtxt))) == NULL) {
871 xmlVErrMemory(NULL, "malloc failed");
872 return (NULL);
873 }
874
875 (void) memset(ret, 0, sizeof (xmlValidCtxt));
876
877 return (ret);
878}
879
886void
887xmlFreeValidCtxt(xmlValidCtxtPtr cur) {
888 if (cur->vstateTab != NULL)
889 xmlFree(cur->vstateTab);
890 if (cur->nodeTab != NULL)
891 xmlFree(cur->nodeTab);
892 xmlFree(cur);
893}
894
895#endif /* LIBXML_VALID_ENABLED */
896
911 xmlDictPtr dict = NULL;
912
913 if (doc != NULL)
914 dict = doc->dict;
915
916 switch(type) {
918 if (name == NULL) {
919 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
920 "xmlNewElementContent : name == NULL !\n",
921 NULL);
922 }
923 break;
927 if (name != NULL) {
928 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
929 "xmlNewElementContent : name != NULL !\n",
930 NULL);
931 }
932 break;
933 default:
934 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
935 "Internal: ELEMENT content corrupted invalid type\n",
936 NULL);
937 return(NULL);
938 }
940 if (ret == NULL) {
941 xmlVErrMemory(NULL, "malloc failed");
942 return(NULL);
943 }
944 memset(ret, 0, sizeof(xmlElementContent));
945 ret->type = type;
947 if (name != NULL) {
948 int l;
949 const xmlChar *tmp;
950
951 tmp = xmlSplitQName3(name, &l);
952 if (tmp == NULL) {
953 if (dict == NULL)
954 ret->name = xmlStrdup(name);
955 else
956 ret->name = xmlDictLookup(dict, name, -1);
957 } else {
958 if (dict == NULL) {
959 ret->prefix = xmlStrndup(name, l);
960 ret->name = xmlStrdup(tmp);
961 } else {
962 ret->prefix = xmlDictLookup(dict, name, l);
963 ret->name = xmlDictLookup(dict, tmp, -1);
964 }
965 }
966 }
967 return(ret);
968}
969
983}
984
996 xmlElementContentPtr ret = NULL, prev = NULL, tmp;
997 xmlDictPtr dict = NULL;
998
999 if (cur == NULL) return(NULL);
1000
1001 if (doc != NULL)
1002 dict = doc->dict;
1003
1005 if (ret == NULL) {
1006 xmlVErrMemory(NULL, "malloc failed");
1007 return(NULL);
1008 }
1009 memset(ret, 0, sizeof(xmlElementContent));
1010 ret->type = cur->type;
1011 ret->ocur = cur->ocur;
1012 if (cur->name != NULL) {
1013 if (dict)
1014 ret->name = xmlDictLookup(dict, cur->name, -1);
1015 else
1016 ret->name = xmlStrdup(cur->name);
1017 }
1018
1019 if (cur->prefix != NULL) {
1020 if (dict)
1021 ret->prefix = xmlDictLookup(dict, cur->prefix, -1);
1022 else
1023 ret->prefix = xmlStrdup(cur->prefix);
1024 }
1025 if (cur->c1 != NULL)
1026 ret->c1 = xmlCopyDocElementContent(doc, cur->c1);
1027 if (ret->c1 != NULL)
1028 ret->c1->parent = ret;
1029 if (cur->c2 != NULL) {
1030 prev = ret;
1031 cur = cur->c2;
1032 while (cur != NULL) {
1034 if (tmp == NULL) {
1035 xmlVErrMemory(NULL, "malloc failed");
1036 return(ret);
1037 }
1038 memset(tmp, 0, sizeof(xmlElementContent));
1039 tmp->type = cur->type;
1040 tmp->ocur = cur->ocur;
1041 prev->c2 = tmp;
1042 tmp->parent = prev;
1043 if (cur->name != NULL) {
1044 if (dict)
1045 tmp->name = xmlDictLookup(dict, cur->name, -1);
1046 else
1047 tmp->name = xmlStrdup(cur->name);
1048 }
1049
1050 if (cur->prefix != NULL) {
1051 if (dict)
1052 tmp->prefix = xmlDictLookup(dict, cur->prefix, -1);
1053 else
1054 tmp->prefix = xmlStrdup(cur->prefix);
1055 }
1056 if (cur->c1 != NULL)
1057 tmp->c1 = xmlCopyDocElementContent(doc,cur->c1);
1058 if (tmp->c1 != NULL)
1059 tmp->c1->parent = ret;
1060 prev = tmp;
1061 cur = cur->c2;
1062 }
1063 }
1064 return(ret);
1065}
1066
1079}
1080
1088void
1090 xmlDictPtr dict = NULL;
1091 size_t depth = 0;
1092
1093 if (cur == NULL)
1094 return;
1095 if (doc != NULL)
1096 dict = doc->dict;
1097
1098 while (1) {
1100
1101 while ((cur->c1 != NULL) || (cur->c2 != NULL)) {
1102 cur = (cur->c1 != NULL) ? cur->c1 : cur->c2;
1103 depth += 1;
1104 }
1105
1106 switch (cur->type) {
1111 break;
1112 default:
1113 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
1114 "Internal: ELEMENT content corrupted invalid type\n",
1115 NULL);
1116 return;
1117 }
1118 if (dict) {
1119 if ((cur->name != NULL) && (!xmlDictOwns(dict, cur->name)))
1120 xmlFree((xmlChar *) cur->name);
1121 if ((cur->prefix != NULL) && (!xmlDictOwns(dict, cur->prefix)))
1122 xmlFree((xmlChar *) cur->prefix);
1123 } else {
1124 if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
1125 if (cur->prefix != NULL) xmlFree((xmlChar *) cur->prefix);
1126 }
1127 parent = cur->parent;
1128 if ((depth == 0) || (parent == NULL)) {
1129 xmlFree(cur);
1130 break;
1131 }
1132 if (cur == parent->c1)
1133 parent->c1 = NULL;
1134 else
1135 parent->c2 = NULL;
1136 xmlFree(cur);
1137
1138 if (parent->c2 != NULL) {
1139 cur = parent->c2;
1140 } else {
1141 depth -= 1;
1142 cur = parent;
1143 }
1144 }
1145}
1146
1154void
1157}
1158
1159#ifdef LIBXML_OUTPUT_ENABLED
1167static void
1168xmlDumpElementOccur(xmlBufferPtr buf, xmlElementContentPtr cur) {
1169 switch (cur->ocur) {
1171 break;
1173 xmlBufferWriteChar(buf, "?");
1174 break;
1176 xmlBufferWriteChar(buf, "*");
1177 break;
1179 xmlBufferWriteChar(buf, "+");
1180 break;
1181 }
1182}
1183
1191static void
1192xmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content) {
1194
1195 if (content == NULL) return;
1196
1197 xmlBufferWriteChar(buf, "(");
1198 cur = content;
1199
1200 do {
1201 if (cur == NULL) return;
1202
1203 switch (cur->type) {
1205 xmlBufferWriteChar(buf, "#PCDATA");
1206 break;
1208 if (cur->prefix != NULL) {
1209 xmlBufferWriteCHAR(buf, cur->prefix);
1210 xmlBufferWriteChar(buf, ":");
1211 }
1212 xmlBufferWriteCHAR(buf, cur->name);
1213 break;
1216 if ((cur != content) &&
1217 (cur->parent != NULL) &&
1218 ((cur->type != cur->parent->type) ||
1219 (cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
1220 xmlBufferWriteChar(buf, "(");
1221 cur = cur->c1;
1222 continue;
1223 default:
1224 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
1225 "Internal: ELEMENT cur corrupted invalid type\n",
1226 NULL);
1227 }
1228
1229 while (cur != content) {
1231
1232 if (parent == NULL) return;
1233
1234 if (((cur->type == XML_ELEMENT_CONTENT_OR) ||
1235 (cur->type == XML_ELEMENT_CONTENT_SEQ)) &&
1236 ((cur->type != parent->type) ||
1237 (cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
1238 xmlBufferWriteChar(buf, ")");
1239 xmlDumpElementOccur(buf, cur);
1240
1241 if (cur == parent->c1) {
1242 if (parent->type == XML_ELEMENT_CONTENT_SEQ)
1243 xmlBufferWriteChar(buf, " , ");
1244 else if (parent->type == XML_ELEMENT_CONTENT_OR)
1245 xmlBufferWriteChar(buf, " | ");
1246
1247 cur = parent->c2;
1248 break;
1249 }
1250
1251 cur = parent;
1252 }
1253 } while (cur != content);
1254
1255 xmlBufferWriteChar(buf, ")");
1256 xmlDumpElementOccur(buf, content);
1257}
1258
1267void
1268xmlSprintfElementContent(char *buf ATTRIBUTE_UNUSED,
1270 int englob ATTRIBUTE_UNUSED) {
1271}
1272#endif /* LIBXML_OUTPUT_ENABLED */
1273
1284void
1286 int len;
1287
1288 if (content == NULL) return;
1289 len = strlen(buf);
1290 if (size - len < 50) {
1291 if ((size - len > 4) && (buf[len - 1] != '.'))
1292 strcat(buf, " ...");
1293 return;
1294 }
1295 if (englob) strcat(buf, "(");
1296 switch (content->type) {
1298 strcat(buf, "#PCDATA");
1299 break;
1301 int qnameLen = xmlStrlen(content->name);
1302
1303 if (content->prefix != NULL)
1304 qnameLen += xmlStrlen(content->prefix) + 1;
1305 if (size - len < qnameLen + 10) {
1306 strcat(buf, " ...");
1307 return;
1308 }
1309 if (content->prefix != NULL) {
1310 strcat(buf, (char *) content->prefix);
1311 strcat(buf, ":");
1312 }
1313 if (content->name != NULL)
1314 strcat(buf, (char *) content->name);
1315 break;
1316 }
1318 if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
1319 (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
1321 else
1323 len = strlen(buf);
1324 if (size - len < 50) {
1325 if ((size - len > 4) && (buf[len - 1] != '.'))
1326 strcat(buf, " ...");
1327 return;
1328 }
1329 strcat(buf, " , ");
1330 if (((content->c2->type == XML_ELEMENT_CONTENT_OR) ||
1331 (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE)) &&
1332 (content->c2->type != XML_ELEMENT_CONTENT_ELEMENT))
1334 else
1336 break;
1338 if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
1339 (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
1341 else
1343 len = strlen(buf);
1344 if (size - len < 50) {
1345 if ((size - len > 4) && (buf[len - 1] != '.'))
1346 strcat(buf, " ...");
1347 return;
1348 }
1349 strcat(buf, " | ");
1350 if (((content->c2->type == XML_ELEMENT_CONTENT_SEQ) ||
1351 (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE)) &&
1352 (content->c2->type != XML_ELEMENT_CONTENT_ELEMENT))
1354 else
1356 break;
1357 }
1358 if (size - strlen(buf) <= 2) return;
1359 if (englob)
1360 strcat(buf, ")");
1361 switch (content->ocur) {
1363 break;
1365 strcat(buf, "?");
1366 break;
1368 strcat(buf, "*");
1369 break;
1371 strcat(buf, "+");
1372 break;
1373 }
1374}
1375
1376/****************************************************************
1377 * *
1378 * Registration of DTD declarations *
1379 * *
1380 ****************************************************************/
1381
1388static void
1390 if (elem == NULL) return;
1392 xmlFreeDocElementContent(elem->doc, elem->content);
1393 if (elem->name != NULL)
1394 xmlFree((xmlChar *) elem->name);
1395 if (elem->prefix != NULL)
1396 xmlFree((xmlChar *) elem->prefix);
1397#ifdef LIBXML_REGEXP_ENABLED
1398 if (elem->contModel != NULL)
1399 xmlRegFreeRegexp(elem->contModel);
1400#endif
1401 xmlFree(elem);
1402}
1403
1404
1419 xmlDtdPtr dtd, const xmlChar *name,
1424 xmlAttributePtr oldAttributes = NULL;
1425 xmlChar *ns, *uqname;
1426
1427 if (dtd == NULL) {
1428 return(NULL);
1429 }
1430 if (name == NULL) {
1431 return(NULL);
1432 }
1433
1434 switch (type) {
1436 if (content != NULL) {
1437 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
1438 "xmlAddElementDecl: content != NULL for EMPTY\n",
1439 NULL);
1440 return(NULL);
1441 }
1442 break;
1444 if (content != NULL) {
1445 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
1446 "xmlAddElementDecl: content != NULL for ANY\n",
1447 NULL);
1448 return(NULL);
1449 }
1450 break;
1452 if (content == NULL) {
1453 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
1454 "xmlAddElementDecl: content == NULL for MIXED\n",
1455 NULL);
1456 return(NULL);
1457 }
1458 break;
1460 if (content == NULL) {
1461 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
1462 "xmlAddElementDecl: content == NULL for ELEMENT\n",
1463 NULL);
1464 return(NULL);
1465 }
1466 break;
1467 default:
1468 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
1469 "Internal: ELEMENT decl corrupted invalid type\n",
1470 NULL);
1471 return(NULL);
1472 }
1473
1474 /*
1475 * check if name is a QName
1476 */
1477 uqname = xmlSplitQName2(name, &ns);
1478 if (uqname != NULL)
1479 name = uqname;
1480
1481 /*
1482 * Create the Element table if needed.
1483 */
1485 if (table == NULL) {
1486 xmlDictPtr dict = NULL;
1487
1488 if (dtd->doc != NULL)
1489 dict = dtd->doc->dict;
1490 table = xmlHashCreateDict(0, dict);
1491 dtd->elements = (void *) table;
1492 }
1493 if (table == NULL) {
1494 xmlVErrMemory(ctxt,
1495 "xmlAddElementDecl: Table creation failed!\n");
1496 if (uqname != NULL)
1497 xmlFree(uqname);
1498 if (ns != NULL)
1499 xmlFree(ns);
1500 return(NULL);
1501 }
1502
1503 /*
1504 * lookup old attributes inserted on an undefined element in the
1505 * internal subset.
1506 */
1507 if ((dtd->doc != NULL) && (dtd->doc->intSubset != NULL)) {
1508 ret = xmlHashLookup2(dtd->doc->intSubset->elements, name, ns);
1509 if ((ret != NULL) && (ret->etype == XML_ELEMENT_TYPE_UNDEFINED)) {
1510 oldAttributes = ret->attributes;
1511 ret->attributes = NULL;
1512 xmlHashRemoveEntry2(dtd->doc->intSubset->elements, name, ns, NULL);
1514 }
1515 }
1516
1517 /*
1518 * The element may already be present if one of its attribute
1519 * was registered first
1520 */
1522 if (ret != NULL) {
1523 if (ret->etype != XML_ELEMENT_TYPE_UNDEFINED) {
1524#ifdef LIBXML_VALID_ENABLED
1525 /*
1526 * The element is already defined in this DTD.
1527 */
1528 xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ELEM_REDEFINED,
1529 "Redefinition of element %s\n",
1530 name, NULL, NULL);
1531#endif /* LIBXML_VALID_ENABLED */
1532 if (uqname != NULL)
1533 xmlFree(uqname);
1534 if (ns != NULL)
1535 xmlFree(ns);
1536 return(NULL);
1537 }
1538 if (ns != NULL) {
1539 xmlFree(ns);
1540 ns = NULL;
1541 }
1542 } else {
1544 if (ret == NULL) {
1545 xmlVErrMemory(ctxt, "malloc failed");
1546 if (uqname != NULL)
1547 xmlFree(uqname);
1548 if (ns != NULL)
1549 xmlFree(ns);
1550 return(NULL);
1551 }
1552 memset(ret, 0, sizeof(xmlElement));
1553 ret->type = XML_ELEMENT_DECL;
1554
1555 /*
1556 * fill the structure.
1557 */
1558 ret->name = xmlStrdup(name);
1559 if (ret->name == NULL) {
1560 xmlVErrMemory(ctxt, "malloc failed");
1561 if (uqname != NULL)
1562 xmlFree(uqname);
1563 if (ns != NULL)
1564 xmlFree(ns);
1565 xmlFree(ret);
1566 return(NULL);
1567 }
1568 ret->prefix = ns;
1569
1570 /*
1571 * Validity Check:
1572 * Insertion must not fail
1573 */
1574 if (xmlHashAddEntry2(table, name, ns, ret)) {
1575#ifdef LIBXML_VALID_ENABLED
1576 /*
1577 * The element is already defined in this DTD.
1578 */
1579 xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ELEM_REDEFINED,
1580 "Redefinition of element %s\n",
1581 name, NULL, NULL);
1582#endif /* LIBXML_VALID_ENABLED */
1584 if (uqname != NULL)
1585 xmlFree(uqname);
1586 return(NULL);
1587 }
1588 /*
1589 * For new element, may have attributes from earlier
1590 * definition in internal subset
1591 */
1592 ret->attributes = oldAttributes;
1593 }
1594
1595 /*
1596 * Finish to fill the structure.
1597 */
1598 ret->etype = type;
1599 /*
1600 * Avoid a stupid copy when called by the parser
1601 * and flag it by setting a special parent value
1602 * so the parser doesn't unallocate it.
1603 */
1604 if ((ctxt != NULL) && (ctxt->flags & XML_VCTXT_USE_PCTXT)) {
1605 ret->content = content;
1606 if (content != NULL)
1607 content->parent = (xmlElementContentPtr) 1;
1608 } else {
1609 ret->content = xmlCopyDocElementContent(dtd->doc, content);
1610 }
1611
1612 /*
1613 * Link it to the DTD
1614 */
1615 ret->parent = dtd;
1616 ret->doc = dtd->doc;
1617 if (dtd->last == NULL) {
1618 dtd->children = dtd->last = (xmlNodePtr) ret;
1619 } else {
1620 dtd->last->next = (xmlNodePtr) ret;
1621 ret->prev = dtd->last;
1622 dtd->last = (xmlNodePtr) ret;
1623 }
1624 if (uqname != NULL)
1625 xmlFree(uqname);
1626 return(ret);
1627}
1628
1629static void
1632}
1633
1640void
1643}
1644
1645#ifdef LIBXML_TREE_ENABLED
1654static void *
1655xmlCopyElement(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
1656 xmlElementPtr elem = (xmlElementPtr) payload;
1658
1660 if (cur == NULL) {
1661 xmlVErrMemory(NULL, "malloc failed");
1662 return(NULL);
1663 }
1664 memset(cur, 0, sizeof(xmlElement));
1665 cur->type = XML_ELEMENT_DECL;
1666 cur->etype = elem->etype;
1667 if (elem->name != NULL)
1668 cur->name = xmlStrdup(elem->name);
1669 else
1670 cur->name = NULL;
1671 if (elem->prefix != NULL)
1672 cur->prefix = xmlStrdup(elem->prefix);
1673 else
1674 cur->prefix = NULL;
1675 cur->content = xmlCopyElementContent(elem->content);
1676 /* TODO : rebuild the attribute list on the copy */
1677 cur->attributes = NULL;
1678 return(cur);
1679}
1680
1690xmlCopyElementTable(xmlElementTablePtr table) {
1691 return((xmlElementTablePtr) xmlHashCopy(table, xmlCopyElement));
1692}
1693#endif /* LIBXML_TREE_ENABLED */
1694
1695#ifdef LIBXML_OUTPUT_ENABLED
1704void
1705xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) {
1706 if ((buf == NULL) || (elem == NULL))
1707 return;
1708 switch (elem->etype) {
1710 xmlBufferWriteChar(buf, "<!ELEMENT ");
1711 if (elem->prefix != NULL) {
1712 xmlBufferWriteCHAR(buf, elem->prefix);
1713 xmlBufferWriteChar(buf, ":");
1714 }
1715 xmlBufferWriteCHAR(buf, elem->name);
1716 xmlBufferWriteChar(buf, " EMPTY>\n");
1717 break;
1719 xmlBufferWriteChar(buf, "<!ELEMENT ");
1720 if (elem->prefix != NULL) {
1721 xmlBufferWriteCHAR(buf, elem->prefix);
1722 xmlBufferWriteChar(buf, ":");
1723 }
1724 xmlBufferWriteCHAR(buf, elem->name);
1725 xmlBufferWriteChar(buf, " ANY>\n");
1726 break;
1728 xmlBufferWriteChar(buf, "<!ELEMENT ");
1729 if (elem->prefix != NULL) {
1730 xmlBufferWriteCHAR(buf, elem->prefix);
1731 xmlBufferWriteChar(buf, ":");
1732 }
1733 xmlBufferWriteCHAR(buf, elem->name);
1734 xmlBufferWriteChar(buf, " ");
1735 xmlDumpElementContent(buf, elem->content);
1736 xmlBufferWriteChar(buf, ">\n");
1737 break;
1739 xmlBufferWriteChar(buf, "<!ELEMENT ");
1740 if (elem->prefix != NULL) {
1741 xmlBufferWriteCHAR(buf, elem->prefix);
1742 xmlBufferWriteChar(buf, ":");
1743 }
1744 xmlBufferWriteCHAR(buf, elem->name);
1745 xmlBufferWriteChar(buf, " ");
1746 xmlDumpElementContent(buf, elem->content);
1747 xmlBufferWriteChar(buf, ">\n");
1748 break;
1749 default:
1750 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
1751 "Internal: ELEMENT struct corrupted invalid type\n",
1752 NULL);
1753 }
1754}
1755
1764static void
1765xmlDumpElementDeclScan(void *elem, void *buf,
1766 const xmlChar *name ATTRIBUTE_UNUSED) {
1767 xmlDumpElementDecl((xmlBufferPtr) buf, (xmlElementPtr) elem);
1768}
1769
1777void
1778xmlDumpElementTable(xmlBufferPtr buf, xmlElementTablePtr table) {
1779 if ((buf == NULL) || (table == NULL))
1780 return;
1781 xmlHashScan(table, xmlDumpElementDeclScan, buf);
1782}
1783#endif /* LIBXML_OUTPUT_ENABLED */
1784
1797
1799 if (ret == NULL) {
1800 xmlVErrMemory(NULL, "malloc failed");
1801 return(NULL);
1802 }
1803 memset(ret, 0, sizeof(xmlEnumeration));
1804
1805 if (name != NULL)
1806 ret->name = xmlStrdup(name);
1807 return(ret);
1808}
1809
1816void
1818 if (cur == NULL) return;
1819
1820 if (cur->next != NULL) xmlFreeEnumeration(cur->next);
1821
1822 if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
1823 xmlFree(cur);
1824}
1825
1826#ifdef LIBXML_TREE_ENABLED
1837xmlCopyEnumeration(xmlEnumerationPtr cur) {
1839
1840 if (cur == NULL) return(NULL);
1841 ret = xmlCreateEnumeration((xmlChar *) cur->name);
1842 if (ret == NULL) return(NULL);
1843
1844 if (cur->next != NULL) ret->next = xmlCopyEnumeration(cur->next);
1845 else ret->next = NULL;
1846
1847 return(ret);
1848}
1849#endif /* LIBXML_TREE_ENABLED */
1850
1851#ifdef LIBXML_OUTPUT_ENABLED
1859static void
1860xmlDumpEnumeration(xmlBufferPtr buf, xmlEnumerationPtr cur) {
1861 if ((buf == NULL) || (cur == NULL))
1862 return;
1863
1864 xmlBufferWriteCHAR(buf, cur->name);
1865 if (cur->next == NULL)
1866 xmlBufferWriteChar(buf, ")");
1867 else {
1868 xmlBufferWriteChar(buf, " | ");
1869 xmlDumpEnumeration(buf, cur->next);
1870 }
1871}
1872#endif /* LIBXML_OUTPUT_ENABLED */
1873
1874#ifdef LIBXML_VALID_ENABLED
1886static int
1887xmlScanIDAttributeDecl(xmlValidCtxtPtr ctxt, xmlElementPtr elem, int err) {
1889 int ret = 0;
1890
1891 if (elem == NULL) return(0);
1892 cur = elem->attributes;
1893 while (cur != NULL) {
1894 if (cur->atype == XML_ATTRIBUTE_ID) {
1895 ret ++;
1896 if ((ret > 1) && (err))
1897 xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_MULTIPLE_ID,
1898 "Element %s has too many ID attributes defined : %s\n",
1899 elem->name, cur->name, NULL);
1900 }
1901 cur = cur->nexth;
1902 }
1903 return(ret);
1904}
1905#endif /* LIBXML_VALID_ENABLED */
1906
1913static void
1915 xmlDictPtr dict;
1916
1917 if (attr == NULL) return;
1918 if (attr->doc != NULL)
1919 dict = attr->doc->dict;
1920 else
1921 dict = NULL;
1923 if (attr->tree != NULL)
1924 xmlFreeEnumeration(attr->tree);
1925 if (dict) {
1926 if ((attr->elem != NULL) && (!xmlDictOwns(dict, attr->elem)))
1927 xmlFree((xmlChar *) attr->elem);
1928 if ((attr->name != NULL) && (!xmlDictOwns(dict, attr->name)))
1929 xmlFree((xmlChar *) attr->name);
1930 if ((attr->prefix != NULL) && (!xmlDictOwns(dict, attr->prefix)))
1931 xmlFree((xmlChar *) attr->prefix);
1932 if ((attr->defaultValue != NULL) &&
1933 (!xmlDictOwns(dict, attr->defaultValue)))
1934 xmlFree((xmlChar *) attr->defaultValue);
1935 } else {
1936 if (attr->elem != NULL)
1937 xmlFree((xmlChar *) attr->elem);
1938 if (attr->name != NULL)
1939 xmlFree((xmlChar *) attr->name);
1940 if (attr->defaultValue != NULL)
1941 xmlFree((xmlChar *) attr->defaultValue);
1942 if (attr->prefix != NULL)
1943 xmlFree((xmlChar *) attr->prefix);
1944 }
1945 xmlFree(attr);
1946}
1947
1948
1968 xmlDtdPtr dtd, const xmlChar *elem,
1969 const xmlChar *name, const xmlChar *ns,
1971 const xmlChar *defaultValue, xmlEnumerationPtr tree) {
1974 xmlElementPtr elemDef;
1975 xmlDictPtr dict = NULL;
1976
1977 if (dtd == NULL) {
1979 return(NULL);
1980 }
1981 if (name == NULL) {
1983 return(NULL);
1984 }
1985 if (elem == NULL) {
1987 return(NULL);
1988 }
1989 if (dtd->doc != NULL)
1990 dict = dtd->doc->dict;
1991
1992#ifdef LIBXML_VALID_ENABLED
1993 /*
1994 * Check the type and possibly the default value.
1995 */
1996 switch (type) {
1998 break;
1999 case XML_ATTRIBUTE_ID:
2000 break;
2002 break;
2004 break;
2006 break;
2008 break;
2010 break;
2012 break;
2014 break;
2016 break;
2017 default:
2018 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
2019 "Internal: ATTRIBUTE struct corrupted invalid type\n",
2020 NULL);
2022 return(NULL);
2023 }
2024 if ((defaultValue != NULL) &&
2025 (!xmlValidateAttributeValueInternal(dtd->doc, type, defaultValue))) {
2026 xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ATTRIBUTE_DEFAULT,
2027 "Attribute %s of %s: invalid default value\n",
2028 elem, name, defaultValue);
2029 defaultValue = NULL;
2030 if (ctxt != NULL)
2031 ctxt->valid = 0;
2032 }
2033#endif /* LIBXML_VALID_ENABLED */
2034
2035 /*
2036 * Check first that an attribute defined in the external subset wasn't
2037 * already defined in the internal subset
2038 */
2039 if ((dtd->doc != NULL) && (dtd->doc->extSubset == dtd) &&
2040 (dtd->doc->intSubset != NULL) &&
2041 (dtd->doc->intSubset->attributes != NULL)) {
2042 ret = xmlHashLookup3(dtd->doc->intSubset->attributes, name, ns, elem);
2043 if (ret != NULL) {
2045 return(NULL);
2046 }
2047 }
2048
2049 /*
2050 * Create the Attribute table if needed.
2051 */
2053 if (table == NULL) {
2054 table = xmlHashCreateDict(0, dict);
2055 dtd->attributes = (void *) table;
2056 }
2057 if (table == NULL) {
2058 xmlVErrMemory(ctxt,
2059 "xmlAddAttributeDecl: Table creation failed!\n");
2061 return(NULL);
2062 }
2063
2064
2066 if (ret == NULL) {
2067 xmlVErrMemory(ctxt, "malloc failed");
2069 return(NULL);
2070 }
2071 memset(ret, 0, sizeof(xmlAttribute));
2072 ret->type = XML_ATTRIBUTE_DECL;
2073
2074 /*
2075 * fill the structure.
2076 */
2077 ret->atype = type;
2078 /*
2079 * doc must be set before possible error causes call
2080 * to xmlFreeAttribute (because it's used to check on
2081 * dict use)
2082 */
2083 ret->doc = dtd->doc;
2084 if (dict) {
2085 ret->name = xmlDictLookup(dict, name, -1);
2086 ret->prefix = xmlDictLookup(dict, ns, -1);
2087 ret->elem = xmlDictLookup(dict, elem, -1);
2088 } else {
2089 ret->name = xmlStrdup(name);
2090 ret->prefix = xmlStrdup(ns);
2091 ret->elem = xmlStrdup(elem);
2092 }
2093 ret->def = def;
2094 ret->tree = tree;
2095 if (defaultValue != NULL) {
2096 if (dict)
2097 ret->defaultValue = xmlDictLookup(dict, defaultValue, -1);
2098 else
2099 ret->defaultValue = xmlStrdup(defaultValue);
2100 }
2101
2102 /*
2103 * Validity Check:
2104 * Search the DTD for previous declarations of the ATTLIST
2105 */
2106 if (xmlHashAddEntry3(table, ret->name, ret->prefix, ret->elem, ret) < 0) {
2107#ifdef LIBXML_VALID_ENABLED
2108 /*
2109 * The attribute is already defined in this DTD.
2110 */
2111 xmlErrValidWarning(ctxt, (xmlNodePtr) dtd, XML_DTD_ATTRIBUTE_REDEFINED,
2112 "Attribute %s of element %s: already defined\n",
2113 name, elem, NULL);
2114#endif /* LIBXML_VALID_ENABLED */
2116 return(NULL);
2117 }
2118
2119 /*
2120 * Validity Check:
2121 * Multiple ID per element
2122 */
2123 elemDef = xmlGetDtdElementDesc2(dtd, elem, 1);
2124 if (elemDef != NULL) {
2125
2126#ifdef LIBXML_VALID_ENABLED
2127 if ((type == XML_ATTRIBUTE_ID) &&
2128 (xmlScanIDAttributeDecl(NULL, elemDef, 1) != 0)) {
2129 xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_MULTIPLE_ID,
2130 "Element %s has too may ID attributes defined : %s\n",
2131 elem, name, NULL);
2132 if (ctxt != NULL)
2133 ctxt->valid = 0;
2134 }
2135#endif /* LIBXML_VALID_ENABLED */
2136
2137 /*
2138 * Insert namespace default def first they need to be
2139 * processed first.
2140 */
2141 if ((xmlStrEqual(ret->name, BAD_CAST "xmlns")) ||
2142 ((ret->prefix != NULL &&
2143 (xmlStrEqual(ret->prefix, BAD_CAST "xmlns"))))) {
2144 ret->nexth = elemDef->attributes;
2145 elemDef->attributes = ret;
2146 } else {
2147 xmlAttributePtr tmp = elemDef->attributes;
2148
2149 while ((tmp != NULL) &&
2150 ((xmlStrEqual(tmp->name, BAD_CAST "xmlns")) ||
2151 ((ret->prefix != NULL &&
2152 (xmlStrEqual(ret->prefix, BAD_CAST "xmlns")))))) {
2153 if (tmp->nexth == NULL)
2154 break;
2155 tmp = tmp->nexth;
2156 }
2157 if (tmp != NULL) {
2158 ret->nexth = tmp->nexth;
2159 tmp->nexth = ret;
2160 } else {
2161 ret->nexth = elemDef->attributes;
2162 elemDef->attributes = ret;
2163 }
2164 }
2165 }
2166
2167 /*
2168 * Link it to the DTD
2169 */
2170 ret->parent = dtd;
2171 if (dtd->last == NULL) {
2172 dtd->children = dtd->last = (xmlNodePtr) ret;
2173 } else {
2174 dtd->last->next = (xmlNodePtr) ret;
2175 ret->prev = dtd->last;
2176 dtd->last = (xmlNodePtr) ret;
2177 }
2178 return(ret);
2179}
2180
2181static void
2184}
2185
2192void
2195}
2196
2197#ifdef LIBXML_TREE_ENABLED
2206static void *
2207xmlCopyAttribute(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
2210
2212 if (cur == NULL) {
2213 xmlVErrMemory(NULL, "malloc failed");
2214 return(NULL);
2215 }
2216 memset(cur, 0, sizeof(xmlAttribute));
2217 cur->type = XML_ATTRIBUTE_DECL;
2218 cur->atype = attr->atype;
2219 cur->def = attr->def;
2220 cur->tree = xmlCopyEnumeration(attr->tree);
2221 if (attr->elem != NULL)
2222 cur->elem = xmlStrdup(attr->elem);
2223 if (attr->name != NULL)
2224 cur->name = xmlStrdup(attr->name);
2225 if (attr->prefix != NULL)
2226 cur->prefix = xmlStrdup(attr->prefix);
2227 if (attr->defaultValue != NULL)
2228 cur->defaultValue = xmlStrdup(attr->defaultValue);
2229 return(cur);
2230}
2231
2241xmlCopyAttributeTable(xmlAttributeTablePtr table) {
2242 return((xmlAttributeTablePtr) xmlHashCopy(table, xmlCopyAttribute));
2243}
2244#endif /* LIBXML_TREE_ENABLED */
2245
2246#ifdef LIBXML_OUTPUT_ENABLED
2255void
2256xmlDumpAttributeDecl(xmlBufferPtr buf, xmlAttributePtr attr) {
2257 if ((buf == NULL) || (attr == NULL))
2258 return;
2259 xmlBufferWriteChar(buf, "<!ATTLIST ");
2260 xmlBufferWriteCHAR(buf, attr->elem);
2261 xmlBufferWriteChar(buf, " ");
2262 if (attr->prefix != NULL) {
2263 xmlBufferWriteCHAR(buf, attr->prefix);
2264 xmlBufferWriteChar(buf, ":");
2265 }
2267 switch (attr->atype) {
2269 xmlBufferWriteChar(buf, " CDATA");
2270 break;
2271 case XML_ATTRIBUTE_ID:
2272 xmlBufferWriteChar(buf, " ID");
2273 break;
2275 xmlBufferWriteChar(buf, " IDREF");
2276 break;
2278 xmlBufferWriteChar(buf, " IDREFS");
2279 break;
2281 xmlBufferWriteChar(buf, " ENTITY");
2282 break;
2284 xmlBufferWriteChar(buf, " ENTITIES");
2285 break;
2287 xmlBufferWriteChar(buf, " NMTOKEN");
2288 break;
2290 xmlBufferWriteChar(buf, " NMTOKENS");
2291 break;
2293 xmlBufferWriteChar(buf, " (");
2294 xmlDumpEnumeration(buf, attr->tree);
2295 break;
2297 xmlBufferWriteChar(buf, " NOTATION (");
2298 xmlDumpEnumeration(buf, attr->tree);
2299 break;
2300 default:
2301 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
2302 "Internal: ATTRIBUTE struct corrupted invalid type\n",
2303 NULL);
2304 }
2305 switch (attr->def) {
2306 case XML_ATTRIBUTE_NONE:
2307 break;
2309 xmlBufferWriteChar(buf, " #REQUIRED");
2310 break;
2312 xmlBufferWriteChar(buf, " #IMPLIED");
2313 break;
2315 xmlBufferWriteChar(buf, " #FIXED");
2316 break;
2317 default:
2318 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
2319 "Internal: ATTRIBUTE struct corrupted invalid def\n",
2320 NULL);
2321 }
2322 if (attr->defaultValue != NULL) {
2323 xmlBufferWriteChar(buf, " ");
2324 xmlBufferWriteQuotedString(buf, attr->defaultValue);
2325 }
2326 xmlBufferWriteChar(buf, ">\n");
2327}
2328
2336static void
2337xmlDumpAttributeDeclScan(void *attr, void *buf,
2338 const xmlChar *name ATTRIBUTE_UNUSED) {
2339 xmlDumpAttributeDecl((xmlBufferPtr) buf, (xmlAttributePtr) attr);
2340}
2341
2349void
2350xmlDumpAttributeTable(xmlBufferPtr buf, xmlAttributeTablePtr table) {
2351 if ((buf == NULL) || (table == NULL))
2352 return;
2353 xmlHashScan(table, xmlDumpAttributeDeclScan, buf);
2354}
2355#endif /* LIBXML_OUTPUT_ENABLED */
2356
2357/************************************************************************
2358 * *
2359 * NOTATIONs *
2360 * *
2361 ************************************************************************/
2368static void
2370 if (nota == NULL) return;
2371 if (nota->name != NULL)
2372 xmlFree((xmlChar *) nota->name);
2373 if (nota->PublicID != NULL)
2374 xmlFree((xmlChar *) nota->PublicID);
2375 if (nota->SystemID != NULL)
2376 xmlFree((xmlChar *) nota->SystemID);
2377 xmlFree(nota);
2378}
2379
2380
2395 const xmlChar *name,
2396 const xmlChar *PublicID, const xmlChar *SystemID) {
2399
2400 if (dtd == NULL) {
2401 return(NULL);
2402 }
2403 if (name == NULL) {
2404 return(NULL);
2405 }
2406 if ((PublicID == NULL) && (SystemID == NULL)) {
2407 return(NULL);
2408 }
2409
2410 /*
2411 * Create the Notation table if needed.
2412 */
2414 if (table == NULL) {
2415 xmlDictPtr dict = NULL;
2416 if (dtd->doc != NULL)
2417 dict = dtd->doc->dict;
2418
2419 dtd->notations = table = xmlHashCreateDict(0, dict);
2420 }
2421 if (table == NULL) {
2422 xmlVErrMemory(ctxt,
2423 "xmlAddNotationDecl: Table creation failed!\n");
2424 return(NULL);
2425 }
2426
2428 if (ret == NULL) {
2429 xmlVErrMemory(ctxt, "malloc failed");
2430 return(NULL);
2431 }
2432 memset(ret, 0, sizeof(xmlNotation));
2433
2434 /*
2435 * fill the structure.
2436 */
2437 ret->name = xmlStrdup(name);
2438 if (SystemID != NULL)
2439 ret->SystemID = xmlStrdup(SystemID);
2440 if (PublicID != NULL)
2441 ret->PublicID = xmlStrdup(PublicID);
2442
2443 /*
2444 * Validity Check:
2445 * Check the DTD for previous declarations of the ATTLIST
2446 */
2447 if (xmlHashAddEntry(table, name, ret)) {
2448#ifdef LIBXML_VALID_ENABLED
2449 xmlErrValid(NULL, XML_DTD_NOTATION_REDEFINED,
2450 "xmlAddNotationDecl: %s already defined\n",
2451 (const char *) name);
2452#endif /* LIBXML_VALID_ENABLED */
2454 return(NULL);
2455 }
2456 return(ret);
2457}
2458
2459static void
2462}
2463
2470void
2473}
2474
2475#ifdef LIBXML_TREE_ENABLED
2484static void *
2485xmlCopyNotation(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
2486 xmlNotationPtr nota = (xmlNotationPtr) payload;
2488
2490 if (cur == NULL) {
2491 xmlVErrMemory(NULL, "malloc failed");
2492 return(NULL);
2493 }
2494 if (nota->name != NULL)
2495 cur->name = xmlStrdup(nota->name);
2496 else
2497 cur->name = NULL;
2498 if (nota->PublicID != NULL)
2499 cur->PublicID = xmlStrdup(nota->PublicID);
2500 else
2501 cur->PublicID = NULL;
2502 if (nota->SystemID != NULL)
2503 cur->SystemID = xmlStrdup(nota->SystemID);
2504 else
2505 cur->SystemID = NULL;
2506 return(cur);
2507}
2508
2518xmlCopyNotationTable(xmlNotationTablePtr table) {
2519 return((xmlNotationTablePtr) xmlHashCopy(table, xmlCopyNotation));
2520}
2521#endif /* LIBXML_TREE_ENABLED */
2522
2523#ifdef LIBXML_OUTPUT_ENABLED
2531void
2532xmlDumpNotationDecl(xmlBufferPtr buf, xmlNotationPtr nota) {
2533 if ((buf == NULL) || (nota == NULL))
2534 return;
2535 xmlBufferWriteChar(buf, "<!NOTATION ");
2536 xmlBufferWriteCHAR(buf, nota->name);
2537 if (nota->PublicID != NULL) {
2538 xmlBufferWriteChar(buf, " PUBLIC ");
2540 if (nota->SystemID != NULL) {
2541 xmlBufferWriteChar(buf, " ");
2543 }
2544 } else {
2545 xmlBufferWriteChar(buf, " SYSTEM ");
2547 }
2548 xmlBufferWriteChar(buf, " >\n");
2549}
2550
2558static void
2559xmlDumpNotationDeclScan(void *nota, void *buf,
2560 const xmlChar *name ATTRIBUTE_UNUSED) {
2561 xmlDumpNotationDecl((xmlBufferPtr) buf, (xmlNotationPtr) nota);
2562}
2563
2571void
2572xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
2573 if ((buf == NULL) || (table == NULL))
2574 return;
2575 xmlHashScan(table, xmlDumpNotationDeclScan, buf);
2576}
2577#endif /* LIBXML_OUTPUT_ENABLED */
2578
2579/************************************************************************
2580 * *
2581 * IDs *
2582 * *
2583 ************************************************************************/
2591#define DICT_FREE(str) \
2592 if ((str) && ((!dict) || \
2593 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
2594 xmlFree((char *)(str));
2595
2602static void
2604 xmlChar *dst;
2605 const xmlChar *src;
2606
2607 if (str == NULL)
2608 return;
2609 src = str;
2610 dst = str;
2611
2612 while (*src == 0x20) src++;
2613 while (*src != 0) {
2614 if (*src == 0x20) {
2615 while (*src == 0x20) src++;
2616 if (*src != 0)
2617 *dst++ = 0x20;
2618 } else {
2619 *dst++ = *src++;
2620 }
2621 }
2622 *dst = 0;
2623}
2624
2625static int
2627 xmlParserCtxtPtr pctxt;
2628
2629 if (ctxt == NULL)
2630 return(0);
2631 if ((ctxt->flags & XML_VCTXT_USE_PCTXT) == 0)
2632 return(0);
2633 pctxt = ctxt->userData;
2634 return(pctxt->parseMode == XML_PARSE_READER);
2635}
2636
2643static void
2645 xmlDictPtr dict = NULL;
2646
2647 if (id == NULL) return;
2648
2649 if (id->doc != NULL)
2650 dict = id->doc->dict;
2651
2652 if (id->value != NULL)
2653 DICT_FREE(id->value)
2654 if (id->name != NULL)
2655 DICT_FREE(id->name)
2656 xmlFree(id);
2657}
2658
2659
2673 xmlAttrPtr attr) {
2674 xmlIDPtr ret;
2676
2677 if (doc == NULL) {
2678 return(NULL);
2679 }
2680 if ((value == NULL) || (value[0] == 0)) {
2681 return(NULL);
2682 }
2683 if (attr == NULL) {
2684 return(NULL);
2685 }
2686
2687 /*
2688 * Create the ID table if needed.
2689 */
2690 table = (xmlIDTablePtr) doc->ids;
2691 if (table == NULL) {
2692 doc->ids = table = xmlHashCreateDict(0, doc->dict);
2693 }
2694 if (table == NULL) {
2695 xmlVErrMemory(ctxt,
2696 "xmlAddID: Table creation failed!\n");
2697 return(NULL);
2698 }
2699
2700 ret = (xmlIDPtr) xmlMalloc(sizeof(xmlID));
2701 if (ret == NULL) {
2702 xmlVErrMemory(ctxt, "malloc failed");
2703 return(NULL);
2704 }
2705
2706 /*
2707 * fill the structure.
2708 */
2709 ret->value = xmlStrdup(value);
2710 ret->doc = doc;
2711 if (xmlIsStreaming(ctxt)) {
2712 /*
2713 * Operating in streaming mode, attr is gonna disappear
2714 */
2715 if (doc->dict != NULL)
2716 ret->name = xmlDictLookup(doc->dict, attr->name, -1);
2717 else
2718 ret->name = xmlStrdup(attr->name);
2719 ret->attr = NULL;
2720 } else {
2721 ret->attr = attr;
2722 ret->name = NULL;
2723 }
2724 ret->lineno = xmlGetLineNo(attr->parent);
2725
2726 if (xmlHashAddEntry(table, value, ret) < 0) {
2727#ifdef LIBXML_VALID_ENABLED
2728 /*
2729 * The id is already defined in this DTD.
2730 */
2731 if (ctxt != NULL) {
2732 xmlErrValidNode(ctxt, attr->parent, XML_DTD_ID_REDEFINED,
2733 "ID %s already defined\n", value, NULL, NULL);
2734 }
2735#endif /* LIBXML_VALID_ENABLED */
2736 xmlFreeID(ret);
2737 return(NULL);
2738 }
2739 if (attr != NULL)
2740 attr->atype = XML_ATTRIBUTE_ID;
2741 return(ret);
2742}
2743
2744static void
2746 xmlFreeID((xmlIDPtr) id);
2747}
2748
2755void
2758}
2759
2773int
2775 if ((attr == NULL) || (attr->name == NULL)) return(0);
2776 if ((attr->ns != NULL) && (attr->ns->prefix != NULL) &&
2777 (!strcmp((char *) attr->name, "id")) &&
2778 (!strcmp((char *) attr->ns->prefix, "xml")))
2779 return(1);
2780 if (doc == NULL) return(0);
2781 if ((doc->intSubset == NULL) && (doc->extSubset == NULL) &&
2782 (doc->type != XML_HTML_DOCUMENT_NODE)) {
2783 return(0);
2784 } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
2785 if ((xmlStrEqual(BAD_CAST "id", attr->name)) ||
2786 ((xmlStrEqual(BAD_CAST "name", attr->name)) &&
2787 ((elem == NULL) || (xmlStrEqual(elem->name, BAD_CAST "a")))))
2788 return(1);
2789 return(0);
2790 } else if (elem == NULL) {
2791 return(0);
2792 } else {
2793 xmlAttributePtr attrDecl = NULL;
2794
2795 xmlChar felem[50], fattr[50];
2796 xmlChar *fullelemname, *fullattrname;
2797
2798 fullelemname = (elem->ns != NULL && elem->ns->prefix != NULL) ?
2799 xmlBuildQName(elem->name, elem->ns->prefix, felem, 50) :
2800 (xmlChar *)elem->name;
2801
2802 fullattrname = (attr->ns != NULL && attr->ns->prefix != NULL) ?
2803 xmlBuildQName(attr->name, attr->ns->prefix, fattr, 50) :
2804 (xmlChar *)attr->name;
2805
2806 if (fullelemname != NULL && fullattrname != NULL) {
2807 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullelemname,
2808 fullattrname);
2809 if ((attrDecl == NULL) && (doc->extSubset != NULL))
2810 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullelemname,
2811 fullattrname);
2812 }
2813
2814 if ((fullattrname != fattr) && (fullattrname != attr->name))
2815 xmlFree(fullattrname);
2816 if ((fullelemname != felem) && (fullelemname != elem->name))
2817 xmlFree(fullelemname);
2818
2819 if ((attrDecl != NULL) && (attrDecl->atype == XML_ATTRIBUTE_ID))
2820 return(1);
2821 }
2822 return(0);
2823}
2824
2834int
2837 xmlIDPtr id;
2838 xmlChar *ID;
2839
2840 if (doc == NULL) return(-1);
2841 if (attr == NULL) return(-1);
2842
2843 table = (xmlIDTablePtr) doc->ids;
2844 if (table == NULL)
2845 return(-1);
2846
2847 ID = xmlNodeListGetString(doc, attr->children, 1);
2848 if (ID == NULL)
2849 return(-1);
2851
2852 id = xmlHashLookup(table, ID);
2853 if (id == NULL || id->attr != attr) {
2854 xmlFree(ID);
2855 return(-1);
2856 }
2857
2859 xmlFree(ID);
2860 attr->atype = 0;
2861 return(0);
2862}
2863
2876 xmlIDPtr id;
2877
2878 if (doc == NULL) {
2879 return(NULL);
2880 }
2881
2882 if (ID == NULL) {
2883 return(NULL);
2884 }
2885
2886 table = (xmlIDTablePtr) doc->ids;
2887 if (table == NULL)
2888 return(NULL);
2889
2890 id = xmlHashLookup(table, ID);
2891 if (id == NULL)
2892 return(NULL);
2893 if (id->attr == NULL) {
2894 /*
2895 * We are operating on a stream, return a well known reference
2896 * since the attribute node doesn't exist anymore
2897 */
2898 return((xmlAttrPtr) doc);
2899 }
2900 return(id->attr);
2901}
2902
2903/************************************************************************
2904 * *
2905 * Refs *
2906 * *
2907 ************************************************************************/
2908typedef struct xmlRemoveMemo_t
2909{
2913
2915
2916typedef struct xmlValidateMemo_t
2917{
2921
2923
2930static void
2933 if (ref == NULL) return;
2934 if (ref->value != NULL)
2935 xmlFree((xmlChar *)ref->value);
2936 if (ref->name != NULL)
2937 xmlFree((xmlChar *)ref->name);
2938 xmlFree(ref);
2939}
2940
2947static void
2949 xmlListPtr list_ref = (xmlListPtr) payload;
2950 if (list_ref == NULL) return;
2951 xmlListDelete(list_ref);
2952}
2953
2961static int
2962xmlWalkRemoveRef(const void *data, void *user)
2963{
2964 xmlAttrPtr attr0 = ((xmlRefPtr)data)->attr;
2965 xmlAttrPtr attr1 = ((xmlRemoveMemoPtr)user)->ap;
2966 xmlListPtr ref_list = ((xmlRemoveMemoPtr)user)->l;
2967
2968 if (attr0 == attr1) { /* Matched: remove and terminate walk */
2969 xmlListRemoveFirst(ref_list, (void *)data);
2970 return 0;
2971 }
2972 return 1;
2973}
2974
2982static int
2984 const void *data1 ATTRIBUTE_UNUSED)
2985{
2986 return (0);
2987}
2988
3004 xmlAttrPtr attr) {
3005 xmlRefPtr ret;
3007 xmlListPtr ref_list;
3008
3009 if (doc == NULL) {
3010 return(NULL);
3011 }
3012 if (value == NULL) {
3013 return(NULL);
3014 }
3015 if (attr == NULL) {
3016 return(NULL);
3017 }
3018
3019 /*
3020 * Create the Ref table if needed.
3021 */
3022 table = (xmlRefTablePtr) doc->refs;
3023 if (table == NULL) {
3024 doc->refs = table = xmlHashCreateDict(0, doc->dict);
3025 }
3026 if (table == NULL) {
3027 xmlVErrMemory(ctxt,
3028 "xmlAddRef: Table creation failed!\n");
3029 return(NULL);
3030 }
3031
3032 ret = (xmlRefPtr) xmlMalloc(sizeof(xmlRef));
3033 if (ret == NULL) {
3034 xmlVErrMemory(ctxt, "malloc failed");
3035 return(NULL);
3036 }
3037
3038 /*
3039 * fill the structure.
3040 */
3041 ret->value = xmlStrdup(value);
3042 if (xmlIsStreaming(ctxt)) {
3043 /*
3044 * Operating in streaming mode, attr is gonna disappear
3045 */
3046 ret->name = xmlStrdup(attr->name);
3047 ret->attr = NULL;
3048 } else {
3049 ret->name = NULL;
3050 ret->attr = attr;
3051 }
3052 ret->lineno = xmlGetLineNo(attr->parent);
3053
3054 /* To add a reference :-
3055 * References are maintained as a list of references,
3056 * Lookup the entry, if no entry create new nodelist
3057 * Add the owning node to the NodeList
3058 * Return the ref
3059 */
3060
3061 if (NULL == (ref_list = xmlHashLookup(table, value))) {
3062 if (NULL == (ref_list = xmlListCreate(xmlFreeRef, xmlDummyCompare))) {
3063 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
3064 "xmlAddRef: Reference list creation failed!\n",
3065 NULL);
3066 goto failed;
3067 }
3068 if (xmlHashAddEntry(table, value, ref_list) < 0) {
3069 xmlListDelete(ref_list);
3070 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
3071 "xmlAddRef: Reference list insertion failed!\n",
3072 NULL);
3073 goto failed;
3074 }
3075 }
3076 if (xmlListAppend(ref_list, ret) != 0) {
3077 xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
3078 "xmlAddRef: Reference list insertion failed!\n",
3079 NULL);
3080 goto failed;
3081 }
3082 return(ret);
3083failed:
3084 if (ret != NULL) {
3085 if (ret->value != NULL)
3086 xmlFree((char *)ret->value);
3087 if (ret->name != NULL)
3088 xmlFree((char *)ret->name);
3089 xmlFree(ret);
3090 }
3091 return(NULL);
3092}
3093
3102void
3105}
3106
3121int
3123 if (attr == NULL)
3124 return(0);
3125 if (doc == NULL) {
3126 doc = attr->doc;
3127 if (doc == NULL) return(0);
3128 }
3129
3130 if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) {
3131 return(0);
3132 } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
3133 /* TODO @@@ */
3134 return(0);
3135 } else {
3136 xmlAttributePtr attrDecl;
3137
3138 if (elem == NULL) return(0);
3139 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, attr->name);
3140 if ((attrDecl == NULL) && (doc->extSubset != NULL))
3141 attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
3142 elem->name, attr->name);
3143
3144 if ((attrDecl != NULL) &&
3145 (attrDecl->atype == XML_ATTRIBUTE_IDREF ||
3146 attrDecl->atype == XML_ATTRIBUTE_IDREFS))
3147 return(1);
3148 }
3149 return(0);
3150}
3151
3163int
3165 xmlListPtr ref_list;
3167 xmlChar *ID;
3169
3170 if (doc == NULL) return(-1);
3171 if (attr == NULL) return(-1);
3172
3173 table = (xmlRefTablePtr) doc->refs;
3174 if (table == NULL)
3175 return(-1);
3176
3177 ID = xmlNodeListGetString(doc, attr->children, 1);
3178 if (ID == NULL)
3179 return(-1);
3180
3181 ref_list = xmlHashLookup(table, ID);
3182 if(ref_list == NULL) {
3183 xmlFree(ID);
3184 return (-1);
3185 }
3186
3187 /* At this point, ref_list refers to a list of references which
3188 * have the same key as the supplied attr. Our list of references
3189 * is ordered by reference address and we don't have that information
3190 * here to use when removing. We'll have to walk the list and
3191 * check for a matching attribute, when we find one stop the walk
3192 * and remove the entry.
3193 * The list is ordered by reference, so that means we don't have the
3194 * key. Passing the list and the reference to the walker means we
3195 * will have enough data to be able to remove the entry.
3196 */
3197 target.l = ref_list;
3198 target.ap = attr;
3199
3200 /* Remove the supplied attr from our list */
3201 xmlListWalk(ref_list, xmlWalkRemoveRef, &target);
3202
3203 /*If the list is empty then remove the list entry in the hash */
3204 if (xmlListEmpty(ref_list))
3206 xmlFree(ID);
3207 return(0);
3208}
3209
3224
3225 if (doc == NULL) {
3226 return(NULL);
3227 }
3228
3229 if (ID == NULL) {
3230 return(NULL);
3231 }
3232
3233 table = (xmlRefTablePtr) doc->refs;
3234 if (table == NULL)
3235 return(NULL);
3236
3237 return (xmlHashLookup(table, ID));
3238}
3239
3240/************************************************************************
3241 * *
3242 * Routines for validity checking *
3243 * *
3244 ************************************************************************/
3245
3260 xmlChar *uqname = NULL, *prefix = NULL;
3261
3262 if ((dtd == NULL) || (name == NULL)) return(NULL);
3263 if (dtd->elements == NULL)
3264 return(NULL);
3266
3267 uqname = xmlSplitQName2(name, &prefix);
3268 if (uqname != NULL)
3269 name = uqname;
3270 cur = xmlHashLookup2(table, name, prefix);
3271 if (prefix != NULL) xmlFree(prefix);
3272 if (uqname != NULL) xmlFree(uqname);
3273 return(cur);
3274}
3286static xmlElementPtr
3290 xmlChar *uqname = NULL, *prefix = NULL;
3291
3292 if (dtd == NULL) return(NULL);
3293 if (dtd->elements == NULL) {
3294 xmlDictPtr dict = NULL;
3295
3296 if (dtd->doc != NULL)
3297 dict = dtd->doc->dict;
3298
3299 if (!create)
3300 return(NULL);
3301 /*
3302 * Create the Element table if needed.
3303 */
3305 if (table == NULL) {
3306 table = xmlHashCreateDict(0, dict);
3307 dtd->elements = (void *) table;
3308 }
3309 if (table == NULL) {
3310 xmlVErrMemory(NULL, "element table allocation failed");
3311 return(NULL);
3312 }
3313 }
3315
3316 uqname = xmlSplitQName2(name, &prefix);
3317 if (uqname != NULL)
3318 name = uqname;
3319 cur = xmlHashLookup2(table, name, prefix);
3320 if ((cur == NULL) && (create)) {
3322 if (cur == NULL) {
3323 xmlVErrMemory(NULL, "malloc failed");
3324 return(NULL);
3325 }
3326 memset(cur, 0, sizeof(xmlElement));
3327 cur->type = XML_ELEMENT_DECL;
3328
3329 /*
3330 * fill the structure.
3331 */
3332 cur->name = xmlStrdup(name);
3333 cur->prefix = xmlStrdup(prefix);
3335
3336 xmlHashAddEntry2(table, name, prefix, cur);
3337 }
3338 if (prefix != NULL) xmlFree(prefix);
3339 if (uqname != NULL) xmlFree(uqname);
3340 return(cur);
3341}
3342
3356 const xmlChar *prefix) {
3358
3359 if (dtd == NULL) return(NULL);
3360 if (dtd->elements == NULL) return(NULL);
3362
3363 return(xmlHashLookup2(table, name, prefix));
3364}
3365
3382 xmlChar *uqname = NULL, *prefix = NULL;
3383
3384 if (dtd == NULL) return(NULL);
3385 if (dtd->attributes == NULL) return(NULL);
3386
3388 if (table == NULL)
3389 return(NULL);
3390
3391 uqname = xmlSplitQName2(name, &prefix);
3392
3393 if (uqname != NULL) {
3394 cur = xmlHashLookup3(table, uqname, prefix, elem);
3395 if (prefix != NULL) xmlFree(prefix);
3396 if (uqname != NULL) xmlFree(uqname);
3397 } else
3399 return(cur);
3400}
3401
3417 const xmlChar *prefix) {
3419
3420 if (dtd == NULL) return(NULL);
3421 if (dtd->attributes == NULL) return(NULL);
3423
3424 return(xmlHashLookup3(table, name, prefix, elem));
3425}
3426
3440
3441 if (dtd == NULL) return(NULL);
3442 if (dtd->notations == NULL) return(NULL);
3444
3445 return(xmlHashLookup(table, name));
3446}
3447
3448#if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
3461int
3462xmlValidateNotationUse(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
3463 const xmlChar *notationName) {
3464 xmlNotationPtr notaDecl;
3465 if ((doc == NULL) || (doc->intSubset == NULL) ||
3466 (notationName == NULL)) return(-1);
3467
3468 notaDecl = xmlGetDtdNotationDesc(doc->intSubset, notationName);
3469 if ((notaDecl == NULL) && (doc->extSubset != NULL))
3470 notaDecl = xmlGetDtdNotationDesc(doc->extSubset, notationName);
3471
3472 if ((notaDecl == NULL) && (ctxt != NULL)) {
3473 xmlErrValidNode(ctxt, (xmlNodePtr) doc, XML_DTD_UNKNOWN_NOTATION,
3474 "NOTATION %s is not declared\n",
3475 notationName, NULL, NULL);
3476 return(0);
3477 }
3478 return(1);
3479}
3480#endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */
3481
3493int
3495 xmlElementPtr elemDecl;
3496
3497 if ((doc == NULL) || (doc->intSubset == NULL)) return(-1);
3498
3499 elemDecl = xmlGetDtdElementDesc(doc->intSubset, name);
3500 if ((elemDecl == NULL) && (doc->extSubset != NULL))
3501 elemDecl = xmlGetDtdElementDesc(doc->extSubset, name);
3502 if (elemDecl == NULL) return(-1);
3503 switch (elemDecl->etype) {
3505 return(-1);
3507 return(0);
3509 /*
3510 * return 1 for EMPTY since we want VC error to pop up
3511 * on <empty> </empty> for example
3512 */
3515 return(1);
3516 }
3517 return(1);
3518}
3519
3520#ifdef LIBXML_VALID_ENABLED
3521
3522static int
3523xmlIsDocNameStartChar(xmlDocPtr doc, int c) {
3524 if ((doc == NULL) || (doc->properties & XML_DOC_OLD10) == 0) {
3525 /*
3526 * Use the new checks of production [4] [4a] amd [5] of the
3527 * Update 5 of XML-1.0
3528 */
3529 if (((c >= 'a') && (c <= 'z')) ||
3530 ((c >= 'A') && (c <= 'Z')) ||
3531 (c == '_') || (c == ':') ||
3532 ((c >= 0xC0) && (c <= 0xD6)) ||
3533 ((c >= 0xD8) && (c <= 0xF6)) ||
3534 ((c >= 0xF8) && (c <= 0x2FF)) ||
3535 ((c >= 0x370) && (c <= 0x37D)) ||
3536 ((c >= 0x37F) && (c <= 0x1FFF)) ||
3537 ((c >= 0x200C) && (c <= 0x200D)) ||
3538 ((c >= 0x2070) && (c <= 0x218F)) ||
3539 ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3540 ((c >= 0x3001) && (c <= 0xD7FF)) ||
3541 ((c >= 0xF900) && (c <= 0xFDCF)) ||
3542 ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3543 ((c >= 0x10000) && (c <= 0xEFFFF)))
3544 return(1);
3545 } else {
3546 if (IS_LETTER(c) || (c == '_') || (c == ':'))
3547 return(1);
3548 }
3549 return(0);
3550}
3551
3552static int
3553xmlIsDocNameChar(xmlDocPtr doc, int c) {
3554 if ((doc == NULL) || (doc->properties & XML_DOC_OLD10) == 0) {
3555 /*
3556 * Use the new checks of production [4] [4a] amd [5] of the
3557 * Update 5 of XML-1.0
3558 */
3559 if (((c >= 'a') && (c <= 'z')) ||
3560 ((c >= 'A') && (c <= 'Z')) ||
3561 ((c >= '0') && (c <= '9')) || /* !start */
3562 (c == '_') || (c == ':') ||
3563 (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3564 ((c >= 0xC0) && (c <= 0xD6)) ||
3565 ((c >= 0xD8) && (c <= 0xF6)) ||
3566 ((c >= 0xF8) && (c <= 0x2FF)) ||
3567 ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3568 ((c >= 0x370) && (c <= 0x37D)) ||
3569 ((c >= 0x37F) && (c <= 0x1FFF)) ||
3570 ((c >= 0x200C) && (c <= 0x200D)) ||
3571 ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3572 ((c >= 0x2070) && (c <= 0x218F)) ||
3573 ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3574 ((c >= 0x3001) && (c <= 0xD7FF)) ||
3575 ((c >= 0xF900) && (c <= 0xFDCF)) ||
3576 ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3577 ((c >= 0x10000) && (c <= 0xEFFFF)))
3578 return(1);
3579 } else {
3580 if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3581 (c == '.') || (c == '-') ||
3582 (c == '_') || (c == ':') ||
3583 (IS_COMBINING(c)) ||
3584 (IS_EXTENDER(c)))
3585 return(1);
3586 }
3587 return(0);
3588}
3589
3600static int
3601xmlValidateNameValueInternal(xmlDocPtr doc, const xmlChar *value) {
3602 const xmlChar *cur;
3603 int val, len;
3604
3605 if (value == NULL) return(0);
3606 cur = value;
3608 cur += len;
3609 if (!xmlIsDocNameStartChar(doc, val))
3610 return(0);
3611
3613 cur += len;
3614 while (xmlIsDocNameChar(doc, val)) {
3616 cur += len;
3617 }
3618
3619 if (val != 0) return(0);
3620
3621 return(1);
3622}
3623
3633int
3634xmlValidateNameValue(const xmlChar *value) {
3635 return(xmlValidateNameValueInternal(NULL, value));
3636}
3637
3648static int
3649xmlValidateNamesValueInternal(xmlDocPtr doc, const xmlChar *value) {
3650 const xmlChar *cur;
3651 int val, len;
3652
3653 if (value == NULL) return(0);
3654 cur = value;
3656 cur += len;
3657
3658 if (!xmlIsDocNameStartChar(doc, val))
3659 return(0);
3660
3662 cur += len;
3663 while (xmlIsDocNameChar(doc, val)) {
3665 cur += len;
3666 }
3667
3668 /* Should not test IS_BLANK(val) here -- see erratum E20*/
3669 while (val == 0x20) {
3670 while (val == 0x20) {
3672 cur += len;
3673 }
3674
3675 if (!xmlIsDocNameStartChar(doc, val))
3676 return(0);
3677
3679 cur += len;
3680
3681 while (xmlIsDocNameChar(doc, val)) {
3683 cur += len;
3684 }
3685 }
3686
3687 if (val != 0) return(0);
3688
3689 return(1);
3690}
3691
3701int
3702xmlValidateNamesValue(const xmlChar *value) {
3703 return(xmlValidateNamesValueInternal(NULL, value));
3704}
3705
3718static int
3719xmlValidateNmtokenValueInternal(xmlDocPtr doc, const xmlChar *value) {
3720 const xmlChar *cur;
3721 int val, len;
3722
3723 if (value == NULL) return(0);
3724 cur = value;
3726 cur += len;
3727
3728 if (!xmlIsDocNameChar(doc, val))
3729 return(0);
3730
3732 cur += len;
3733 while (xmlIsDocNameChar(doc, val)) {
3735 cur += len;
3736 }
3737
3738 if (val != 0) return(0);
3739
3740 return(1);
3741}
3742
3754int
3755xmlValidateNmtokenValue(const xmlChar *value) {
3756 return(xmlValidateNmtokenValueInternal(NULL, value));
3757}
3758
3771static int
3772xmlValidateNmtokensValueInternal(xmlDocPtr doc, const xmlChar *value) {
3773 const xmlChar *cur;
3774 int val, len;
3775
3776 if (value == NULL) return(0);
3777 cur = value;
3779 cur += len;
3780
3781 while (IS_BLANK(val)) {
3783 cur += len;
3784 }
3785
3786 if (!xmlIsDocNameChar(doc, val))
3787 return(0);
3788
3789 while (xmlIsDocNameChar(doc, val)) {
3791 cur += len;
3792 }
3793
3794 /* Should not test IS_BLANK(val) here -- see erratum E20*/
3795 while (val == 0x20) {
3796 while (val == 0x20) {
3798 cur += len;
3799 }
3800 if (val == 0) return(1);
3801
3802 if (!xmlIsDocNameChar(doc, val))
3803 return(0);
3804
3806 cur += len;
3807
3808 while (xmlIsDocNameChar(doc, val)) {
3810 cur += len;
3811 }
3812 }
3813
3814 if (val != 0) return(0);
3815
3816 return(1);
3817}
3818
3830int
3831xmlValidateNmtokensValue(const xmlChar *value) {
3832 return(xmlValidateNmtokensValueInternal(NULL, value));
3833}
3834
3850int
3851xmlValidateNotationDecl(xmlValidCtxtPtr ctxt ATTRIBUTE_UNUSED, xmlDocPtr doc ATTRIBUTE_UNUSED,
3853 int ret = 1;
3854
3855 return(ret);
3856}
3857
3869static int
3870xmlValidateAttributeValueInternal(xmlDocPtr doc, xmlAttributeType type,
3871 const xmlChar *value) {
3872 switch (type) {
3875 return(xmlValidateNamesValueInternal(doc, value));
3878 case XML_ATTRIBUTE_ID:
3880 return(xmlValidateNameValueInternal(doc, value));
3883 return(xmlValidateNmtokensValueInternal(doc, value));
3885 return(xmlValidateNmtokenValueInternal(doc, value));
3887 break;
3888 }
3889 return(1);
3890}
3891
3916int
3917xmlValidateAttributeValue(xmlAttributeType type, const xmlChar *value) {
3918 return(xmlValidateAttributeValueInternal(NULL, type, value));
3919}
3920
3950static int
3951xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
3952 const xmlChar *name, xmlAttributeType type, const xmlChar *value) {
3953 int ret = 1;
3954 switch (type) {
3957 case XML_ATTRIBUTE_ID:
3962 break;
3963 case XML_ATTRIBUTE_ENTITY: {
3964 xmlEntityPtr ent;
3965
3966 ent = xmlGetDocEntity(doc, value);
3967 /* yeah it's a bit messy... */
3968 if ((ent == NULL) && (doc->standalone == 1)) {
3969 doc->standalone = 0;
3970 ent = xmlGetDocEntity(doc, value);
3971 }
3972 if (ent == NULL) {
3973 xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3975 "ENTITY attribute %s reference an unknown entity \"%s\"\n",
3976 name, value, NULL);
3977 ret = 0;
3978 } else if (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
3979 xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3981 "ENTITY attribute %s reference an entity \"%s\" of wrong type\n",
3982 name, value, NULL);
3983 ret = 0;
3984 }
3985 break;
3986 }
3988 xmlChar *dup, *nam = NULL, *cur, save;
3989 xmlEntityPtr ent;
3990
3991 dup = xmlStrdup(value);
3992 if (dup == NULL)
3993 return(0);
3994 cur = dup;
3995 while (*cur != 0) {
3996 nam = cur;
3997 while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
3998 save = *cur;
3999 *cur = 0;
4000 ent = xmlGetDocEntity(doc, nam);
4001 if (ent == NULL) {
4002 xmlErrValidNode(ctxt, (xmlNodePtr) doc,
4004 "ENTITIES attribute %s reference an unknown entity \"%s\"\n",
4005 name, nam, NULL);
4006 ret = 0;
4007 } else if (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
4008 xmlErrValidNode(ctxt, (xmlNodePtr) doc,
4010 "ENTITIES attribute %s reference an entity \"%s\" of wrong type\n",
4011 name, nam, NULL);
4012 ret = 0;
4013 }
4014 if (save == 0)
4015 break;
4016 *cur = save;
4017 while (IS_BLANK_CH(*cur)) cur++;
4018 }
4019 xmlFree(dup);
4020 break;
4021 }
4023 xmlNotationPtr nota;
4024
4026 if ((nota == NULL) && (doc->extSubset != NULL))
4028
4029 if (nota == NULL) {
4030 xmlErrValidNode(ctxt, (xmlNodePtr) doc,
4032 "NOTATION attribute %s reference an unknown notation \"%s\"\n",
4033 name, value, NULL);
4034 ret = 0;
4035 }
4036 break;
4037 }
4038 }
4039 return(ret);
4040}
4041
4066xmlChar *
4067xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
4068 xmlNodePtr elem, const xmlChar *name, const xmlChar *value) {
4069 xmlChar *ret;
4070 xmlAttributePtr attrDecl = NULL;
4071 int extsubset = 0;
4072
4073 if (doc == NULL) return(NULL);
4074 if (elem == NULL) return(NULL);
4075 if (name == NULL) return(NULL);
4076 if (value == NULL) return(NULL);
4077
4078 if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
4079 xmlChar fn[50];
4081
4082 fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
4083 if (fullname == NULL)
4084 return(NULL);
4085 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, name);
4086 if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
4087 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname, name);
4088 if (attrDecl != NULL)
4089 extsubset = 1;
4090 }
4091 if ((fullname != fn) && (fullname != elem->name))
4093 }
4094 if ((attrDecl == NULL) && (doc->intSubset != NULL))
4095 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name);
4096 if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
4097 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, name);
4098 if (attrDecl != NULL)
4099 extsubset = 1;
4100 }
4101
4102 if (attrDecl == NULL)
4103 return(NULL);
4104 if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
4105 return(NULL);
4106
4107 ret = xmlStrdup(value);
4108 if (ret == NULL)
4109 return(NULL);
4111 if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) {
4112 xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE,
4113"standalone: %s on %s value had to be normalized based on external subset declaration\n",
4114 name, elem->name, NULL);
4115 ctxt->valid = 0;
4116 }
4117 return(ret);
4118}
4119
4139xmlChar *
4140xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
4141 const xmlChar *name, const xmlChar *value) {
4142 xmlChar *ret;
4143 xmlAttributePtr attrDecl = NULL;
4144
4145 if (doc == NULL) return(NULL);
4146 if (elem == NULL) return(NULL);
4147 if (name == NULL) return(NULL);
4148 if (value == NULL) return(NULL);
4149
4150 if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
4151 xmlChar fn[50];
4153
4154 fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
4155 if (fullname == NULL)
4156 return(NULL);
4157 if ((fullname != fn) && (fullname != elem->name))
4159 }
4160 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name);
4161 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4162 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, name);
4163
4164 if (attrDecl == NULL)
4165 return(NULL);
4166 if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
4167 return(NULL);
4168
4169 ret = xmlStrdup(value);
4170 if (ret == NULL)
4171 return(NULL);
4173 return(ret);
4174}
4175
4176static void
4177xmlValidateAttributeIdCallback(void *payload, void *data,
4178 const xmlChar *name ATTRIBUTE_UNUSED) {
4180 int *count = (int *) data;
4181 if (attr->atype == XML_ATTRIBUTE_ID) (*count)++;
4182}
4183
4202int
4203xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
4205 int ret = 1;
4206 int val;
4207 CHECK_DTD;
4208 if(attr == NULL) return(1);
4209
4210 /* Attribute Default Legal */
4211 /* Enumeration */
4212 if (attr->defaultValue != NULL) {
4213 val = xmlValidateAttributeValueInternal(doc, attr->atype,
4214 attr->defaultValue);
4215 if (val == 0) {
4216 xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ATTRIBUTE_DEFAULT,
4217 "Syntax of default value for attribute %s of %s is not valid\n",
4218 attr->name, attr->elem, NULL);
4219 }
4220 ret &= val;
4221 }
4222
4223 /* ID Attribute Default */
4224 if ((attr->atype == XML_ATTRIBUTE_ID)&&
4225 (attr->def != XML_ATTRIBUTE_IMPLIED) &&
4226 (attr->def != XML_ATTRIBUTE_REQUIRED)) {
4227 xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_FIXED,
4228 "ID attribute %s of %s is not valid must be #IMPLIED or #REQUIRED\n",
4229 attr->name, attr->elem, NULL);
4230 ret = 0;
4231 }
4232
4233 /* One ID per Element Type */
4234 if (attr->atype == XML_ATTRIBUTE_ID) {
4235 int nbId;
4236
4237 /* the trick is that we parse DtD as their own internal subset */
4239 attr->elem);
4240 if (elem != NULL) {
4241 nbId = xmlScanIDAttributeDecl(NULL, elem, 0);
4242 } else {
4244
4245 /*
4246 * The attribute may be declared in the internal subset and the
4247 * element in the external subset.
4248 */
4249 nbId = 0;
4250 if (doc->intSubset != NULL) {
4251 table = (xmlAttributeTablePtr) doc->intSubset->attributes;
4252 xmlHashScan3(table, NULL, NULL, attr->elem,
4253 xmlValidateAttributeIdCallback, &nbId);
4254 }
4255 }
4256 if (nbId > 1) {
4257
4258 xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
4259 "Element %s has %d ID attribute defined in the internal subset : %s\n",
4260 attr->elem, nbId, attr->name);
4261 } else if (doc->extSubset != NULL) {
4262 int extId = 0;
4263 elem = xmlGetDtdElementDesc(doc->extSubset, attr->elem);
4264 if (elem != NULL) {
4265 extId = xmlScanIDAttributeDecl(NULL, elem, 0);
4266 }
4267 if (extId > 1) {
4268 xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
4269 "Element %s has %d ID attribute defined in the external subset : %s\n",
4270 attr->elem, extId, attr->name);
4271 } else if (extId + nbId > 1) {
4272 xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
4273"Element %s has ID attributes defined in the internal and external subset : %s\n",
4274 attr->elem, attr->name, NULL);
4275 }
4276 }
4277 }
4278
4279 /* Validity Constraint: Enumeration */
4280 if ((attr->defaultValue != NULL) && (attr->tree != NULL)) {
4281 xmlEnumerationPtr tree = attr->tree;
4282 while (tree != NULL) {
4283 if (xmlStrEqual(tree->name, attr->defaultValue)) break;
4284 tree = tree->next;
4285 }
4286 if (tree == NULL) {
4287 xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ATTRIBUTE_VALUE,
4288"Default value \"%s\" for attribute %s of %s is not among the enumerated set\n",
4289 attr->defaultValue, attr->name, attr->elem);
4290 ret = 0;
4291 }
4292 }
4293
4294 return(ret);
4295}
4296
4313int
4314xmlValidateElementDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
4316 int ret = 1;
4317 xmlElementPtr tst;
4318
4319 CHECK_DTD;
4320
4321 if (elem == NULL) return(1);
4322
4323#if 0
4324#ifdef LIBXML_REGEXP_ENABLED
4325 /* Build the regexp associated to the content model */
4326 ret = xmlValidBuildContentModel(ctxt, elem);
4327#endif
4328#endif
4329
4330 /* No Duplicate Types */
4331 if (elem->etype == XML_ELEMENT_TYPE_MIXED) {
4333 const xmlChar *name;
4334
4335 cur = elem->content;
4336 while (cur != NULL) {
4337 if (cur->type != XML_ELEMENT_CONTENT_OR) break;
4338 if (cur->c1 == NULL) break;
4339 if (cur->c1->type == XML_ELEMENT_CONTENT_ELEMENT) {
4340 name = cur->c1->name;
4341 next = cur->c2;
4342 while (next != NULL) {
4343 if (next->type == XML_ELEMENT_CONTENT_ELEMENT) {
4344 if ((xmlStrEqual(next->name, name)) &&
4345 (xmlStrEqual(next->prefix, cur->c1->prefix))) {
4346 if (cur->c1->prefix == NULL) {
4347 xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4348 "Definition of %s has duplicate references of %s\n",
4349 elem->name, name, NULL);
4350 } else {
4351 xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4352 "Definition of %s has duplicate references of %s:%s\n",
4353 elem->name, cur->c1->prefix, name);
4354 }
4355 ret = 0;
4356 }
4357 break;
4358 }
4359 if (next->c1 == NULL) break;
4360 if (next->c1->type != XML_ELEMENT_CONTENT_ELEMENT) break;
4361 if ((xmlStrEqual(next->c1->name, name)) &&
4362 (xmlStrEqual(next->c1->prefix, cur->c1->prefix))) {
4363 if (cur->c1->prefix == NULL) {
4364 xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4365 "Definition of %s has duplicate references to %s\n",
4366 elem->name, name, NULL);
4367 } else {
4368 xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4369 "Definition of %s has duplicate references to %s:%s\n",
4370 elem->name, cur->c1->prefix, name);
4371 }
4372 ret = 0;
4373 }
4374 next = next->c2;
4375 }
4376 }
4377 cur = cur->c2;
4378 }
4379 }
4380
4381 /* VC: Unique Element Type Declaration */
4382 tst = xmlGetDtdElementDesc(doc->intSubset, elem->name);
4383 if ((tst != NULL ) && (tst != elem) &&
4384 ((tst->prefix == elem->prefix) ||
4385 (xmlStrEqual(tst->prefix, elem->prefix))) &&
4387 xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED,
4388 "Redefinition of element %s\n",
4389 elem->name, NULL, NULL);
4390 ret = 0;
4391 }
4392 tst = xmlGetDtdElementDesc(doc->extSubset, elem->name);
4393 if ((tst != NULL ) && (tst != elem) &&
4394 ((tst->prefix == elem->prefix) ||
4395 (xmlStrEqual(tst->prefix, elem->prefix))) &&
4397 xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED,
4398 "Redefinition of element %s\n",
4399 elem->name, NULL, NULL);
4400 ret = 0;
4401 }
4402 /* One ID per Element Type
4403 * already done when registering the attribute
4404 if (xmlScanIDAttributeDecl(ctxt, elem) > 1) {
4405 ret = 0;
4406 } */
4407 return(ret);
4408}
4409
4435int
4436xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
4438{
4439 xmlAttributePtr attrDecl = NULL;
4440 int val;
4441 int ret = 1;
4442
4443 CHECK_DTD;
4444 if ((elem == NULL) || (elem->name == NULL)) return(0);
4445 if ((attr == NULL) || (attr->name == NULL)) return(0);
4446
4447 if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
4448 xmlChar fn[50];
4450
4451 fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
4452 if (fullname == NULL)
4453 return(0);
4454 if (attr->ns != NULL) {
4455 attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
4456 attr->name, attr->ns->prefix);
4457 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4458 attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
4459 attr->name, attr->ns->prefix);
4460 } else {
4461 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, attr->name);
4462 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4463 attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
4464 fullname, attr->name);
4465 }
4466 if ((fullname != fn) && (fullname != elem->name))
4468 }
4469 if (attrDecl == NULL) {
4470 if (attr->ns != NULL) {
4471 attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
4472 attr->name, attr->ns->prefix);
4473 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4474 attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
4475 attr->name, attr->ns->prefix);
4476 } else {
4477 attrDecl = xmlGetDtdAttrDesc(doc->intSubset,
4478 elem->name, attr->name);
4479 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4480 attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
4481 elem->name, attr->name);
4482 }
4483 }
4484
4485
4486 /* Validity Constraint: Attribute Value Type */
4487 if (attrDecl == NULL) {
4488 xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE,
4489 "No declaration for attribute %s of element %s\n",
4490 attr->name, elem->name, NULL);
4491 return(0);
4492 }
4493 attr->atype = attrDecl->atype;
4494
4495 val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
4496 if (val == 0) {
4497 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4498 "Syntax of value for attribute %s of %s is not valid\n",
4499 attr->name, elem->name, NULL);
4500 ret = 0;
4501 }
4502
4503 /* Validity constraint: Fixed Attribute Default */
4504 if (attrDecl->def == XML_ATTRIBUTE_FIXED) {
4505 if (!xmlStrEqual(value, attrDecl->defaultValue)) {
4506 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT,
4507 "Value for attribute %s of %s is different from default \"%s\"\n",
4508 attr->name, elem->name, attrDecl->defaultValue);
4509 ret = 0;
4510 }
4511 }
4512
4513 /* Validity Constraint: ID uniqueness */
4514 if (attrDecl->atype == XML_ATTRIBUTE_ID) {
4515 if (xmlAddID(ctxt, doc, value, attr) == NULL)
4516 ret = 0;
4517 }
4518
4519 if ((attrDecl->atype == XML_ATTRIBUTE_IDREF) ||
4520 (attrDecl->atype == XML_ATTRIBUTE_IDREFS)) {
4521 if (xmlAddRef(ctxt, doc, value, attr) == NULL)
4522 ret = 0;
4523 }
4524
4525 /* Validity Constraint: Notation Attributes */
4526 if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
4527 xmlEnumerationPtr tree = attrDecl->tree;
4528 xmlNotationPtr nota;
4529
4530 /* First check that the given NOTATION was declared */
4532 if (nota == NULL)
4534
4535 if (nota == NULL) {
4536 xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION,
4537 "Value \"%s\" for attribute %s of %s is not a declared Notation\n",
4538 value, attr->name, elem->name);
4539 ret = 0;
4540 }
4541
4542 /* Second, verify that it's among the list */
4543 while (tree != NULL) {
4544 if (xmlStrEqual(tree->name, value)) break;
4545 tree = tree->next;
4546 }
4547 if (tree == NULL) {
4548 xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE,
4549"Value \"%s\" for attribute %s of %s is not among the enumerated notations\n",
4550 value, attr->name, elem->name);
4551 ret = 0;
4552 }
4553 }
4554
4555 /* Validity Constraint: Enumeration */
4556 if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) {
4557 xmlEnumerationPtr tree = attrDecl->tree;
4558 while (tree != NULL) {
4559 if (xmlStrEqual(tree->name, value)) break;
4560 tree = tree->next;
4561 }
4562 if (tree == NULL) {
4563 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4564 "Value \"%s\" for attribute %s of %s is not among the enumerated set\n",
4565 value, attr->name, elem->name);
4566 ret = 0;
4567 }
4568 }
4569
4570 /* Fixed Attribute Default */
4571 if ((attrDecl->def == XML_ATTRIBUTE_FIXED) &&
4572 (!xmlStrEqual(attrDecl->defaultValue, value))) {
4573 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4574 "Value for attribute %s of %s must be \"%s\"\n",
4575 attr->name, elem->name, attrDecl->defaultValue);
4576 ret = 0;
4577 }
4578
4579 /* Extra check for the attribute value */
4580 ret &= xmlValidateAttributeValue2(ctxt, doc, attr->name,
4581 attrDecl->atype, value);
4582
4583 return(ret);
4584}
4585
4612int
4613xmlValidateOneNamespace(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
4614xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) {
4615 /* xmlElementPtr elemDecl; */
4616 xmlAttributePtr attrDecl = NULL;
4617 int val;
4618 int ret = 1;
4619
4620 CHECK_DTD;
4621 if ((elem == NULL) || (elem->name == NULL)) return(0);
4622 if ((ns == NULL) || (ns->href == NULL)) return(0);
4623
4624 if (prefix != NULL) {
4625 xmlChar fn[50];
4627
4628 fullname = xmlBuildQName(elem->name, prefix, fn, 50);
4629 if (fullname == NULL) {
4630 xmlVErrMemory(ctxt, "Validating namespace");
4631 return(0);
4632 }
4633 if (ns->prefix != NULL) {
4634 attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
4635 ns->prefix, BAD_CAST "xmlns");
4636 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4637 attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
4638 ns->prefix, BAD_CAST "xmlns");
4639 } else {
4640 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname,
4641 BAD_CAST "xmlns");
4642 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4643 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname,
4644 BAD_CAST "xmlns");
4645 }
4646 if ((fullname != fn) && (fullname != elem->name))
4648 }
4649 if (attrDecl == NULL) {
4650 if (ns->prefix != NULL) {
4651 attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
4652 ns->prefix, BAD_CAST "xmlns");
4653 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4654 attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
4655 ns->prefix, BAD_CAST "xmlns");
4656 } else {
4657 attrDecl = xmlGetDtdAttrDesc(doc->intSubset,
4658 elem->name, BAD_CAST "xmlns");
4659 if ((attrDecl == NULL) && (doc->extSubset != NULL))
4660 attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
4661 elem->name, BAD_CAST "xmlns");
4662 }
4663 }
4664
4665
4666 /* Validity Constraint: Attribute Value Type */
4667 if (attrDecl == NULL) {
4668 if (ns->prefix != NULL) {
4669 xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE,
4670 "No declaration for attribute xmlns:%s of element %s\n",
4671 ns->prefix, elem->name, NULL);
4672 } else {
4673 xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE,
4674 "No declaration for attribute xmlns of element %s\n",
4675 elem->name, NULL, NULL);
4676 }
4677 return(0);
4678 }
4679
4680 val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
4681 if (val == 0) {
4682 if (ns->prefix != NULL) {
4683 xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_DEFAULT,
4684 "Syntax of value for attribute xmlns:%s of %s is not valid\n",
4685 ns->prefix, elem->name, NULL);
4686 } else {
4687 xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_DEFAULT,
4688 "Syntax of value for attribute xmlns of %s is not valid\n",
4689 elem->name, NULL, NULL);
4690 }
4691 ret = 0;
4692 }
4693
4694 /* Validity constraint: Fixed Attribute Default */
4695 if (attrDecl->def == XML_ATTRIBUTE_FIXED) {
4696 if (!xmlStrEqual(value, attrDecl->defaultValue)) {
4697 if (ns->prefix != NULL) {
4698 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT,
4699 "Value for attribute xmlns:%s of %s is different from default \"%s\"\n",
4700 ns->prefix, elem->name, attrDecl->defaultValue);
4701 } else {
4702 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT,
4703 "Value for attribute xmlns of %s is different from default \"%s\"\n",
4704 elem->name, attrDecl->defaultValue, NULL);
4705 }
4706 ret = 0;
4707 }
4708 }
4709
4710 /*
4711 * Casting ns to xmlAttrPtr is wrong. We'd need separate functions
4712 * xmlAddID and xmlAddRef for namespace declarations, but it makes
4713 * no practical sense to use ID types anyway.
4714 */
4715#if 0
4716 /* Validity Constraint: ID uniqueness */
4717 if (attrDecl->atype == XML_ATTRIBUTE_ID) {
4718 if (xmlAddID(ctxt, doc, value, (xmlAttrPtr) ns) == NULL)
4719 ret = 0;
4720 }
4721
4722 if ((attrDecl->atype == XML_ATTRIBUTE_IDREF) ||
4723 (attrDecl->atype == XML_ATTRIBUTE_IDREFS)) {
4724 if (xmlAddRef(ctxt, doc, value, (xmlAttrPtr) ns) == NULL)
4725 ret = 0;
4726 }
4727#endif
4728
4729 /* Validity Constraint: Notation Attributes */
4730 if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
4731 xmlEnumerationPtr tree = attrDecl->tree;
4732 xmlNotationPtr nota;
4733
4734 /* First check that the given NOTATION was declared */
4736 if (nota == NULL)
4738
4739 if (nota == NULL) {
4740 if (ns->prefix != NULL) {
4741 xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION,
4742 "Value \"%s\" for attribute xmlns:%s of %s is not a declared Notation\n",
4743 value, ns->prefix, elem->name);
4744 } else {
4745 xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION,
4746 "Value \"%s\" for attribute xmlns of %s is not a declared Notation\n",
4747 value, elem->name, NULL);
4748 }
4749 ret = 0;
4750 }
4751
4752 /* Second, verify that it's among the list */
4753 while (tree != NULL) {
4754 if (xmlStrEqual(tree->name, value)) break;
4755 tree = tree->next;
4756 }
4757 if (tree == NULL) {
4758 if (ns->prefix != NULL) {
4759 xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE,
4760"Value \"%s\" for attribute xmlns:%s of %s is not among the enumerated notations\n",
4761 value, ns->prefix, elem->name);
4762 } else {
4763 xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE,
4764"Value \"%s\" for attribute xmlns of %s is not among the enumerated notations\n",
4765 value, elem->name, NULL);
4766 }
4767 ret = 0;
4768 }
4769 }
4770
4771 /* Validity Constraint: Enumeration */
4772 if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) {
4773 xmlEnumerationPtr tree = attrDecl->tree;
4774 while (tree != NULL) {
4775 if (xmlStrEqual(tree->name, value)) break;
4776 tree = tree->next;
4777 }
4778 if (tree == NULL) {
4779 if (ns->prefix != NULL) {
4780 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4781"Value \"%s\" for attribute xmlns:%s of %s is not among the enumerated set\n",
4782 value, ns->prefix, elem->name);
4783 } else {
4784 xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4785"Value \"%s\" for attribute xmlns of %s is not among the enumerated set\n",
4786 value, elem->name, NULL);
4787 }
4788 ret = 0;
4789 }
4790 }
4791
4792 /* Fixed Attribute Default */
4793 if ((attrDecl->def == XML_ATTRIBUTE_FIXED) &&
4794 (!xmlStrEqual(attrDecl->defaultValue, value))) {
4795 if (ns->prefix != NULL) {
4796 xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE,
4797 "Value for attribute xmlns:%s of %s must be \"%s\"\n",
4798 ns->prefix, elem->name, attrDecl->defaultValue);
4799 } else {
4800 xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE,
4801 "Value for attribute xmlns of %s must be \"%s\"\n",
4802 elem->name, attrDecl->defaultValue, NULL);
4803 }
4804 ret = 0;
4805 }
4806
4807 /* Extra check for the attribute value */
4808 if (ns->prefix != NULL) {
4809 ret &= xmlValidateAttributeValue2(ctxt, doc, ns->prefix,
4810 attrDecl->atype, value);
4811 } else {
4812 ret &= xmlValidateAttributeValue2(ctxt, doc, BAD_CAST "xmlns",
4813 attrDecl->atype, value);
4814 }
4815
4816 return(ret);
4817}
4818
4819#ifndef LIBXML_REGEXP_ENABLED
4830static xmlNodePtr
4831xmlValidateSkipIgnorable(xmlNodePtr child) {
4832 while (child != NULL) {
4833 switch (child->type) {
4834 /* These things are ignored (skipped) during validation. */
4835 case XML_PI_NODE:
4836 case XML_COMMENT_NODE:
4837 case XML_XINCLUDE_START:
4838 case XML_XINCLUDE_END:
4839 child = child->next;
4840 break;
4841 case XML_TEXT_NODE:
4842 if (xmlIsBlankNode(child))
4843 child = child->next;
4844 else
4845 return(child);
4846 break;
4847 /* keep current node */
4848 default:
4849 return(child);
4850 }
4851 }
4852 return(child);
4853}
4854
4866static int
4867xmlValidateElementType(xmlValidCtxtPtr ctxt) {
4868 int ret = -1;
4869 int determinist = 1;
4870
4871 NODE = xmlValidateSkipIgnorable(NODE);
4872 if ((NODE == NULL) && (CONT == NULL))
4873 return(1);
4874 if ((NODE == NULL) &&
4875 ((CONT->ocur == XML_ELEMENT_CONTENT_MULT) ||
4876 (CONT->ocur == XML_ELEMENT_CONTENT_OPT))) {
4877 return(1);
4878 }
4879 if (CONT == NULL) return(-1);
4880 if ((NODE != NULL) && (NODE->type == XML_ENTITY_REF_NODE))
4881 return(-2);
4882
4883 /*
4884 * We arrive here when more states need to be examined
4885 */
4886cont:
4887
4888 /*
4889 * We just recovered from a rollback generated by a possible
4890 * epsilon transition, go directly to the analysis phase
4891 */
4892 if (STATE == ROLLBACK_PARENT) {
4893 DEBUG_VALID_MSG("restored parent branch");
4894 DEBUG_VALID_STATE(NODE, CONT)
4895 ret = 1;
4896 goto analyze;
4897 }
4898
4899 DEBUG_VALID_STATE(NODE, CONT)
4900 /*
4901 * we may have to save a backup state here. This is the equivalent
4902 * of handling epsilon transition in NFAs.
4903 */
4904 if ((CONT != NULL) &&
4905 ((CONT->parent == NULL) ||
4906 (CONT->parent->type != XML_ELEMENT_CONTENT_OR)) &&
4907 ((CONT->ocur == XML_ELEMENT_CONTENT_MULT) ||
4908 (CONT->ocur == XML_ELEMENT_CONTENT_OPT) ||
4909 ((CONT->ocur == XML_ELEMENT_CONTENT_PLUS) && (OCCURRENCE)))) {
4910 DEBUG_VALID_MSG("saving parent branch");
4911 if (vstateVPush(ctxt, CONT, NODE, DEPTH, OCCURS, ROLLBACK_PARENT) < 0)
4912 return(0);
4913 }
4914
4915
4916 /*
4917 * Check first if the content matches
4918 */
4919 switch (CONT->type) {
4921 if (NODE == NULL) {
4922 DEBUG_VALID_MSG("pcdata failed no node");
4923 ret = 0;
4924 break;
4925 }
4926 if (NODE->type == XML_TEXT_NODE) {
4927 DEBUG_VALID_MSG("pcdata found, skip to next");
4928 /*
4929 * go to next element in the content model
4930 * skipping ignorable elems
4931 */
4932 do {
4933 NODE = NODE->next;
4934 NODE = xmlValidateSkipIgnorable(NODE);
4935 if ((NODE != NULL) &&
4936 (NODE->type == XML_ENTITY_REF_NODE))
4937 return(-2);
4938 } while ((NODE != NULL) &&
4939 ((NODE->type != XML_ELEMENT_NODE) &&
4940 (NODE->type != XML_TEXT_NODE) &&
4941 (NODE->type != XML_CDATA_SECTION_NODE)));
4942 ret = 1;
4943 break;
4944 } else {
4945 DEBUG_VALID_MSG("pcdata failed");
4946 ret = 0;
4947 break;
4948 }
4949 break;
4951 if (NODE == NULL) {
4952 DEBUG_VALID_MSG("element failed no node");
4953 ret = 0;
4954 break;
4955 }
4956 ret = ((NODE->type == XML_ELEMENT_NODE) &&
4957 (xmlStrEqual(NODE->name, CONT->name)));
4958 if (ret == 1) {
4959 if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) {
4960 ret = (CONT->prefix == NULL);
4961 } else if (CONT->prefix == NULL) {
4962 ret = 0;
4963 } else {
4964 ret = xmlStrEqual(NODE->ns->prefix, CONT->prefix);
4965 }
4966 }
4967 if (ret == 1) {
4968 DEBUG_VALID_MSG("element found, skip to next");
4969 /*
4970 * go to next element in the content model
4971 * skipping ignorable elems
4972 */
4973 do {
4974 NODE = NODE->next;
4975 NODE = xmlValidateSkipIgnorable(NODE);
4976 if ((NODE != NULL) &&
4977 (NODE->type == XML_ENTITY_REF_NODE))
4978 return(-2);
4979 } while ((NODE != NULL) &&
4980 ((NODE->type != XML_ELEMENT_NODE) &&
4981 (NODE->type != XML_TEXT_NODE) &&
4982 (NODE->type != XML_CDATA_SECTION_NODE)));
4983 } else {
4984 DEBUG_VALID_MSG("element failed");
4985 ret = 0;
4986 break;
4987 }
4988 break;
4990 /*
4991 * Small optimization.
4992 */
4993 if (CONT->c1->type == XML_ELEMENT_CONTENT_ELEMENT) {
4994 if ((NODE == NULL) ||
4995 (!xmlStrEqual(NODE->name, CONT->c1->name))) {
4996 DEPTH++;
4997 CONT = CONT->c2;
4998 goto cont;
4999 }
5000 if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) {
5001 ret = (CONT->c1->prefix == NULL);
5002 } else if (CONT->c1->prefix == NULL) {
5003 ret = 0;
5004 } else {
5005 ret = xmlStrEqual(NODE->ns->prefix, CONT->c1->prefix);
5006 }
5007 if (ret == 0) {
5008 DEPTH++;
5009 CONT = CONT->c2;
5010 goto cont;
5011 }
5012 }
5013
5014 /*
5015 * save the second branch 'or' branch
5016 */
5017 DEBUG_VALID_MSG("saving 'or' branch");
5018 if (vstateVPush(ctxt, CONT->c2, NODE, (unsigned char)(DEPTH + 1),
5019 OCCURS, ROLLBACK_OR) < 0)
5020 return(-1);
5021 DEPTH++;
5022 CONT = CONT->c1;
5023 goto cont;
5025 /*
5026 * Small optimization.
5027 */
5028 if ((CONT->c1->type == XML_ELEMENT_CONTENT_ELEMENT) &&
5029 ((CONT->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
5030 (CONT->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
5031 if ((NODE == NULL) ||
5032 (!xmlStrEqual(NODE->name, CONT->c1->name))) {
5033 DEPTH++;
5034 CONT = CONT->c2;
5035 goto cont;
5036 }
5037 if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) {
5038 ret = (CONT->c1->prefix == NULL);
5039 } else if (CONT->c1->prefix == NULL) {
5040 ret = 0;
5041 } else {
5042 ret = xmlStrEqual(NODE->ns->prefix, CONT->c1->prefix);
5043 }
5044 if (ret == 0) {
5045 DEPTH++;
5046 CONT = CONT->c2;
5047 goto cont;
5048 }
5049 }
5050 DEPTH++;
5051 CONT = CONT->c1;
5052 goto cont;
5053 }
5054
5055 /*
5056 * At this point handle going up in the tree
5057 */
5058 if (ret == -1) {
5059 DEBUG_VALID_MSG("error found returning");
5060 return(ret);
5061 }
5062analyze:
5063 while (CONT != NULL) {
5064 /*
5065 * First do the analysis depending on the occurrence model at
5066 * this level.
5067 */
5068 if (ret == 0) {
5069 switch (CONT->ocur) {
5071
5073 cur = ctxt->vstate->node;
5074 DEBUG_VALID_MSG("Once branch failed, rollback");
5075 if (vstateVPop(ctxt) < 0 ) {
5076 DEBUG_VALID_MSG("exhaustion, failed");
5077 return(0);
5078 }
5079 if (cur != ctxt->vstate->node)
5080 determinist = -3;
5081 goto cont;
5083 if (OCCURRENCE == 0) {
5084 cur = ctxt->vstate->node;
5085 DEBUG_VALID_MSG("Plus branch failed, rollback");
5086 if (vstateVPop(ctxt) < 0 ) {
5087 DEBUG_VALID_MSG("exhaustion, failed");
5088 return(0);
5089 }
5090 if (cur != ctxt->vstate->node)
5091 determinist = -3;
5092 goto cont;
5093 }
5094 DEBUG_VALID_MSG("Plus branch found");
5095 ret = 1;
5096 break;
5098#ifdef DEBUG_VALID_ALGO
5099 if (OCCURRENCE == 0) {
5100 DEBUG_VALID_MSG("Mult branch failed");
5101 } else {
5102 DEBUG_VALID_MSG("Mult branch found");
5103 }
5104#endif
5105 ret = 1;
5106 break;
5108 DEBUG_VALID_MSG("Option branch failed");
5109 ret = 1;
5110 break;
5111 }
5112 } else {
5113 switch (CONT->ocur) {
5115 DEBUG_VALID_MSG("Option branch succeeded");
5116 ret = 1;
5117 break;
5119 DEBUG_VALID_MSG("Once branch succeeded");
5120 ret = 1;
5121 break;
5123 if (STATE == ROLLBACK_PARENT) {
5124 DEBUG_VALID_MSG("Plus branch rollback");
5125 ret = 1;
5126 break;
5127 }
5128 if (NODE == NULL) {
5129 DEBUG_VALID_MSG("Plus branch exhausted");
5130 ret = 1;
5131 break;
5132 }
5133 DEBUG_VALID_MSG("Plus branch succeeded, continuing");
5134 SET_OCCURRENCE;
5135 goto cont;
5137 if (STATE == ROLLBACK_PARENT) {
5138 DEBUG_VALID_MSG("Mult branch rollback");
5139 ret = 1;
5140 break;
5141 }
5142 if (NODE == NULL) {
5143 DEBUG_VALID_MSG("Mult branch exhausted");
5144 ret = 1;
5145 break;
5146 }
5147 DEBUG_VALID_MSG("Mult branch succeeded, continuing");
5148 /* SET_OCCURRENCE; */
5149 goto cont;
5150 }
5151 }
5152 STATE = 0;
5153
5154 /*
5155 * Then act accordingly at the parent level
5156 */
5157 RESET_OCCURRENCE;
5158 if (CONT->parent == NULL)
5159 break;
5160
5161 switch (CONT->parent->type) {
5163 DEBUG_VALID_MSG("Error: parent pcdata");
5164 return(-1);
5166 DEBUG_VALID_MSG("Error: parent element");
5167 return(-1);
5169 if (ret == 1) {
5170 DEBUG_VALID_MSG("Or succeeded");
5171 CONT = CONT->parent;
5172 DEPTH--;
5173 } else {
5174 DEBUG_VALID_MSG("Or failed");
5175 CONT = CONT->parent;
5176 DEPTH--;
5177 }
5178 break;
5180 if (ret == 0) {
5181 DEBUG_VALID_MSG("Sequence failed");
5182 CONT = CONT->parent;
5183 DEPTH--;
5184 } else if (CONT == CONT->parent->c1) {
5185 DEBUG_VALID_MSG("Sequence testing 2nd branch");
5186 CONT = CONT->parent->c2;
5187 goto cont;
5188 } else {
5189 DEBUG_VALID_MSG("Sequence succeeded");
5190 CONT = CONT->parent;
5191 DEPTH--;
5192 }
5193 }
5194 }
5195 if (NODE != NULL) {
5197
5198 cur = ctxt->vstate->node;
5199 DEBUG_VALID_MSG("Failed, remaining input, rollback");
5200 if (vstateVPop(ctxt) < 0 ) {
5201 DEBUG_VALID_MSG("exhaustion, failed");
5202 return(0);
5203 }
5204 if (cur != ctxt->vstate->node)
5205 determinist = -3;
5206 goto cont;
5207 }
5208 if (ret == 0) {
5210
5211 cur = ctxt->vstate->node;
5212 DEBUG_VALID_MSG("Failure, rollback");
5213 if (vstateVPop(ctxt) < 0 ) {
5214 DEBUG_VALID_MSG("exhaustion, failed");
5215 return(0);
5216 }
5217 if (cur != ctxt->vstate->node)
5218 determinist = -3;
5219 goto cont;
5220 }
5221 return(determinist);
5222}
5223#endif
5224
5235static void
5236xmlSnprintfElements(char *buf, int size, xmlNodePtr node, int glob) {
5238 int len;
5239
5240 if (node == NULL) return;
5241 if (glob) strcat(buf, "(");
5242 cur = node;
5243 while (cur != NULL) {
5244 len = strlen(buf);
5245 if (size - len < 50) {
5246 if ((size - len > 4) && (buf[len - 1] != '.'))
5247 strcat(buf, " ...");
5248 return;
5249 }
5250 switch (cur->type) {
5251 case XML_ELEMENT_NODE:
5252 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
5253 if (size - len < xmlStrlen(cur->ns->prefix) + 10) {
5254 if ((size - len > 4) && (buf[len - 1] != '.'))
5255 strcat(buf, " ...");
5256 return;
5257 }
5258 strcat(buf, (char *) cur->ns->prefix);
5259 strcat(buf, ":");
5260 }
5261 if (size - len < xmlStrlen(cur->name) + 10) {
5262 if ((size - len > 4) && (buf[len - 1] != '.'))
5263 strcat(buf, " ...");
5264 return;
5265 }
5266 strcat(buf, (char *) cur->name);
5267 if (cur->next != NULL)
5268 strcat(buf, " ");
5269 break;
5270 case XML_TEXT_NODE:
5271 if (xmlIsBlankNode(cur))
5272 break;
5273 /* Falls through. */
5276 strcat(buf, "CDATA");
5277 if (cur->next != NULL)
5278 strcat(buf, " ");
5279 break;
5280 case XML_ATTRIBUTE_NODE:
5281 case XML_DOCUMENT_NODE:
5285 case XML_NOTATION_NODE:
5286 case XML_NAMESPACE_DECL:
5287 strcat(buf, "???");
5288 if (cur->next != NULL)
5289 strcat(buf, " ");
5290 break;
5291 case XML_ENTITY_NODE:
5292 case XML_PI_NODE:
5293 case XML_DTD_NODE:
5294 case XML_COMMENT_NODE:
5295 case XML_ELEMENT_DECL:
5296 case XML_ATTRIBUTE_DECL:
5297 case XML_ENTITY_DECL:
5298 case XML_XINCLUDE_START:
5299 case XML_XINCLUDE_END:
5300 break;
5301 }
5302 cur = cur->next;
5303 }
5304 if (glob) strcat(buf, ")");
5305}
5306
5320static int
5321xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child,
5322 xmlElementPtr elemDecl, int warn, xmlNodePtr parent) {
5323 int ret = 1;
5324#ifndef LIBXML_REGEXP_ENABLED
5325 xmlNodePtr repl = NULL, last = NULL, tmp;
5326#endif
5329 const xmlChar *name;
5330
5331 if ((elemDecl == NULL) || (parent == NULL) || (ctxt == NULL))
5332 return(-1);
5333 cont = elemDecl->content;
5334 name = elemDecl->name;
5335
5336#ifdef LIBXML_REGEXP_ENABLED
5337 /* Build the regexp associated to the content model */
5338 if (elemDecl->contModel == NULL)
5339 ret = xmlValidBuildContentModel(ctxt, elemDecl);
5340 if (elemDecl->contModel == NULL) {
5341 return(-1);
5342 } else {
5343 xmlRegExecCtxtPtr exec;
5344
5345 if (!xmlRegexpIsDeterminist(elemDecl->contModel)) {
5346 return(-1);
5347 }
5348 ctxt->nodeMax = 0;
5349 ctxt->nodeNr = 0;
5350 ctxt->nodeTab = NULL;
5351 exec = xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL);
5352 if (exec != NULL) {
5353 cur = child;
5354 while (cur != NULL) {
5355 switch (cur->type) {
5357 /*
5358 * Push the current node to be able to roll back
5359 * and process within the entity
5360 */
5361 if ((cur->children != NULL) &&
5362 (cur->children->children != NULL)) {
5363 nodeVPush(ctxt, cur);
5364 cur = cur->children->children;
5365 continue;
5366 }
5367 break;
5368 case XML_TEXT_NODE:
5369 if (xmlIsBlankNode(cur))
5370 break;
5371 ret = 0;
5372 goto fail;
5374 /* TODO */
5375 ret = 0;
5376 goto fail;
5377 case XML_ELEMENT_NODE:
5378 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
5379 xmlChar fn[50];
5381
5382 fullname = xmlBuildQName(cur->name,
5383 cur->ns->prefix, fn, 50);
5384 if (fullname == NULL) {
5385 ret = -1;
5386 goto fail;
5387 }
5388 ret = xmlRegExecPushString(exec, fullname, NULL);
5389 if ((fullname != fn) && (fullname != cur->name))
5391 } else {
5392 ret = xmlRegExecPushString(exec, cur->name, NULL);
5393 }
5394 break;
5395 default:
5396 break;
5397 }
5398 /*
5399 * Switch to next element
5400 */
5401 cur = cur->next;
5402 while (cur == NULL) {
5403 cur = nodeVPop(ctxt);
5404 if (cur == NULL)
5405 break;
5406 cur = cur->next;
5407 }
5408 }
5409 ret = xmlRegExecPushString(exec, NULL, NULL);
5410fail:
5411 xmlRegFreeExecCtxt(exec);
5412 }
5413 }
5414#else /* LIBXML_REGEXP_ENABLED */
5415 /*
5416 * Allocate the stack
5417 */
5418 ctxt->vstateMax = 8;
5419 ctxt->vstateTab = (xmlValidState *) xmlMalloc(
5420 ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
5421 if (ctxt->vstateTab == NULL) {
5422 xmlVErrMemory(ctxt, "malloc failed");
5423 return(-1);
5424 }
5425 /*
5426 * The first entry in the stack is reserved to the current state
5427 */
5428 ctxt->nodeMax = 0;
5429 ctxt->nodeNr = 0;
5430 ctxt->nodeTab = NULL;
5431 ctxt->vstate = &ctxt->vstateTab[0];
5432 ctxt->vstateNr = 1;
5433 CONT = cont;
5434 NODE = child;
5435 DEPTH = 0;
5436 OCCURS = 0;
5437 STATE = 0;
5438 ret = xmlValidateElementType(ctxt);
5439 if ((ret == -3) && (warn)) {
5440 xmlErrValidWarning(ctxt, child, XML_DTD_CONTENT_NOT_DETERMINIST,
5441 "Content model for Element %s is ambiguous\n",
5442 name, NULL, NULL);
5443 } else if (ret == -2) {
5444 /*
5445 * An entities reference appeared at this level.
5446 * Build a minimal representation of this node content
5447 * sufficient to run the validation process on it
5448 */
5449 DEBUG_VALID_MSG("Found an entity reference, linearizing");
5450 cur = child;
5451 while (cur != NULL) {
5452 switch (cur->type) {
5454 /*
5455 * Push the current node to be able to roll back
5456 * and process within the entity
5457 */
5458 if ((cur->children != NULL) &&
5459 (cur->children->children != NULL)) {
5460 nodeVPush(ctxt, cur);
5461 cur = cur->children->children;
5462 continue;
5463 }
5464 break;
5465 case XML_TEXT_NODE:
5466 if (xmlIsBlankNode(cur))
5467 break;
5468 /* no break on purpose */
5470 /* no break on purpose */
5471 case XML_ELEMENT_NODE:
5472 /*
5473 * Allocate a new node and minimally fills in
5474 * what's required
5475 */
5476 tmp = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
5477 if (tmp == NULL) {
5478 xmlVErrMemory(ctxt, "malloc failed");
5479 xmlFreeNodeList(repl);
5480 ret = -1;
5481 goto done;
5482 }
5483 tmp->type = cur->type;
5484 tmp->name = cur->name;
5485 tmp->ns = cur->ns;
5486 tmp->next = NULL;
5487 tmp->content = NULL;
5488 if (repl == NULL)
5489 repl = last = tmp;
5490 else {
5491 last->next = tmp;
5492 last = tmp;
5493 }
5494 if (cur->type == XML_CDATA_SECTION_NODE) {
5495 /*
5496 * E59 spaces in CDATA does not match the
5497 * nonterminal S
5498 */
5499 tmp->content = xmlStrdup(BAD_CAST "CDATA");
5500 }
5501 break;
5502 default:
5503 break;
5504 }
5505 /*
5506 * Switch to next element
5507 */
5508 cur = cur->next;
5509 while (cur == NULL) {
5510 cur = nodeVPop(ctxt);
5511 if (cur == NULL)
5512 break;
5513 cur = cur->next;
5514 }
5515 }
5516
5517 /*
5518 * Relaunch the validation
5519 */
5520 ctxt->vstate = &ctxt->vstateTab[0];
5521 ctxt->vstateNr = 1;
5522 CONT = cont;
5523 NODE = repl;
5524 DEPTH = 0;
5525 OCCURS = 0;
5526 STATE = 0;
5527 ret = xmlValidateElementType(ctxt);
5528 }
5529#endif /* LIBXML_REGEXP_ENABLED */
5530 if ((warn) && ((ret != 1) && (ret != -3))) {
5531 if (ctxt != NULL) {
5532 char expr[5000];
5533 char list[5000];
5534
5535 expr[0] = 0;
5536 xmlSnprintfElementContent(&expr[0], 5000, cont, 1);
5537 list[0] = 0;
5538#ifndef LIBXML_REGEXP_ENABLED
5539 if (repl != NULL)
5540 xmlSnprintfElements(&list[0], 5000, repl, 1);
5541 else
5542#endif /* LIBXML_REGEXP_ENABLED */
5543 xmlSnprintfElements(&list[0], 5000, child, 1);
5544
5545 if (name != NULL) {
5546 xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5547 "Element %s content does not follow the DTD, expecting %s, got %s\n",
5549 } else {
5550 xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5551 "Element content does not follow the DTD, expecting %s, got %s\n",
5553 }
5554 } else {
5555 if (name != NULL) {
5556 xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5557 "Element %s content does not follow the DTD\n",
5558 name, NULL, NULL);
5559 } else {
5560 xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5561 "Element content does not follow the DTD\n",
5562 NULL, NULL, NULL);
5563 }
5564 }
5565 ret = 0;
5566 }
5567 if (ret == -3)
5568 ret = 1;
5569
5570#ifndef LIBXML_REGEXP_ENABLED
5571done:
5572 /*
5573 * Deallocate the copy if done, and free up the validation stack
5574 */
5575 while (repl != NULL) {
5576 tmp = repl->next;
5577 xmlFree(repl);
5578 repl = tmp;
5579 }
5580 ctxt->vstateMax = 0;
5581 if (ctxt->vstateTab != NULL) {
5582 xmlFree(ctxt->vstateTab);
5583 ctxt->vstateTab = NULL;
5584 }
5585#endif
5586 ctxt->nodeMax = 0;
5587 ctxt->nodeNr = 0;
5588 if (ctxt->nodeTab != NULL) {
5589 xmlFree(ctxt->nodeTab);
5590 ctxt->nodeTab = NULL;
5591 }
5592 return(ret);
5593
5594}
5595
5606static int
5607xmlValidateOneCdataElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
5608 xmlNodePtr elem) {
5609 int ret = 1;
5611
5612 if ((ctxt == NULL) || (doc == NULL) || (elem == NULL) ||
5613 (elem->type != XML_ELEMENT_NODE))
5614 return(0);
5615
5616 child = elem->children;
5617
5618 cur = child;
5619 while (cur != NULL) {
5620 switch (cur->type) {
5622 /*
5623 * Push the current node to be able to roll back
5624 * and process within the entity
5625 */
5626 if ((cur->children != NULL) &&
5627 (cur->children->children != NULL)) {
5628 nodeVPush(ctxt, cur);
5629 cur = cur->children->children;
5630 continue;
5631 }
5632 break;
5633 case XML_COMMENT_NODE:
5634 case XML_PI_NODE:
5635 case XML_TEXT_NODE:
5637 break;
5638 default:
5639 ret = 0;
5640 goto done;
5641 }
5642 /*
5643 * Switch to next element
5644 */
5645 cur = cur->next;
5646 while (cur == NULL) {
5647 cur = nodeVPop(ctxt);
5648 if (cur == NULL)
5649 break;
5650 cur = cur->next;
5651 }
5652 }
5653done:
5654 ctxt->nodeMax = 0;
5655 ctxt->nodeNr = 0;
5656 if (ctxt->nodeTab != NULL) {
5657 xmlFree(ctxt->nodeTab);
5658 ctxt->nodeTab = NULL;
5659 }
5660 return(ret);
5661}
5662
5673static int
5674xmlValidateCheckMixed(xmlValidCtxtPtr ctxt,
5675 xmlElementContentPtr cont, const xmlChar *qname) {
5676 const xmlChar *name;
5677 int plen;
5678 name = xmlSplitQName3(qname, &plen);
5679
5680 if (name == NULL) {
5681 while (cont != NULL) {
5682 if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
5683 if ((cont->prefix == NULL) && (xmlStrEqual(cont->name, qname)))
5684 return(1);
5685 } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
5686 (cont->c1 != NULL) &&
5687 (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
5688 if ((cont->c1->prefix == NULL) &&
5689 (xmlStrEqual(cont->c1->name, qname)))
5690 return(1);
5691 } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
5692 (cont->c1 == NULL) ||
5693 (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
5694 xmlErrValid(NULL, XML_DTD_MIXED_CORRUPT,
5695 "Internal: MIXED struct corrupted\n",
5696 NULL);
5697 break;
5698 }
5699 cont = cont->c2;
5700 }
5701 } else {
5702 while (cont != NULL) {
5703 if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
5704 if ((cont->prefix != NULL) &&
5705 (xmlStrncmp(cont->prefix, qname, plen) == 0) &&
5706 (xmlStrEqual(cont->name, name)))
5707 return(1);
5708 } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
5709 (cont->c1 != NULL) &&
5710 (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
5711 if ((cont->c1->prefix != NULL) &&
5712 (xmlStrncmp(cont->c1->prefix, qname, plen) == 0) &&
5713 (xmlStrEqual(cont->c1->name, name)))
5714 return(1);
5715 } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
5716 (cont->c1 == NULL) ||
5717 (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
5718 xmlErrValid(ctxt, XML_DTD_MIXED_CORRUPT,
5719 "Internal: MIXED struct corrupted\n",
5720 NULL);
5721 break;
5722 }
5723 cont = cont->c2;
5724 }
5725 }
5726 return(0);
5727}
5728
5741static xmlElementPtr
5742xmlValidGetElemDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
5743 xmlNodePtr elem, int *extsubset) {
5744 xmlElementPtr elemDecl = NULL;
5745 const xmlChar *prefix = NULL;
5746
5747 if ((ctxt == NULL) || (doc == NULL) ||
5748 (elem == NULL) || (elem->name == NULL))
5749 return(NULL);
5750 if (extsubset != NULL)
5751 *extsubset = 0;
5752
5753 /*
5754 * Fetch the declaration for the qualified name
5755 */
5756 if ((elem->ns != NULL) && (elem->ns->prefix != NULL))
5757 prefix = elem->ns->prefix;
5758
5759 if (prefix != NULL) {
5760 elemDecl = xmlGetDtdQElementDesc(doc->intSubset,
5761 elem->name, prefix);
5762 if ((elemDecl == NULL) && (doc->extSubset != NULL)) {
5763 elemDecl = xmlGetDtdQElementDesc(doc->extSubset,
5764 elem->name, prefix);
5765 if ((elemDecl != NULL) && (extsubset != NULL))
5766 *extsubset = 1;
5767 }
5768 }
5769
5770 /*
5771 * Fetch the declaration for the non qualified name
5772 * This is "non-strict" validation should be done on the
5773 * full QName but in that case being flexible makes sense.
5774 */
5775 if (elemDecl == NULL) {
5776 elemDecl = xmlGetDtdElementDesc(doc->intSubset, elem->name);
5777 if ((elemDecl == NULL) && (doc->extSubset != NULL)) {
5778 elemDecl = xmlGetDtdElementDesc(doc->extSubset, elem->name);
5779 if ((elemDecl != NULL) && (extsubset != NULL))
5780 *extsubset = 1;
5781 }
5782 }
5783 if (elemDecl == NULL) {
5784 xmlErrValidNode(ctxt, elem,
5786 "No declaration for element %s\n",
5787 elem->name, NULL, NULL);
5788 }
5789 return(elemDecl);
5790}
5791
5792#ifdef LIBXML_REGEXP_ENABLED
5804int
5805xmlValidatePushElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
5806 xmlNodePtr elem, const xmlChar *qname) {
5807 int ret = 1;
5808 xmlElementPtr eDecl;
5809 int extsubset = 0;
5810
5811 if (ctxt == NULL)
5812 return(0);
5813/* printf("PushElem %s\n", qname); */
5814 if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) {
5815 xmlValidStatePtr state = ctxt->vstate;
5816 xmlElementPtr elemDecl;
5817
5818 /*
5819 * Check the new element against the content model of the new elem.
5820 */
5821 if (state->elemDecl != NULL) {
5822 elemDecl = state->elemDecl;
5823
5824 switch(elemDecl->etype) {
5826 ret = 0;
5827 break;
5829 xmlErrValidNode(ctxt, state->node,
5831 "Element %s was declared EMPTY this one has content\n",
5832 state->node->name, NULL, NULL);
5833 ret = 0;
5834 break;
5836 /* I don't think anything is required then */
5837 break;
5839 /* simple case of declared as #PCDATA */
5840 if ((elemDecl->content != NULL) &&
5841 (elemDecl->content->type ==
5843 xmlErrValidNode(ctxt, state->node,
5845 "Element %s was declared #PCDATA but contains non text nodes\n",
5846 state->node->name, NULL, NULL);
5847 ret = 0;
5848 } else {
5849 ret = xmlValidateCheckMixed(ctxt, elemDecl->content,
5850 qname);
5851 if (ret != 1) {
5852 xmlErrValidNode(ctxt, state->node,
5854 "Element %s is not declared in %s list of possible children\n",
5855 qname, state->node->name, NULL);
5856 }
5857 }
5858 break;
5860 /*
5861 * TODO:
5862 * VC: Standalone Document Declaration
5863 * - element types with element content, if white space
5864 * occurs directly within any instance of those types.
5865 */
5866 if (state->exec != NULL) {
5867 ret = xmlRegExecPushString(state->exec, qname, NULL);
5868 if (ret < 0) {
5869 xmlErrValidNode(ctxt, state->node,
5871 "Element %s content does not follow the DTD, Misplaced %s\n",
5872 state->node->name, qname, NULL);
5873 ret = 0;
5874 } else {
5875 ret = 1;
5876 }
5877 }
5878 break;
5879 }
5880 }
5881 }
5882 eDecl = xmlValidGetElemDecl(ctxt, doc, elem, &extsubset);
5883 vstateVPush(ctxt, eDecl, elem);
5884 return(ret);
5885}
5886
5897int
5898xmlValidatePushCData(xmlValidCtxtPtr ctxt, const xmlChar *data, int len) {
5899 int ret = 1;
5900
5901/* printf("CDATA %s %d\n", data, len); */
5902 if (ctxt == NULL)
5903 return(0);
5904 if (len <= 0)
5905 return(ret);
5906 if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) {
5907 xmlValidStatePtr state = ctxt->vstate;
5908 xmlElementPtr elemDecl;
5909
5910 /*
5911 * Check the new element against the content model of the new elem.
5912 */
5913 if (state->elemDecl != NULL) {
5914 elemDecl = state->elemDecl;
5915
5916 switch(elemDecl->etype) {
5918 ret = 0;
5919 break;
5921 xmlErrValidNode(ctxt, state->node,
5923 "Element %s was declared EMPTY this one has content\n",
5924 state->node->name, NULL, NULL);
5925 ret = 0;
5926 break;
5928 break;
5930 break;
5932 int i;
5933
5934 for (i = 0;i < len;i++) {
5935 if (!IS_BLANK_CH(data[i])) {
5936 xmlErrValidNode(ctxt, state->node,
5938 "Element %s content does not follow the DTD, Text not allowed\n",
5939 state->node->name, NULL, NULL);
5940 ret = 0;
5941 goto done;
5942 }
5943 }
5944 /*
5945 * TODO:
5946 * VC: Standalone Document Declaration
5947 * element types with element content, if white space
5948 * occurs directly within any instance of those types.
5949 */
5950 break;
5951 }
5952 }
5953 }
5954 }
5955done:
5956 return(ret);
5957}
5958
5970int
5971xmlValidatePopElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc ATTRIBUTE_UNUSED,
5973 const xmlChar *qname ATTRIBUTE_UNUSED) {
5974 int ret = 1;
5975
5976 if (ctxt == NULL)
5977 return(0);
5978/* printf("PopElem %s\n", qname); */
5979 if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) {
5980 xmlValidStatePtr state = ctxt->vstate;
5981 xmlElementPtr elemDecl;
5982
5983 /*
5984 * Check the new element against the content model of the new elem.
5985 */
5986 if (state->elemDecl != NULL) {
5987 elemDecl = state->elemDecl;
5988
5989 if (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT) {
5990 if (state->exec != NULL) {
5991 ret = xmlRegExecPushString(state->exec, NULL, NULL);
5992 if (ret == 0) {
5993 xmlErrValidNode(ctxt, state->node,
5995 "Element %s content does not follow the DTD, Expecting more child\n",
5996 state->node->name, NULL,NULL);
5997 } else {
5998 /*
5999 * previous validation errors should not generate
6000 * a new one here
6001 */
6002 ret = 1;
6003 }
6004 }
6005 }
6006 }
6007 vstateVPop(ctxt);
6008 }
6009 return(ret);
6010}
6011#endif /* LIBXML_REGEXP_ENABLED */
6012
6031int
6032xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
6033 xmlNodePtr elem) {
6034 xmlElementPtr elemDecl = NULL;
6038 int ret = 1, tmp;
6039 const xmlChar *name;
6040 int extsubset = 0;
6041
6042 CHECK_DTD;
6043
6044 if (elem == NULL) return(0);
6045 switch (elem->type) {
6046 case XML_ATTRIBUTE_NODE:
6047 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
6048 "Attribute element not expected\n", NULL, NULL ,NULL);
6049 return(0);
6050 case XML_TEXT_NODE:
6051 if (elem->children != NULL) {
6052 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
6053 "Text element has children !\n",
6054 NULL,NULL,NULL);
6055 return(0);
6056 }
6057 if (elem->ns != NULL) {
6058 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
6059 "Text element has namespace !\n",
6060 NULL,NULL,NULL);
6061 return(0);
6062 }
6063 if (elem->content == NULL) {
6064 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
6065 "Text element has no content !\n",
6066 NULL,NULL,NULL);
6067 return(0);
6068 }
6069 return(1);
6070 case XML_XINCLUDE_START:
6071 case XML_XINCLUDE_END:
6072 return(1);
6075 case XML_PI_NODE:
6076 case XML_COMMENT_NODE:
6077 return(1);
6078 case XML_ENTITY_NODE:
6079 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
6080 "Entity element not expected\n", NULL, NULL ,NULL);
6081 return(0);
6082 case XML_NOTATION_NODE:
6083 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
6084 "Notation element not expected\n", NULL, NULL ,NULL);
6085 return(0);
6086 case XML_DOCUMENT_NODE:
6089 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
6090 "Document element not expected\n", NULL, NULL ,NULL);
6091 return(0);
6093 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
6094 "HTML Document not expected\n", NULL, NULL ,NULL);
6095 return(0);
6096 case XML_ELEMENT_NODE:
6097 break;
6098 default:
6099 xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
6100 "unknown element type\n", NULL, NULL ,NULL);
6101 return(0);
6102 }
6103
6104 /*
6105 * Fetch the declaration
6106 */
6107 elemDecl = xmlValidGetElemDecl(ctxt, doc, elem, &extsubset);
6108 if (elemDecl == NULL)
6109 return(0);
6110
6111 /*
6112 * If vstateNr is not zero that means continuous validation is
6113 * activated, do not try to check the content model at that level.
6114 */
6115 if (ctxt->vstateNr == 0) {
6116 /* Check that the element content matches the definition */
6117 switch (elemDecl->etype) {
6119 xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ELEM,
6120 "No declaration for element %s\n",
6121 elem->name, NULL, NULL);
6122 return(0);
6124 if (elem->children != NULL) {
6125 xmlErrValidNode(ctxt, elem, XML_DTD_NOT_EMPTY,
6126 "Element %s was declared EMPTY this one has content\n",
6127 elem->name, NULL, NULL);
6128 ret = 0;
6129 }
6130 break;
6132 /* I don't think anything is required then */
6133 break;
6135
6136 /* simple case of declared as #PCDATA */
6137 if ((elemDecl->content != NULL) &&
6138 (elemDecl->content->type == XML_ELEMENT_CONTENT_PCDATA)) {
6139 ret = xmlValidateOneCdataElement(ctxt, doc, elem);
6140 if (!ret) {
6141 xmlErrValidNode(ctxt, elem, XML_DTD_NOT_PCDATA,
6142 "Element %s was declared #PCDATA but contains non text nodes\n",
6143 elem->name, NULL, NULL);
6144 }
6145 break;
6146 }
6147 child = elem->children;
6148 /* Hum, this start to get messy */
6149 while (child != NULL) {
6150 if (child->type == XML_ELEMENT_NODE) {
6151 name = child->name;
6152 if ((child->ns != NULL) && (child->ns->prefix != NULL)) {
6153 xmlChar fn[50];
6155
6156 fullname = xmlBuildQName(child->name, child->ns->prefix,
6157 fn, 50);
6158 if (fullname == NULL)
6159 return(0);
6160 cont = elemDecl->content;
6161 while (cont != NULL) {
6162 if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
6163 if (xmlStrEqual(cont->name, fullname))
6164 break;
6165 } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
6166 (cont->c1 != NULL) &&
6167 (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
6168 if (xmlStrEqual(cont->c1->name, fullname))
6169 break;
6170 } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
6171 (cont->c1 == NULL) ||
6172 (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
6173 xmlErrValid(NULL, XML_DTD_MIXED_CORRUPT,
6174 "Internal: MIXED struct corrupted\n",
6175 NULL);
6176 break;
6177 }
6178 cont = cont->c2;
6179 }
6180 if ((fullname != fn) && (fullname != child->name))
6182 if (cont != NULL)
6183 goto child_ok;
6184 }
6185 cont = elemDecl->content;
6186 while (cont != NULL) {
6187 if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
6188 if (xmlStrEqual(cont->name, name)) break;
6189 } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
6190 (cont->c1 != NULL) &&
6191 (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)) {
6192 if (xmlStrEqual(cont->c1->name, name)) break;
6193 } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
6194 (cont->c1 == NULL) ||
6195 (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)) {
6196 xmlErrValid(ctxt, XML_DTD_MIXED_CORRUPT,
6197 "Internal: MIXED struct corrupted\n",
6198 NULL);
6199 break;
6200 }
6201 cont = cont->c2;
6202 }
6203 if (cont == NULL) {
6204 xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_CHILD,
6205 "Element %s is not declared in %s list of possible children\n",
6206 name, elem->name, NULL);
6207 ret = 0;
6208 }
6209 }
6210child_ok:
6211 child = child->next;
6212 }
6213 break;
6215 if ((doc->standalone == 1) && (extsubset == 1)) {
6216 /*
6217 * VC: Standalone Document Declaration
6218 * - element types with element content, if white space
6219 * occurs directly within any instance of those types.
6220 */
6221 child = elem->children;
6222 while (child != NULL) {
6223 if (child->type == XML_TEXT_NODE) {
6224 const xmlChar *content = child->content;
6225
6226 while (IS_BLANK_CH(*content))
6227 content++;
6228 if (*content == 0) {
6229 xmlErrValidNode(ctxt, elem,
6231"standalone: %s declared in the external subset contains white spaces nodes\n",
6232 elem->name, NULL, NULL);
6233 ret = 0;
6234 break;
6235 }
6236 }
6237 child =child->next;
6238 }
6239 }
6240 child = elem->children;
6241 cont = elemDecl->content;
6242 tmp = xmlValidateElementContent(ctxt, child, elemDecl, 1, elem);
6243 if (tmp <= 0)
6244 ret = tmp;
6245 break;
6246 }
6247 } /* not continuous */
6248
6249 /* [ VC: Required Attribute ] */
6250 attr = elemDecl->attributes;
6251 while (attr != NULL) {
6252 if (attr->def == XML_ATTRIBUTE_REQUIRED) {
6253 int qualified = -1;
6254
6255 if ((attr->prefix == NULL) &&
6256 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) {
6257 xmlNsPtr ns;
6258
6259 ns = elem->nsDef;
6260 while (ns != NULL) {
6261 if (ns->prefix == NULL)
6262 goto found;
6263 ns = ns->next;
6264 }
6265 } else if (xmlStrEqual(attr->prefix, BAD_CAST "xmlns")) {
6266 xmlNsPtr ns;
6267
6268 ns = elem->nsDef;
6269 while (ns != NULL) {
6270 if (xmlStrEqual(attr->name, ns->prefix))
6271 goto found;
6272 ns = ns->next;
6273 }
6274 } else {
6275 xmlAttrPtr attrib;
6276
6277 attrib = elem->properties;
6278 while (attrib != NULL) {
6279 if (xmlStrEqual(attrib->name, attr->name)) {
6280 if (attr->prefix != NULL) {
6281 xmlNsPtr nameSpace = attrib->ns;
6282
6283 if (nameSpace == NULL)
6284 nameSpace = elem->ns;
6285 /*
6286 * qualified names handling is problematic, having a
6287 * different prefix should be possible but DTDs don't
6288 * allow to define the URI instead of the prefix :-(
6289 */
6290 if (nameSpace == NULL) {
6291 if (qualified < 0)
6292 qualified = 0;
6293 } else if (!xmlStrEqual(nameSpace->prefix,
6294 attr->prefix)) {
6295 if (qualified < 1)
6296 qualified = 1;
6297 } else
6298 goto found;
6299 } else {
6300 /*
6301 * We should allow applications to define namespaces
6302 * for their application even if the DTD doesn't
6303 * carry one, otherwise, basically we would always
6304 * break.
6305 */
6306 goto found;
6307 }
6308 }
6309 attrib = attrib->next;
6310 }
6311 }
6312 if (qualified == -1) {
6313 if (attr->prefix == NULL) {
6314 xmlErrValidNode(ctxt, elem, XML_DTD_MISSING_ATTRIBUTE,
6315 "Element %s does not carry attribute %s\n",
6316 elem->name, attr->name, NULL);
6317 ret = 0;
6318 } else {
6319 xmlErrValidNode(ctxt, elem, XML_DTD_MISSING_ATTRIBUTE,
6320 "Element %s does not carry attribute %s:%s\n",
6321 elem->name, attr->prefix,attr->name);
6322 ret = 0;
6323 }
6324 } else if (qualified == 0) {
6325 xmlErrValidWarning(ctxt, elem, XML_DTD_NO_PREFIX,
6326 "Element %s required attribute %s:%s has no prefix\n",
6327 elem->name, attr->prefix, attr->name);
6328 } else if (qualified == 1) {
6329 xmlErrValidWarning(ctxt, elem, XML_DTD_DIFFERENT_PREFIX,
6330 "Element %s required attribute %s:%s has different prefix\n",
6331 elem->name, attr->prefix, attr->name);
6332 }
6333 } else if (attr->def == XML_ATTRIBUTE_FIXED) {
6334 /*
6335 * Special tests checking #FIXED namespace declarations
6336 * have the right value since this is not done as an
6337 * attribute checking
6338 */
6339 if ((attr->prefix == NULL) &&
6340 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) {
6341 xmlNsPtr ns;
6342
6343 ns = elem->nsDef;
6344 while (ns != NULL) {
6345 if (ns->prefix == NULL) {
6346 if (!xmlStrEqual(attr->defaultValue, ns->href)) {
6347 xmlErrValidNode(ctxt, elem,
6349 "Element %s namespace name for default namespace does not match the DTD\n",
6350 elem->name, NULL, NULL);
6351 ret = 0;
6352 }
6353 goto found;
6354 }
6355 ns = ns->next;
6356 }
6357 } else if (xmlStrEqual(attr->prefix, BAD_CAST "xmlns")) {
6358 xmlNsPtr ns;
6359
6360 ns = elem->nsDef;
6361 while (ns != NULL) {
6362 if (xmlStrEqual(attr->name, ns->prefix)) {
6363 if (!xmlStrEqual(attr->defaultValue, ns->href)) {
6364 xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE,
6365 "Element %s namespace name for %s does not match the DTD\n",
6366 elem->name, ns->prefix, NULL);
6367 ret = 0;
6368 }
6369 goto found;
6370 }
6371 ns = ns->next;
6372 }
6373 }
6374 }
6375found:
6376 attr = attr->nexth;
6377 }
6378 return(ret);
6379}
6380
6395int
6396xmlValidateRoot(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6398 int ret;
6399
6400 if (doc == NULL) return(0);
6401
6403 if ((root == NULL) || (root->name == NULL)) {
6404 xmlErrValid(ctxt, XML_DTD_NO_ROOT,
6405 "no root element\n", NULL);
6406 return(0);
6407 }
6408
6409 /*
6410 * When doing post validation against a separate DTD, those may
6411 * no internal subset has been generated
6412 */
6413 if ((doc->intSubset != NULL) &&
6414 (doc->intSubset->name != NULL)) {
6415 /*
6416 * Check first the document root against the NQName
6417 */
6418 if (!xmlStrEqual(doc->intSubset->name, root->name)) {
6419 if ((root->ns != NULL) && (root->ns->prefix != NULL)) {
6420 xmlChar fn[50];
6422
6423 fullname = xmlBuildQName(root->name, root->ns->prefix, fn, 50);
6424 if (fullname == NULL) {
6425 xmlVErrMemory(ctxt, NULL);
6426 return(0);
6427 }
6428 ret = xmlStrEqual(doc->intSubset->name, fullname);
6429 if ((fullname != fn) && (fullname != root->name))
6431 if (ret == 1)
6432 goto name_ok;
6433 }
6434 if ((xmlStrEqual(doc->intSubset->name, BAD_CAST "HTML")) &&
6435 (xmlStrEqual(root->name, BAD_CAST "html")))
6436 goto name_ok;
6437 xmlErrValidNode(ctxt, root, XML_DTD_ROOT_NAME,
6438 "root and DTD name do not match '%s' and '%s'\n",
6439 root->name, doc->intSubset->name, NULL);
6440 return(0);
6441 }
6442 }
6443name_ok:
6444 return(1);
6445}
6446
6447
6459int
6460xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem) {
6463 xmlNsPtr ns;
6464 const xmlChar *value;
6465 int ret = 1;
6466
6467 if (elem == NULL) return(0);
6468
6469 /*
6470 * XInclude elements were added after parsing in the infoset,
6471 * they don't really mean anything validation wise.
6472 */
6473 if ((elem->type == XML_XINCLUDE_START) ||
6474 (elem->type == XML_XINCLUDE_END) ||
6475 (elem->type == XML_NAMESPACE_DECL))
6476 return(1);
6477
6478 CHECK_DTD;
6479
6480 /*
6481 * Entities references have to be handled separately
6482 */
6483 if (elem->type == XML_ENTITY_REF_NODE) {
6484 return(1);
6485 }
6486
6487 ret &= xmlValidateOneElement(ctxt, doc, elem);
6488 if (elem->type == XML_ELEMENT_NODE) {
6489 attr = elem->properties;
6490 while (attr != NULL) {
6491 value = xmlNodeListGetString(doc, attr->children, 0);
6492 ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value);
6493 if (value != NULL)
6494 xmlFree((char *)value);
6495 attr= attr->next;
6496 }
6497 ns = elem->nsDef;
6498 while (ns != NULL) {
6499 if (elem->ns == NULL)
6500 ret &= xmlValidateOneNamespace(ctxt, doc, elem, NULL,
6501 ns, ns->href);
6502 else
6503 ret &= xmlValidateOneNamespace(ctxt, doc, elem,
6504 elem->ns->prefix, ns, ns->href);
6505 ns = ns->next;
6506 }
6507 }
6508 child = elem->children;
6509 while (child != NULL) {
6510 ret &= xmlValidateElement(ctxt, doc, child);
6511 child = child->next;
6512 }
6513
6514 return(ret);
6515}
6516
6524static void
6525xmlValidateRef(xmlRefPtr ref, xmlValidCtxtPtr ctxt,
6526 const xmlChar *name) {
6527 xmlAttrPtr id;
6529
6530 if (ref == NULL)
6531 return;
6532 if ((ref->attr == NULL) && (ref->name == NULL))
6533 return;
6534 attr = ref->attr;
6535 if (attr == NULL) {
6536 xmlChar *dup, *str = NULL, *cur, save;
6537
6538 dup = xmlStrdup(name);
6539 if (dup == NULL) {
6540 ctxt->valid = 0;
6541 return;
6542 }
6543 cur = dup;
6544 while (*cur != 0) {
6545 str = cur;
6546 while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
6547 save = *cur;
6548 *cur = 0;
6549 id = xmlGetID(ctxt->doc, str);
6550 if (id == NULL) {
6551 xmlErrValidNodeNr(ctxt, NULL, XML_DTD_UNKNOWN_ID,
6552 "attribute %s line %d references an unknown ID \"%s\"\n",
6553 ref->name, ref->lineno, str);
6554 ctxt->valid = 0;
6555 }
6556 if (save == 0)
6557 break;
6558 *cur = save;
6559 while (IS_BLANK_CH(*cur)) cur++;
6560 }
6561 xmlFree(dup);
6562 } else if (attr->atype == XML_ATTRIBUTE_IDREF) {
6563 id = xmlGetID(ctxt->doc, name);
6564 if (id == NULL) {
6565 xmlErrValidNode(ctxt, attr->parent, XML_DTD_UNKNOWN_ID,
6566 "IDREF attribute %s references an unknown ID \"%s\"\n",
6567 attr->name, name, NULL);
6568 ctxt->valid = 0;
6569 }
6570 } else if (attr->atype == XML_ATTRIBUTE_IDREFS) {
6571 xmlChar *dup, *str = NULL, *cur, save;
6572
6573 dup = xmlStrdup(name);
6574 if (dup == NULL) {
6575 xmlVErrMemory(ctxt, "IDREFS split");
6576 ctxt->valid = 0;
6577 return;
6578 }
6579 cur = dup;
6580 while (*cur != 0) {
6581 str = cur;
6582 while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
6583 save = *cur;
6584 *cur = 0;
6585 id = xmlGetID(ctxt->doc, str);
6586 if (id == NULL) {
6587 xmlErrValidNode(ctxt, attr->parent, XML_DTD_UNKNOWN_ID,
6588 "IDREFS attribute %s references an unknown ID \"%s\"\n",
6589 attr->name, str, NULL);
6590 ctxt->valid = 0;
6591 }
6592 if (save == 0)
6593 break;
6594 *cur = save;
6595 while (IS_BLANK_CH(*cur)) cur++;
6596 }
6597 xmlFree(dup);
6598 }
6599}
6600
6608static int
6609xmlWalkValidateList(const void *data, void *user)
6610{
6612 xmlValidateRef((xmlRefPtr)data, memo->ctxt, memo->name);
6613 return 1;
6614}
6615
6623static void
6624xmlValidateCheckRefCallback(void *payload, void *data, const xmlChar *name) {
6625 xmlListPtr ref_list = (xmlListPtr) payload;
6627 xmlValidateMemo memo;
6628
6629 if (ref_list == NULL)
6630 return;
6631 memo.ctxt = ctxt;
6632 memo.name = name;
6633
6634 xmlListWalk(ref_list, xmlWalkValidateList, &memo);
6635
6636}
6637
6653int
6654xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6656 unsigned int save;
6657
6658 if (ctxt == NULL)
6659 return(0);
6660 if (doc == NULL) {
6661 xmlErrValid(ctxt, XML_DTD_NO_DOC,
6662 "xmlValidateDocumentFinal: doc == NULL\n", NULL);
6663 return(0);
6664 }
6665
6666 /* trick to get correct line id report */
6667 save = ctxt->flags;
6668 ctxt->flags &= ~XML_VCTXT_USE_PCTXT;
6669
6670 /*
6671 * Check all the NOTATION/NOTATIONS attributes
6672 */
6673 /*
6674 * Check all the ENTITY/ENTITIES attributes definition for validity
6675 */
6676 /*
6677 * Check all the IDREF/IDREFS attributes definition for validity
6678 */
6679 table = (xmlRefTablePtr) doc->refs;
6680 ctxt->doc = doc;
6681 ctxt->valid = 1;
6682 xmlHashScan(table, xmlValidateCheckRefCallback, ctxt);
6683
6684 ctxt->flags = save;
6685 return(ctxt->valid);
6686}
6687
6704int
6705xmlValidateDtd(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd) {
6706 int ret;
6707 xmlDtdPtr oldExt, oldInt;
6709
6710 if (dtd == NULL) return(0);
6711 if (doc == NULL) return(0);
6712 oldExt = doc->extSubset;
6713 oldInt = doc->intSubset;
6714 doc->extSubset = dtd;
6715 doc->intSubset = NULL;
6716 ret = xmlValidateRoot(ctxt, doc);
6717 if (ret == 0) {
6718 doc->extSubset = oldExt;
6719 doc->intSubset = oldInt;
6720 return(ret);
6721 }
6722 if (doc->ids != NULL) {
6723 xmlFreeIDTable(doc->ids);
6724 doc->ids = NULL;
6725 }
6726 if (doc->refs != NULL) {
6727 xmlFreeRefTable(doc->refs);
6728 doc->refs = NULL;
6729 }
6731 ret = xmlValidateElement(ctxt, doc, root);
6732 ret &= xmlValidateDocumentFinal(ctxt, doc);
6733 doc->extSubset = oldExt;
6734 doc->intSubset = oldInt;
6735 return(ret);
6736}
6737
6738static void
6739xmlValidateNotationCallback(void *payload, void *data,
6740 const xmlChar *name ATTRIBUTE_UNUSED) {
6741 xmlEntityPtr cur = (xmlEntityPtr) payload;
6743 if (cur == NULL)
6744 return;
6746 xmlChar *notation = cur->content;
6747
6748 if (notation != NULL) {
6749 int ret;
6750
6751 ret = xmlValidateNotationUse(ctxt, cur->doc, notation);
6752 if (ret != 1) {
6753 ctxt->valid = 0;
6754 }
6755 }
6756 }
6757}
6758
6759static void
6760xmlValidateAttributeCallback(void *payload, void *data,
6761 const xmlChar *name ATTRIBUTE_UNUSED) {
6764 int ret;
6765 xmlDocPtr doc;
6767
6768 if (cur == NULL)
6769 return;
6770 switch (cur->atype) {
6772 case XML_ATTRIBUTE_ID:
6773 case XML_ATTRIBUTE_IDREF :
6778 break;
6782 if (cur->defaultValue != NULL) {
6783
6784 ret = xmlValidateAttributeValue2(ctxt, ctxt->doc, cur->name,
6785 cur->atype, cur->defaultValue);
6786 if ((ret == 0) && (ctxt->valid == 1))
6787 ctxt->valid = 0;
6788 }
6789 if (cur->tree != NULL) {
6790 xmlEnumerationPtr tree = cur->tree;
6791 while (tree != NULL) {
6792 ret = xmlValidateAttributeValue2(ctxt, ctxt->doc,
6793 cur->name, cur->atype, tree->name);
6794 if ((ret == 0) && (ctxt->valid == 1))
6795 ctxt->valid = 0;
6796 tree = tree->next;
6797 }
6798 }
6799 }
6800 if (cur->atype == XML_ATTRIBUTE_NOTATION) {
6801 doc = cur->doc;
6802 if (cur->elem == NULL) {
6803 xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
6804 "xmlValidateAttributeCallback(%s): internal error\n",
6805 (const char *) cur->name);
6806 return;
6807 }
6808
6809 if (doc != NULL)
6810 elem = xmlGetDtdElementDesc(doc->intSubset, cur->elem);
6811 if ((elem == NULL) && (doc != NULL))
6812 elem = xmlGetDtdElementDesc(doc->extSubset, cur->elem);
6813 if ((elem == NULL) && (cur->parent != NULL) &&
6814 (cur->parent->type == XML_DTD_NODE))
6815 elem = xmlGetDtdElementDesc((xmlDtdPtr) cur->parent, cur->elem);
6816 if (elem == NULL) {
6817 xmlErrValidNode(ctxt, NULL, XML_DTD_UNKNOWN_ELEM,
6818 "attribute %s: could not find decl for element %s\n",
6819 cur->name, cur->elem, NULL);
6820 return;
6821 }
6822 if (elem->etype == XML_ELEMENT_TYPE_EMPTY) {
6823 xmlErrValidNode(ctxt, NULL, XML_DTD_EMPTY_NOTATION,
6824 "NOTATION attribute %s declared for EMPTY element %s\n",
6825 cur->name, cur->elem, NULL);
6826 ctxt->valid = 0;
6827 }
6828 }
6829}
6830
6848int
6849xmlValidateDtdFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6850 xmlDtdPtr dtd;
6852 xmlEntitiesTablePtr entities;
6853
6854 if ((doc == NULL) || (ctxt == NULL)) return(0);
6855 if ((doc->intSubset == NULL) && (doc->extSubset == NULL))
6856 return(0);
6857 ctxt->doc = doc;
6858 ctxt->valid = 1;
6859 dtd = doc->intSubset;
6860 if ((dtd != NULL) && (dtd->attributes != NULL)) {
6862 xmlHashScan(table, xmlValidateAttributeCallback, ctxt);
6863 }
6864 if ((dtd != NULL) && (dtd->entities != NULL)) {
6865 entities = (xmlEntitiesTablePtr) dtd->entities;
6866 xmlHashScan(entities, xmlValidateNotationCallback, ctxt);
6867 }
6868 dtd = doc->extSubset;
6869 if ((dtd != NULL) && (dtd->attributes != NULL)) {
6871 xmlHashScan(table, xmlValidateAttributeCallback, ctxt);
6872 }
6873 if ((dtd != NULL) && (dtd->entities != NULL)) {
6874 entities = (xmlEntitiesTablePtr) dtd->entities;
6875 xmlHashScan(entities, xmlValidateNotationCallback, ctxt);
6876 }
6877 return(ctxt->valid);
6878}
6879
6894int
6895xmlValidateDocument(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6896 int ret;
6898
6899 if (doc == NULL)
6900 return(0);
6901 if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) {
6902 xmlErrValid(ctxt, XML_DTD_NO_DTD,
6903 "no DTD found!\n", NULL);
6904 return(0);
6905 }
6906 if ((doc->intSubset != NULL) && ((doc->intSubset->SystemID != NULL) ||
6907 (doc->intSubset->ExternalID != NULL)) && (doc->extSubset == NULL)) {
6908 xmlChar *sysID;
6909 if (doc->intSubset->SystemID != NULL) {
6910 sysID = xmlBuildURI(doc->intSubset->SystemID,
6911 doc->URL);
6912 if (sysID == NULL) {
6913 xmlErrValid(ctxt, XML_DTD_LOAD_ERROR,
6914 "Could not build URI for external subset \"%s\"\n",
6915 (const char *) doc->intSubset->SystemID);
6916 return 0;
6917 }
6918 } else
6919 sysID = NULL;
6920 doc->extSubset = xmlParseDTD(doc->intSubset->ExternalID,
6921 (const xmlChar *)sysID);
6922 if (sysID != NULL)
6923 xmlFree(sysID);
6924 if (doc->extSubset == NULL) {
6925 if (doc->intSubset->SystemID != NULL) {
6926 xmlErrValid(ctxt, XML_DTD_LOAD_ERROR,
6927 "Could not load the external subset \"%s\"\n",
6928 (const char *) doc->intSubset->SystemID);
6929 } else {
6930 xmlErrValid(ctxt, XML_DTD_LOAD_ERROR,
6931 "Could not load the external subset \"%s\"\n",
6932 (const char *) doc->intSubset->ExternalID);
6933 }
6934 return(0);
6935 }
6936 }
6937
6938 if (doc->ids != NULL) {
6939 xmlFreeIDTable(doc->ids);
6940 doc->ids = NULL;
6941 }
6942 if (doc->refs != NULL) {
6943 xmlFreeRefTable(doc->refs);
6944 doc->refs = NULL;
6945 }
6946 ret = xmlValidateDtdFinal(ctxt, doc);
6947 if (!xmlValidateRoot(ctxt, doc)) return(0);
6948
6950 ret &= xmlValidateElement(ctxt, doc, root);
6951 ret &= xmlValidateDocumentFinal(ctxt, doc);
6952 return(ret);
6953}
6954
6955/************************************************************************
6956 * *
6957 * Routines for dynamic validation editing *
6958 * *
6959 ************************************************************************/
6960
6973int
6974xmlValidGetPotentialChildren(xmlElementContent *ctree,
6975 const xmlChar **names,
6976 int *len, int max) {
6977 int i;
6978
6979 if ((ctree == NULL) || (names == NULL) || (len == NULL))
6980 return(-1);
6981 if (*len >= max) return(*len);
6982
6983 switch (ctree->type) {
6985 for (i = 0; i < *len;i++)
6986 if (xmlStrEqual(BAD_CAST "#PCDATA", names[i])) return(*len);
6987 names[(*len)++] = BAD_CAST "#PCDATA";
6988 break;
6990 for (i = 0; i < *len;i++)
6991 if (xmlStrEqual(ctree->name, names[i])) return(*len);
6992 names[(*len)++] = ctree->name;
6993 break;
6995 xmlValidGetPotentialChildren(ctree->c1, names, len, max);
6996 xmlValidGetPotentialChildren(ctree->c2, names, len, max);
6997 break;
6999 xmlValidGetPotentialChildren(ctree->c1, names, len, max);
7000 xmlValidGetPotentialChildren(ctree->c2, names, len, max);
7001 break;
7002 }
7003
7004 return(*len);
7005}
7006
7007/*
7008 * Dummy function to suppress messages while we try out valid elements
7009 */
7010static void XMLCDECL xmlNoValidityErr(void *ctx ATTRIBUTE_UNUSED,
7011 const char *msg ATTRIBUTE_UNUSED, ...) {
7012 return;
7013}
7014
7040int
7041xmlValidGetValidElements(xmlNode *prev, xmlNode *next, const xmlChar **names,
7042 int max) {
7043 xmlValidCtxt vctxt;
7044 int nb_valid_elements = 0;
7045 const xmlChar *elements[256]={0};
7046 int nb_elements = 0, i;
7047 const xmlChar *name;
7048
7049 xmlNode *ref_node;
7050 xmlNode *parent;
7051 xmlNode *test_node;
7052
7053 xmlNode *prev_next;
7054 xmlNode *next_prev;
7055 xmlNode *parent_childs;
7056 xmlNode *parent_last;
7057
7058 xmlElement *element_desc;
7059
7060 if (prev == NULL && next == NULL)
7061 return(-1);
7062
7063 if (names == NULL) return(-1);
7064 if (max <= 0) return(-1);
7065
7066 memset(&vctxt, 0, sizeof (xmlValidCtxt));
7067 vctxt.error = xmlNoValidityErr; /* this suppresses err/warn output */
7068
7069 nb_valid_elements = 0;
7070 ref_node = prev ? prev : next;
7071 parent = ref_node->parent;
7072
7073 /*
7074 * Retrieves the parent element declaration
7075 */
7076 element_desc = xmlGetDtdElementDesc(parent->doc->intSubset,
7077 parent->name);
7078 if ((element_desc == NULL) && (parent->doc->extSubset != NULL))
7079 element_desc = xmlGetDtdElementDesc(parent->doc->extSubset,
7080 parent->name);
7081 if (element_desc == NULL) return(-1);
7082
7083 /*
7084 * Do a backup of the current tree structure
7085 */
7086 prev_next = prev ? prev->next : NULL;
7087 next_prev = next ? next->prev : NULL;
7088 parent_childs = parent->children;
7089 parent_last = parent->last;
7090
7091 /*
7092 * Creates a dummy node and insert it into the tree
7093 */
7094 test_node = xmlNewDocNode (ref_node->doc, NULL, BAD_CAST "<!dummy?>", NULL);
7095 if (test_node == NULL)
7096 return(-1);
7097
7098 test_node->parent = parent;
7099 test_node->prev = prev;
7100 test_node->next = next;
7101 name = test_node->name;
7102
7103 if (prev) prev->next = test_node;
7104 else parent->children = test_node;
7105
7106 if (next) next->prev = test_node;
7107 else parent->last = test_node;
7108
7109 /*
7110 * Insert each potential child node and check if the parent is
7111 * still valid
7112 */
7113 nb_elements = xmlValidGetPotentialChildren(element_desc->content,
7114 elements, &nb_elements, 256);
7115
7116 for (i = 0;i < nb_elements;i++) {
7117 test_node->name = elements[i];
7118 if (xmlValidateOneElement(&vctxt, parent->doc, parent)) {
7119 int j;
7120
7121 for (j = 0; j < nb_valid_elements;j++)
7122 if (xmlStrEqual(elements[i], names[j])) break;
7123 names[nb_valid_elements++] = elements[i];
7124 if (nb_valid_elements >= max) break;
7125 }
7126 }
7127
7128 /*
7129 * Restore the tree structure
7130 */
7131 if (prev) prev->next = prev_next;
7132 if (next) next->prev = next_prev;
7133 parent->children = parent_childs;
7134 parent->last = parent_last;
7135
7136 /*
7137 * Free up the dummy node
7138 */
7139 test_node->name = name;
7140 xmlFreeNode(test_node);
7141
7142 return(nb_valid_elements);
7143}
7144#endif /* LIBXML_VALID_ENABLED */
7145
#define MAX_RECURSE
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
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:26
content
Definition: atl_ax.c:994
r parent
Definition: btrfs.c:3010
XMLPUBFUN xmlEntityPtr XMLCALL xmlGetDocEntity(const xmlDoc *doc, const xmlChar *name)
@ XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
Definition: entities.h:27
xmlEntitiesTable * xmlEntitiesTablePtr
Definition: entities.h:71
char ** glob(const char *v)
Definition: fake.c:36
FxCollectionEntry * cur
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLenum src
Definition: glext.h:6340
GLuint GLuint * names
Definition: glext.h:11545
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
GLenum target
Definition: glext.h:7315
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 stderr
Definition: stdio.h:100
#define dup
Definition: syshdrs.h:51
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
static BYTE int2[]
Definition: cert.c:3155
const char * fullname
Definition: shader.c:1766
static UINT UINT last
Definition: font.c:45
#define child_ok
Definition: debugger.c:33
static const struct access_res create[16]
Definition: package.c:7644
static size_t elem
Definition: string.c:68
static HWND child
Definition: cursoricon.c:298
#define IS_COMBINING(c)
XMLPUBFUN int XMLCALL xmlStringCurrentChar(xmlParserCtxtPtr ctxt, const xmlChar *cur, int *len)
#define IS_DIGIT(c)
#define IS_EXTENDER(c)
#define IS_LETTER(c)
#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
XMLPUBFUN const xmlChar *XMLCALL xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len)
Definition: dict.c:867
XMLPUBFUN int XMLCALL xmlDictOwns(xmlDictPtr dict, const xmlChar *str)
Definition: dict.c:1220
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:248
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
XMLPUBVAR void * xmlGenericErrorContext
Definition: globals.h:353
XMLPUBVAR xmlReallocFunc xmlRealloc
Definition: globals.h:250
XMLPUBVAR xmlGenericErrorFunc xmlGenericError
Definition: globals.h:337
XMLPUBFUN int XMLCALL xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, void *userdata)
Definition: hash.c:406
XMLPUBFUN void XMLCALL xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f)
Definition: hash.c:322
XMLPUBFUN void *XMLCALL xmlHashLookup3(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, const xmlChar *name3)
Definition: hash.c:769
XMLPUBFUN void *XMLCALL xmlHashLookup(xmlHashTablePtr table, const xmlChar *name)
Definition: hash.c:461
XMLPUBFUN int XMLCALL xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, xmlHashDeallocator f)
Definition: hash.c:1071
XMLPUBFUN xmlHashTablePtr XMLCALL xmlHashCreateDict(int size, xmlDictPtr dict)
Definition: hash.c:210
XMLPUBFUN int XMLCALL xmlHashAddEntry(xmlHashTablePtr table, const xmlChar *name, void *userdata)
Definition: hash.c:389
XMLPUBFUN int XMLCALL xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name, xmlHashDeallocator f)
Definition: hash.c:1052
XMLPUBFUN void *XMLCALL xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2)
Definition: hash.c:476
XMLPUBFUN void XMLCALL xmlHashScan3(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, const xmlChar *name3, xmlHashScanner f, void *data)
Definition: hash.c:926
XMLPUBFUN int XMLCALL xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, const xmlChar *name3, void *userdata)
Definition: hash.c:531
XMLPUBFUN void XMLCALL xmlHashScan(xmlHashTablePtr table, xmlHashScanner f, void *data)
Definition: hash.c:859
XMLPUBFUN int XMLCALL xmlHashUpdateEntry(xmlHashTablePtr table, const xmlChar *name, void *userdata, xmlHashDeallocator f)
Definition: hash.c:425
XMLPUBFUN xmlHashTablePtr XMLCALL xmlHashCopy(xmlHashTablePtr table, xmlHashCopier f)
Definition: hash.c:992
XMLPUBFUN void XMLCALL xmlListWalk(xmlListPtr l, xmlListWalker walker, void *user)
Definition: list.c:676
XMLPUBFUN int XMLCALL xmlListEmpty(xmlListPtr l)
Definition: list.c:446
xmlList * xmlListPtr
Definition: list.h:24
XMLPUBFUN void *XMLCALL xmlLinkGetData(xmlLinkPtr lk)
Definition: list.c:604
XMLPUBFUN int XMLCALL xmlListAppend(xmlListPtr l, void *data)
Definition: list.c:305
XMLPUBFUN void XMLCALL xmlListDelete(xmlListPtr l)
Definition: list.c:333
XMLPUBFUN xmlListPtr XMLCALL xmlListCreate(xmlListDeallocator deallocator, xmlListDataCompare compare)
Definition: list.c:188
XMLPUBFUN int XMLCALL xmlListRemoveFirst(xmlListPtr l, void *data)
Definition: list.c:353
@ XML_PARSE_READER
Definition: parser.h:167
XMLPUBFUN xmlNodePtr XMLCALL xmlDocGetRootElement(const xmlDoc *doc)
xmlAttributeType
Definition: tree.h:206
@ XML_ATTRIBUTE_NMTOKENS
Definition: tree.h:214
@ XML_ATTRIBUTE_IDREF
Definition: tree.h:209
@ XML_ATTRIBUTE_ENTITIES
Definition: tree.h:212
@ XML_ATTRIBUTE_IDREFS
Definition: tree.h:210
@ XML_ATTRIBUTE_ID
Definition: tree.h:208
@ XML_ATTRIBUTE_NOTATION
Definition: tree.h:216
@ XML_ATTRIBUTE_ENUMERATION
Definition: tree.h:215
@ XML_ATTRIBUTE_CDATA
Definition: tree.h:207
@ XML_ATTRIBUTE_NMTOKEN
Definition: tree.h:213
@ XML_ATTRIBUTE_ENTITY
Definition: tree.h:211
XMLPUBFUN void XMLCALL xmlBufferWriteChar(xmlBufferPtr buf, const char *string)
xmlAttributeDefault
Definition: tree.h:225
@ XML_ATTRIBUTE_REQUIRED
Definition: tree.h:227
@ XML_ATTRIBUTE_IMPLIED
Definition: tree.h:228
@ XML_ATTRIBUTE_NONE
Definition: tree.h:226
@ XML_ATTRIBUTE_FIXED
Definition: tree.h:229
xmlElementContent * xmlElementContentPtr
Definition: tree.h:305
XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns, const xmlChar *name, const xmlChar *content)
XMLPUBFUN xmlChar *XMLCALL xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix, xmlChar *memory, int len)
xmlElement * xmlElementPtr
Definition: tree.h:345
xmlNode * xmlNodePtr
Definition: tree.h:488
xmlElementContentOccur
Definition: tree.h:290
@ XML_ELEMENT_CONTENT_OPT
Definition: tree.h:292
@ XML_ELEMENT_CONTENT_ONCE
Definition: tree.h:291
@ XML_ELEMENT_CONTENT_PLUS
Definition: tree.h:294
@ XML_ELEMENT_CONTENT_MULT
Definition: tree.h:293
XMLPUBFUN void XMLCALL xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string)
@ XML_DOCUMENT_TYPE_NODE
Definition: tree.h:169
@ XML_ATTRIBUTE_NODE
Definition: tree.h:161
@ XML_ENTITY_DECL
Definition: tree.h:176
@ XML_DOCUMENT_NODE
Definition: tree.h:168
@ XML_CDATA_SECTION_NODE
Definition: tree.h:163
@ XML_TEXT_NODE
Definition: tree.h:162
@ XML_XINCLUDE_START
Definition: tree.h:178
@ XML_ENTITY_NODE
Definition: tree.h:165
@ XML_PI_NODE
Definition: tree.h:166
@ XML_XINCLUDE_END
Definition: tree.h:179
@ XML_DOCUMENT_FRAG_NODE
Definition: tree.h:170
@ XML_COMMENT_NODE
Definition: tree.h:167
@ XML_DTD_NODE
Definition: tree.h:173
@ XML_NAMESPACE_DECL
Definition: tree.h:177
@ XML_HTML_DOCUMENT_NODE
Definition: tree.h:172
@ XML_ELEMENT_NODE
Definition: tree.h:160
@ XML_ELEMENT_DECL
Definition: tree.h:174
@ XML_ENTITY_REF_NODE
Definition: tree.h:164
@ XML_NOTATION_NODE
Definition: tree.h:171
@ XML_ATTRIBUTE_DECL
Definition: tree.h:175
XMLPUBFUN void XMLCALL xmlUnlinkNode(xmlNodePtr cur)
xmlNotation * xmlNotationPtr
Definition: tree.h:193
xmlEnumeration * xmlEnumerationPtr
Definition: tree.h:239
@ XML_DOC_OLD10
Definition: tree.h:535
xmlRef * xmlRefPtr
Definition: tree.h:473
xmlID * xmlIDPtr
Definition: tree.h:456
XMLPUBFUN int XMLCALL xmlIsBlankNode(const xmlNode *node)
xmlEntity * xmlEntityPtr
Definition: tree.h:49
XMLPUBFUN long XMLCALL xmlGetLineNo(const xmlNode *node)
XMLPUBFUN void XMLCALL xmlFreeNodeList(xmlNodePtr cur)
xmlElementTypeVal
Definition: tree.h:322
@ XML_ELEMENT_TYPE_MIXED
Definition: tree.h:326
@ XML_ELEMENT_TYPE_EMPTY
Definition: tree.h:324
@ XML_ELEMENT_TYPE_UNDEFINED
Definition: tree.h:323
@ XML_ELEMENT_TYPE_ELEMENT
Definition: tree.h:327
@ XML_ELEMENT_TYPE_ANY
Definition: tree.h:325
XMLPUBFUN void XMLCALL xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string)
XMLPUBFUN void XMLCALL xmlFreeNode(xmlNodePtr cur)
XMLPUBFUN const xmlChar *XMLCALL xmlSplitQName3(const xmlChar *name, int *len)
XMLPUBFUN xmlChar *XMLCALL xmlSplitQName2(const xmlChar *name, xmlChar **prefix)
xmlAttribute * xmlAttributePtr
Definition: tree.h:252
xmlElementContentType
Definition: tree.h:278
@ XML_ELEMENT_CONTENT_PCDATA
Definition: tree.h:279
@ XML_ELEMENT_CONTENT_ELEMENT
Definition: tree.h:280
@ XML_ELEMENT_CONTENT_OR
Definition: tree.h:282
@ XML_ELEMENT_CONTENT_SEQ
Definition: tree.h:281
XMLPUBFUN xmlChar *XMLCALL xmlNodeListGetString(xmlDocPtr doc, const xmlNode *list, int inLine)
#define memset(x, y, z)
Definition: compat.h:39
Definition: userinit.h:57
Definition: tree.h:434
xmlNs * ns
Definition: tree.h:444
struct _xmlAttr * next
Definition: tree.h:441
const xmlChar * name
Definition: tree.h:437
const xmlChar * defaultValue
Definition: tree.h:267
const xmlChar * name
Definition: tree.h:256
xmlAttributeDefault def
Definition: tree.h:266
xmlEnumerationPtr tree
Definition: tree.h:268
struct _xmlAttribute * nexth
Definition: tree.h:264
xmlAttributeType atype
Definition: tree.h:265
Definition: dict.c:111
struct _xmlDictEntry * dict
Definition: dict.c:114
Definition: tree.h:551
const xmlChar * URL
Definition: tree.h:577
struct _xmlDtd * intSubset
Definition: tree.h:570
void * ids
Definition: tree.h:575
int properties
Definition: tree.h:584
void * refs
Definition: tree.h:576
int standalone
Definition: tree.h:564
struct _xmlDict * dict
Definition: tree.h:580
xmlElementType type
Definition: tree.h:553
struct _xmlDtd * extSubset
Definition: tree.h:571
Definition: tree.h:406
struct _xmlDoc * doc
Definition: tree.h:415
struct _xmlNode * last
Definition: tree.h:411
void * elements
Definition: tree.h:419
void * entities
Definition: tree.h:421
struct _xmlNode * children
Definition: tree.h:410
void * notations
Definition: tree.h:418
void * attributes
Definition: tree.h:420
struct _xmlElementContent * c2
Definition: tree.h:311
xmlElementContentType type
Definition: tree.h:307
const xmlChar * prefix
Definition: tree.h:313
const xmlChar * name
Definition: tree.h:309
struct _xmlElementContent * c1
Definition: tree.h:310
const xmlChar * name
Definition: tree.h:349
xmlElementTypeVal etype
Definition: tree.h:357
xmlAttributePtr attributes
Definition: tree.h:359
const xmlChar * prefix
Definition: tree.h:360
void * contModel
Definition: tree.h:364
xmlElementContentPtr content
Definition: tree.h:358
xmlEntityType etype
Definition: entities.h:52
Definition: tree.h:457
Definition: list.c:39
Definition: tree.h:489
struct _xmlNode * next
Definition: tree.h:496
struct _xmlDoc * doc
Definition: tree.h:498
const xmlChar * name
Definition: tree.h:492
struct _xmlNode * parent
Definition: tree.h:495
struct _xmlNode * prev
Definition: tree.h:497
const xmlChar * name
Definition: tree.h:195
const xmlChar * SystemID
Definition: tree.h:197
const xmlChar * PublicID
Definition: tree.h:196
Definition: tree.h:389
const xmlChar * prefix
Definition: tree.h:393
xmlParserMode parseMode
Definition: parser.h:302
void * userData
Definition: parser.h:186
Definition: tree.h:474
Definition: cookie.c:202
WCHAR * name
Definition: cookie.c:203
Definition: tftpd.h:126
struct define * next
Definition: compiler.c:65
char * name
Definition: compiler.c:66
Definition: query.h:87
Definition: fatfs.h:133
Definition: name.c:39
Definition: mxnamespace.c:45
BSTR prefix
Definition: mxnamespace.c:46
Definition: send.c:48
char name[1]
Definition: send.c:52
xmlListPtr l
Definition: valid.c:2910
xmlAttrPtr ap
Definition: valid.c:2911
xmlValidCtxtPtr ctxt
Definition: valid.c:2918
const xmlChar * name
Definition: valid.c:2919
#define max(a, b)
Definition: svc.c:63
Definition: dlist.c:348
Definition: pdh_main.c:94
XMLPUBFUN xmlChar *XMLCALL xmlBuildURI(const xmlChar *URI, const xmlChar *base)
Definition: uri.c:1892
int xmlIsRef(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr)
Definition: valid.c:3122
static int xmlIsStreaming(xmlValidCtxtPtr ctxt)
Definition: valid.c:2626
static int xmlWalkRemoveRef(const void *data, void *user)
Definition: valid.c:2962
static void xmlVErrMemory(xmlValidCtxtPtr ctxt, const char *extra)
Definition: valid.c:55
#define DICT_FREE(str)
Definition: valid.c:2591
xmlRemoveMemo * xmlRemoveMemoPtr
Definition: valid.c:2914
int xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr)
Definition: valid.c:2774
void xmlSnprintfElementContent(char *buf, int size, xmlElementContentPtr content, int englob)
Definition: valid.c:1285
static void xmlFreeIDTableEntry(void *id, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: valid.c:2745
xmlValidateMemo * xmlValidateMemoPtr
Definition: valid.c:2922
static int xmlDummyCompare(const void *data0 ATTRIBUTE_UNUSED, const void *data1 ATTRIBUTE_UNUSED)
Definition: valid.c:2983
xmlAttributePtr xmlGetDtdQAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name, const xmlChar *prefix)
Definition: valid.c:3416
xmlElementContentPtr xmlCopyElementContent(xmlElementContentPtr cur)
Definition: valid.c:1077
void xmlFreeIDTable(xmlIDTablePtr table)
Definition: valid.c:2756
static void xmlFreeID(xmlIDPtr id)
Definition: valid.c:2644
xmlNotationPtr xmlAddNotationDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name, const xmlChar *PublicID, const xmlChar *SystemID)
Definition: valid.c:2394
static void xmlFreeNotation(xmlNotationPtr nota)
Definition: valid.c:2369
static xmlElementPtr xmlGetDtdElementDesc2(xmlDtdPtr dtd, const xmlChar *name, int create)
Definition: valid.c:3287
xmlElementPtr xmlGetDtdQElementDesc(xmlDtdPtr dtd, const xmlChar *name, const xmlChar *prefix)
Definition: valid.c:3355
xmlEnumerationPtr xmlCreateEnumeration(const xmlChar *name)
Definition: valid.c:1795
struct xmlValidateMemo_t xmlValidateMemo
xmlAttributePtr xmlGetDtdAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name)
Definition: valid.c:3379
xmlIDPtr xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr)
Definition: valid.c:2672
void xmlFreeEnumeration(xmlEnumerationPtr cur)
Definition: valid.c:1817
xmlElementContentPtr xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur)
Definition: valid.c:995
xmlElementContentPtr xmlNewDocElementContent(xmlDocPtr doc, const xmlChar *name, xmlElementContentType type)
Definition: valid.c:908
static void xmlFreeElementTableEntry(void *elem, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: valid.c:1630
void xmlFreeDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur)
Definition: valid.c:1089
void xmlFreeRefTable(xmlRefTablePtr table)
Definition: valid.c:3103
static void xmlFreeRefTableEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: valid.c:2948
void xmlFreeNotationTable(xmlNotationTablePtr table)
Definition: valid.c:2471
static void xmlFreeElement(xmlElementPtr elem)
Definition: valid.c:1389
int xmlRemoveRef(xmlDocPtr doc, xmlAttrPtr attr)
Definition: valid.c:3164
xmlElementContentPtr xmlNewElementContent(const xmlChar *name, xmlElementContentType type)
Definition: valid.c:981
xmlListPtr xmlGetRefs(xmlDocPtr doc, const xmlChar *ID)
Definition: valid.c:3222
int xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr)
Definition: valid.c:2835
xmlElementPtr xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name, xmlElementTypeVal type, xmlElementContentPtr content)
Definition: valid.c:1418
void xmlFreeElementContent(xmlElementContentPtr cur)
Definition: valid.c:1155
void xmlFreeElementTable(xmlElementTablePtr table)
Definition: valid.c:1641
xmlNotationPtr xmlGetDtdNotationDesc(xmlDtdPtr dtd, const xmlChar *name)
Definition: valid.c:3438
int xmlIsMixedElement(xmlDocPtr doc, const xmlChar *name)
Definition: valid.c:3494
static void xmlFreeAttributeTableEntry(void *attr, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: valid.c:2182
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:1967
static void xmlValidNormalizeString(xmlChar *str)
Definition: valid.c:2603
static void xmlFreeNotationTableEntry(void *nota, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: valid.c:2460
static void xmlFreeRef(xmlLinkPtr lk)
Definition: valid.c:2931
xmlAttrPtr xmlGetID(xmlDocPtr doc, const xmlChar *ID)
Definition: valid.c:2874
xmlRefPtr xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr)
Definition: valid.c:3003
xmlElementPtr xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name)
Definition: valid.c:3257
void xmlFreeAttributeTable(xmlAttributeTablePtr table)
Definition: valid.c:2193
struct xmlRemoveMemo_t xmlRemoveMemo
static void xmlFreeAttribute(xmlAttributePtr attr)
Definition: valid.c:1914
xmlRefTable * xmlRefTablePtr
Definition: valid.h:150
xmlIDTable * xmlIDTablePtr
Definition: valid.h:142
xmlAttributeTable * xmlAttributeTablePtr
Definition: valid.h:134
xmlElementTable * xmlElementTablePtr
Definition: valid.h:126
typedeftypedef void(XMLCDECL *) typedef void(XMLCDECL *) struct _xmlValidCtx xmlValidCtxt)
Definition: valid.h:80
xmlValidState * xmlValidStatePtr
Definition: valid.h:29
xmlValidCtxt * xmlValidCtxtPtr
Definition: valid.h:81
xmlNotationTable * xmlNotationTablePtr
Definition: valid.h:118
struct _xmlValidState xmlValidState
Definition: valid.h:28
int ret
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
void(XMLCDECL * xmlGenericErrorFunc)(void *ctx, const char *msg,...) LIBXML_ATTR_FORMAT(2
Definition: xmlerror.h:847
@ 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(XMLCDECL *) typedef void(XMLCALL * xmlStructuredErrorFunc)(void *userData, xmlErrorPtr error)
Definition: xmlerror.h:858
xmlParserErrors
Definition: xmlerror.h:99
@ XML_DTD_LOAD_ERROR
Definition: xmlerror.h:236
@ XML_DTD_ATTRIBUTE_REDEFINED
Definition: xmlerror.h:220
@ XML_DTD_INVALID_CHILD
Definition: xmlerror.h:234
@ XML_DTD_UNKNOWN_ELEM
Definition: xmlerror.h:253
@ XML_DTD_MULTIPLE_ID
Definition: xmlerror.h:239
@ XML_DTD_DIFFERENT_PREFIX
Definition: xmlerror.h:225
@ XML_DTD_UNKNOWN_ID
Definition: xmlerror.h:255
@ XML_DTD_UNKNOWN_ATTRIBUTE
Definition: xmlerror.h:252
@ XML_DTD_CONTENT_MODEL
Definition: xmlerror.h:223
@ XML_DTD_NO_DTD
Definition: xmlerror.h:241
@ XML_DTD_NOT_STANDALONE
Definition: xmlerror.h:249
@ XML_DTD_INVALID_DEFAULT
Definition: xmlerror.h:235
@ XML_DTD_ID_SUBSET
Definition: xmlerror.h:233
@ XML_DTD_MIXED_CORRUPT
Definition: xmlerror.h:238
@ XML_DTD_EMPTY_NOTATION
Definition: xmlerror.h:229
@ XML_DTD_UNKNOWN_ENTITY
Definition: xmlerror.h:254
@ XML_DTD_NO_PREFIX
Definition: xmlerror.h:243
@ XML_DTD_ATTRIBUTE_DEFAULT
Definition: xmlerror.h:219
@ XML_DTD_NO_DOC
Definition: xmlerror.h:240
@ XML_DTD_ELEM_DEFAULT_NAMESPACE
Definition: xmlerror.h:226
@ XML_DTD_MISSING_ATTRIBUTE
Definition: xmlerror.h:237
@ XML_ERR_INTERNAL_ERROR
Definition: xmlerror.h:101
@ XML_DTD_CONTENT_ERROR
Definition: xmlerror.h:222
@ XML_DTD_CONTENT_NOT_DETERMINIST
Definition: xmlerror.h:224
@ XML_DTD_ROOT_NAME
Definition: xmlerror.h:250
@ XML_DTD_NO_ROOT
Definition: xmlerror.h:244
@ XML_DTD_ELEM_NAMESPACE
Definition: xmlerror.h:227
@ XML_DTD_NOT_PCDATA
Definition: xmlerror.h:248
@ XML_DTD_NOTATION_VALUE
Definition: xmlerror.h:246
@ XML_DTD_ELEM_REDEFINED
Definition: xmlerror.h:228
@ XML_DTD_ENTITY_TYPE
Definition: xmlerror.h:230
@ XML_DTD_ID_REDEFINED
Definition: xmlerror.h:232
@ XML_DTD_ATTRIBUTE_VALUE
Definition: xmlerror.h:221
@ XML_DTD_NOT_EMPTY
Definition: xmlerror.h:247
@ XML_DTD_NOTATION_REDEFINED
Definition: xmlerror.h:245
@ XML_DTD_STANDALONE_WHITE_SPACE
Definition: xmlerror.h:251
@ XML_ERR_NO_MEMORY
Definition: xmlerror.h:102
@ XML_DTD_UNKNOWN_NOTATION
Definition: xmlerror.h:256
@ XML_DTD_ID_FIXED
Definition: xmlerror.h:231
#define XMLCDECL
Definition: xmlexports.h:52
XMLPUBFUN xmlChar *XMLCALL xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:42
XMLPUBFUN int XMLCALL xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len)
Definition: xmlstring.c:213
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:67
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:160
XMLPUBFUN int XMLCALL xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:426
unsigned char xmlChar
Definition: xmlstring.h:28
#define LIBXML_ATTR_FORMAT(fmt, args)
Definition: xmlversion.h:486
#define const
Definition: zconf.h:233