1 /*
2  * libxml2_xmlschemas.c : implementation of the XML Schema handling and
3  *                        schema validity checking
4  *
5  * See Copyright for the status of this software.
6  *
7  * Daniel Veillard <veillard@redhat.com>
8  * Portion Copyright � 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
9  */
10 
11 /*
12 
13 
14 
15 
16  */
17 #define IN_LIBXML
18 #include "xmlenglibxml.h"
19 
20 #if defined(LIBXML_SCHEMAS_ENABLED) || defined(XMLENGINE_XMLSCHEMA_DATATYPES)
21 
22 
23 #include <string.h>
24 #include <libxml2_globals.h>
25 #include <libxml2_parser.h>
26 #include <libxml2_parserinternals.h>
27 #include "libxml2_xmlerror2.h"
28 #include <libxml2_hash.h>
29 #include <libxml2_uri.h>
30 #include "libxml2_xmlschemas.h"
31 #include <libxml2_schemasinternals.h>
32 #include "libxml2_xmlschemastypes.h"
33 
34 #ifdef LIBXML_AUTOMATA_ENABLED
35 #include "libxml2_xmlautomata.h"
36 #endif
37 
38 #ifdef LIBXML_REGEXP_ENABLED
39 #include "libxml2_xmlregexp.h"
40 #endif
41 
42 #include <libxml2_dict.h>
43 
44 /* #define DEBUG 1 */
45 
46 /* #define DEBUG_CONTENT 1 */
47 
48 /* #define DEBUG_TYPE 1 */
49 
50 /* #define DEBUG_CONTENT_REGEXP 1 */
51 
52 /* #define DEBUG_AUTOMATA 1 */
53 
54 #define UNBOUNDED (1 << 30)
55 #define TODO                                \
56     xmlGenericError(xmlGenericErrorContext,             \
57         "Unimplemented block at %s:%d\n",               \
58             __FILE__, __LINE__);
59 
60 #define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar*)"the default namespace"
61 
62 /*
63  * The XML Schemas namespaces
64  */
65 static const xmlChar* const xmlSchemaNs = (const xmlChar*)
66     "http://www.w3.org/2001/XMLSchema";
67 
68 static const xmlChar* const xmlSchemaInstanceNs = (const xmlChar*)
69     "http://www.w3.org/2001/XMLSchema-instance";
70 
71 /**
72  * xmlSchemaFreeAnnot:
73  * @param annot a schema type structure
74  *
75  * Deallocate a annotation structure
76  */
77 static void
xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)78 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
79 {
80     if (annot == NULL)
81         return;
82     xmlFree(annot);
83 }
84 
85 /**
86  * xmlSchemaFreeType:
87  * @param type a schema type structure
88  *
89  * Deallocate a Schema Type structure.
90  */
91 XMLPUBFUNEXPORT void
xmlSchemaFreeType(xmlSchemaTypePtr type)92 xmlSchemaFreeType(xmlSchemaTypePtr type)
93 {
94     if (type == NULL)
95         return;
96     if (type->annot != NULL)
97         xmlSchemaFreeAnnot(type->annot);
98     if (type->facets != NULL) {
99         xmlSchemaFacetPtr facet, next;
100 
101         facet = type->facets;
102         while (facet != NULL) {
103             next = facet->next;
104             xmlSchemaFreeFacet(facet);
105             facet = next;
106         }
107     }
108     xmlFree(type);
109 }
110 
111 
112 /**
113  * xmlSchemaFreeFacet:
114  * @param facet a schema facet structure
115  *
116  * Deallocate a Schema Facet structure.
117  */
118 XMLPUBFUNEXPORT void
xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)119 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
120 {
121     if (facet == NULL)
122         return;
123     if (facet->val != NULL)
124         xmlSchemaFreeValue(facet->val);
125 #ifdef LIBXML_REGEXP_ENABLED
126     if (facet->regexp != NULL)
127         xmlRegFreeRegexp(facet->regexp);
128 #endif
129     if (facet->annot != NULL)
130         xmlSchemaFreeAnnot(facet->annot);
131     xmlFree(facet);
132 }
133 
134 #endif /* defined(LIBXML_SCHEMAS_ENABLED) || defined(XMLENGINE_XMLSCHEMA_DATATYPES) */
135 
136 #ifdef LIBXML_SCHEMAS_ENABLED
137 
138 #define IS_SCHEMA(node, type)                       \
139    ((node != NULL) && (node->ns != NULL) &&             \
140     (xmlStrEqual(node->name, (const xmlChar *) type)) &&        \
141     (xmlStrEqual(node->ns->href, xmlSchemaNs)))
142 
143 #define XML_SCHEMAS_PARSE_ERROR     1
144 
145 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
146 
147 struct _xmlSchemaParserCtxt {
148     void *userData;             /* user specific data block */
149     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
150     xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */
151     xmlSchemaValidError err;
152     int nberrors;
153     xmlStructuredErrorFunc serror;
154 
155     xmlSchemaPtr topschema; /* The main schema */
156     xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
157 
158     xmlSchemaPtr schema;        /* The schema in use */
159     const xmlChar *container;   /* the current element, group, ... */
160     int counter;
161 
162     const xmlChar *URL;
163     xmlDocPtr doc;
164     int preserve;       /* Whether the doc should be freed  */
165 
166     const char *buffer;
167     int size;
168 
169     /*
170      * Used to build complex element content models
171      */
172     xmlAutomataPtr am;
173     xmlAutomataStatePtr start;
174     xmlAutomataStatePtr end;
175     xmlAutomataStatePtr state;
176 
177     xmlDictPtr dict;        /* dictionnary for interned string names */
178     int        includes;    /* the inclusion level, 0 for root or imports */
179 };
180 
181 
182 #define XML_SCHEMAS_ATTR_UNKNOWN 1
183 #define XML_SCHEMAS_ATTR_CHECKED 2
184 
185 typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
186 typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
187 struct _xmlSchemaAttrState {
188     xmlAttrPtr attr;
189     int state;
190 };
191 
192 /**
193  * xmlSchemaValidCtxt:
194  *
195  * A Schemas validation context
196  */
197 
198 struct _xmlSchemaValidCtxt {
199     void *userData;             /* user specific data block */
200     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
201     xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */
202     xmlStructuredErrorFunc serror;
203 
204     xmlSchemaPtr schema;        /* The schema in use */
205     xmlDocPtr doc;
206     xmlParserInputBufferPtr input;
207     xmlCharEncoding enc;
208     xmlSAXHandlerPtr sax;
209     void *user_data;
210 
211     xmlDocPtr myDoc;
212     int err;
213     int nberrors;
214 
215     xmlNodePtr node;
216     xmlNodePtr cur;
217     xmlSchemaTypePtr type;
218 
219     xmlRegExecCtxtPtr regexp;
220     xmlSchemaValPtr value;
221 
222     int attrNr;
223     int attrBase;
224     int attrMax;
225     xmlSchemaAttrStatePtr attr;
226 };
227 
228 /*
229  * These are the entries in the schemas importSchemas hash table
230  */
231 typedef struct _xmlSchemaImport xmlSchemaImport;
232 typedef xmlSchemaImport *xmlSchemaImportPtr;
233 struct _xmlSchemaImport {
234     const xmlChar *schemaLocation;
235     xmlSchemaPtr schema;
236 };
237 
238 /*
239  * These are the entries associated to includes in a schemas
240  */
241 typedef struct _xmlSchemaInclude xmlSchemaInclude;
242 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
243 struct _xmlSchemaInclude {
244     xmlSchemaIncludePtr next;
245 
246     const xmlChar *schemaLocation;
247     xmlDocPtr doc;
248 };
249 
250 
251 
252 /************************************************************************
253  *                                  *
254  *          Some predeclarations                *
255  *                                  *
256  ************************************************************************/
257 static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
258                                         xmlSchemaTypePtr type,
259                                         const xmlChar * value);
260 
261 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
262                                  xmlSchemaPtr schema,
263                                  xmlNodePtr node);
264 static int
265 xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
266                              xmlSchemaTypePtr type,
267                  const xmlChar * value,
268                  int fireErrors);
269 
270 /************************************************************************
271  *                                  *
272  *          Datatype error handlers             *
273  *                                  *
274  ************************************************************************/
275 
276 /**
277  * xmlSchemaPErrMemory:
278  * @param node a context node
279  * @param extra extra informations
280  *
281  * Handle an out of memory condition
282  */
283 static void
xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,const char * extra,xmlNodePtr node)284 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
285                     const char *extra, xmlNodePtr node)
286 {
287     if (ctxt != NULL)
288         ctxt->nberrors++;
289     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
290                      extra);
291 }
292 
293 /**
294  * xmlSchemaPErr:
295  * @param ctxt the parsing context
296  * @param node the context node
297  * @param error the error code
298  * @param msg the error message
299  * @param str1 extra data
300  * @param str2 extra data
301  *
302  * Handle a parser error
303  */
304 static void
xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)305 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
306               const char *msg, const xmlChar * str1, const xmlChar * str2)
307 {
308     xmlGenericErrorFunc channel = NULL;
309     xmlStructuredErrorFunc schannel = NULL;
310     void *data = NULL;
311 
312     if (ctxt != NULL) {
313         ctxt->nberrors++;
314         channel = ctxt->error;
315         data = ctxt->userData;
316     schannel = ctxt->serror;
317     }
318     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
319                     error, XML_ERR_ERROR, NULL, 0,
320                     (const char *) str1, (const char *) str2, NULL, 0, 0,
321                     msg, str1, str2);
322 }
323 
324 /**
325  * xmlSchemaPErr2:
326  * @param ctxt the parsing context
327  * @param node the context node
328  * @param node the current child
329  * @param error the error code
330  * @param msg the error message
331  * @param str1 extra data
332  * @param str2 extra data
333  *
334  * Handle a parser error
335  */
336 static void
xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,xmlNodePtr child,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)337 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
338                xmlNodePtr child, int error,
339                const char *msg, const xmlChar * str1, const xmlChar * str2)
340 {
341     if (child != NULL)
342         xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
343     else
344         xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
345 }
346 
347 /**
348  * xmlSchemaVTypeErrMemory:
349  * @param node a context node
350  * @param extra extra informations
351  *
352  * Handle an out of memory condition
353  */
354 static void
xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,const char * extra,xmlNodePtr node)355 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
356                     const char *extra, xmlNodePtr node)
357 {
358     if (ctxt != NULL) {
359         ctxt->nberrors++;
360         ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
361     }
362     __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
363                      extra);
364 }
365 
366 /**
367  * xmlSchemaVErr3:
368  * @param ctxt the validation context
369  * @param node the context node
370  * @param error the error code
371  * @param msg the error message
372  * @param str1 extra data
373  * @param str2 extra data
374  * @param str3 extra data
375  *
376  * Handle a validation error
377  */
378 static void
xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node,int error,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)379 xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
380                const char *msg, const xmlChar *str1, const xmlChar *str2,
381            const xmlChar *str3)
382 {
383     xmlStructuredErrorFunc schannel = NULL;
384     xmlGenericErrorFunc channel = NULL;
385     void *data = NULL;
386 
387     if (ctxt != NULL) {
388         ctxt->nberrors++;
389     ctxt->err = error;
390         channel = ctxt->error;
391         schannel = ctxt->serror;
392         data = ctxt->userData;
393     }
394     /* reajust to global error numbers */
395     error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
396     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
397                     error, XML_ERR_ERROR, NULL, 0,
398                     (const char *) str1, (const char *) str2,
399             (const char *) str3, 0, 0,
400                     msg, str1, str2, str3);
401 }
402 /**
403  * xmlSchemaVErr:
404  * @param ctxt the validation context
405  * @param node the context node
406  * @param error the error code
407  * @param msg the error message
408  * @param str1 extra data
409  * @param str2 extra data
410  *
411  * Handle a validation error
412  */
413 static void
xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)414 xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
415               const char *msg, const xmlChar * str1, const xmlChar * str2)
416 {
417     xmlStructuredErrorFunc schannel = NULL;
418     xmlGenericErrorFunc channel = NULL;
419     void *data = NULL;
420 
421     if (ctxt != NULL) {
422         ctxt->nberrors++;
423     ctxt->err = error;
424         channel = ctxt->error;
425         data = ctxt->userData;
426         schannel = ctxt->serror;
427     }
428     /* reajust to global error numbers */
429     error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
430     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
431                     error, XML_ERR_ERROR, NULL, 0,
432                     (const char *) str1, (const char *) str2, NULL, 0, 0,
433                     msg, str1, str2);
434 }
435 
436 /************************************************************************
437  *                                  *
438  *          Allocation functions                *
439  *                                  *
440  ************************************************************************/
441 
442 /**
443  * xmlSchemaNewSchema:
444  * @param ctxt a schema validation context
445  *
446  * Allocate a new Schema structure.
447  *
448  * Returns the newly allocated structure or NULL in case or error
449  */
450 static xmlSchemaPtr
xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)451 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
452 {
453     xmlSchemaPtr ret;
454 
455     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
456     if (ret == NULL) {
457         xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
458         return (NULL);
459     }
460     memset(ret, 0, sizeof(xmlSchema));
461     ret->dict = ctxt->dict;
462     xmlDictReference(ret->dict);
463 
464     return (ret);
465 }
466 
467 /**
468  * xmlSchemaNewFacet:
469  *
470  * Allocate a new Facet structure.
471  *
472  * Returns the newly allocated structure or NULL in case or error
473  */
474 xmlSchemaFacetPtr
xmlSchemaNewFacet(void)475 xmlSchemaNewFacet(void)
476 {
477     xmlSchemaFacetPtr ret;
478 
479     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
480     if (ret == NULL) {
481         return (NULL);
482     }
483     memset(ret, 0, sizeof(xmlSchemaFacet));
484 
485     return (ret);
486 }
487 
488 /**
489  * xmlSchemaNewAnnot:
490  * @param ctxt a schema validation context
491  * @param node a node
492  *
493  * Allocate a new annotation structure.
494  *
495  * Returns the newly allocated structure or NULL in case or error
496  */
497 static xmlSchemaAnnotPtr
xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)498 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
499 {
500     xmlSchemaAnnotPtr ret;
501 
502     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
503     if (ret == NULL) {
504         xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
505         return (NULL);
506     }
507     memset(ret, 0, sizeof(xmlSchemaAnnot));
508     ret->content = node;
509     return (ret);
510 }
511 
512 
513 
514 /**
515  * xmlSchemaFreeImport:
516  * @param import a schema import structure
517  *
518  * Deallocate an import structure
519  */
520 static void
xmlSchemaFreeImport(xmlSchemaImportPtr import)521 xmlSchemaFreeImport(xmlSchemaImportPtr import)
522 {
523     if (import == NULL)
524         return;
525 
526     xmlSchemaFree(import->schema);
527     xmlFree(import);
528 }
529 
530 /**
531  * xmlSchemaFreeInclude:
532  * @param include a schema include structure
533  *
534  * Deallocate an include structure
535  */
536 static void
xmlSchemaFreeInclude(xmlSchemaIncludePtr include)537 xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
538 {
539     if (include == NULL)
540         return;
541 
542     xmlFreeDoc(include->doc);
543     xmlFree(include);
544 }
545 
546 /**
547  * xmlSchemaFreeIncludeList:
548  * @param includes a schema include list
549  *
550  * Deallocate an include structure
551  */
552 static void
xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)553 xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
554 {
555     xmlSchemaIncludePtr next;
556 
557     while (includes != NULL) {
558         next = includes->next;
559     xmlSchemaFreeInclude(includes);
560     includes = next;
561     }
562 }
563 
564 /**
565  * xmlSchemaFreeNotation:
566  * @param schema a schema notation structure
567  *
568  * Deallocate a Schema Notation structure.
569  */
570 static void
xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)571 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
572 {
573     if (nota == NULL)
574         return;
575     xmlFree(nota);
576 }
577 
578 /**
579  * xmlSchemaFreeAttribute:
580  * @param schema a schema attribute structure
581  *
582  * Deallocate a Schema Attribute structure.
583  */
584 static void
xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)585 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
586 {
587     if (attr == NULL)
588         return;
589     xmlFree(attr);
590 }
591 
592 /**
593  * xmlSchemaFreeAttributeGroup:
594  * @param schema a schema attribute group structure
595  *
596  * Deallocate a Schema Attribute Group structure.
597  */
598 static void
xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)599 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
600 {
601     if (attr == NULL)
602         return;
603     xmlFree(attr);
604 }
605 
606 /**
607  * xmlSchemaFreeElement:
608  * @param schema a schema element structure
609  *
610  * Deallocate a Schema Element structure.
611  */
612 static void
xmlSchemaFreeElement(xmlSchemaElementPtr elem)613 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
614 {
615     if (elem == NULL)
616         return;
617     if (elem->annot != NULL)
618         xmlSchemaFreeAnnot(elem->annot);
619     if (elem->contModel != NULL)
620         xmlRegFreeRegexp(elem->contModel);
621     xmlFree(elem);
622 }
623 
624 /**
625  * xmlSchemaFreeTypeList:
626  * @param type a schema type structure
627  *
628  * Deallocate a Schema Type structure.
629  */
630 static void
xmlSchemaFreeTypeList(xmlSchemaTypePtr type)631 xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
632 {
633     xmlSchemaTypePtr next;
634 
635     while (type != NULL) {
636         next = type->redef;
637     xmlSchemaFreeType(type);
638     type = next;
639     }
640 }
641 
642 /**
643  * xmlSchemaFree:
644  * @param schema a schema structure
645  *
646  * Deallocate a Schema structure.
647  */
648 void
xmlSchemaFree(xmlSchemaPtr schema)649 xmlSchemaFree(xmlSchemaPtr schema)
650 {
651     if (schema == NULL)
652         return;
653 
654     if (schema->notaDecl != NULL)
655         xmlHashFree(schema->notaDecl,
656                     (xmlHashDeallocator) xmlSchemaFreeNotation);
657     if (schema->attrDecl != NULL)
658         xmlHashFree(schema->attrDecl,
659                     (xmlHashDeallocator) xmlSchemaFreeAttribute);
660     if (schema->attrgrpDecl != NULL)
661         xmlHashFree(schema->attrgrpDecl,
662                     (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
663     if (schema->elemDecl != NULL)
664         xmlHashFree(schema->elemDecl,
665                     (xmlHashDeallocator) xmlSchemaFreeElement);
666     if (schema->typeDecl != NULL)
667         xmlHashFree(schema->typeDecl,
668                     (xmlHashDeallocator) xmlSchemaFreeTypeList);
669     if (schema->groupDecl != NULL)
670         xmlHashFree(schema->groupDecl,
671                     (xmlHashDeallocator) xmlSchemaFreeType);
672     if (schema->schemasImports != NULL)
673     xmlHashFree(schema->schemasImports,
674             (xmlHashDeallocator) xmlSchemaFreeImport);
675     if (schema->includes != NULL) {
676         xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
677     }
678     if (schema->annot != NULL)
679         xmlSchemaFreeAnnot(schema->annot);
680     if (schema->doc != NULL && !schema->preserve)
681         xmlFreeDoc(schema->doc);
682     xmlDictFree(schema->dict);
683 
684     xmlFree(schema);
685 }
686 
687 /************************************************************************
688  *                                  *
689  *          Debug functions                 *
690  *                                  *
691  ************************************************************************/
692 
693 #ifdef LIBXML_OUTPUT_ENABLED
694 
695 /**
696  * xmlSchemaElementDump:
697  * @param elem an element
698  * @param output the file output
699  *
700  * Dump the element
701  */
702 static void
xmlSchemaElementDump(xmlSchemaElementPtr elem,FILE * output,const xmlChar * name ATTRIBUTE_UNUSED,const xmlChar * context ATTRIBUTE_UNUSED,const xmlChar * namespace ATTRIBUTE_UNUSED)703 xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
704                      const xmlChar * name ATTRIBUTE_UNUSED,
705                      const xmlChar * context ATTRIBUTE_UNUSED,
706                      const xmlChar * namespace ATTRIBUTE_UNUSED)
707 {
708     if (elem == NULL)
709         return;
710 
711     fprintf(output, "Element ");
712     if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
713         fprintf(output, "toplevel ");
714     fprintf(output, ": %s ", elem->name);
715     if (namespace != NULL)
716         fprintf(output, "namespace '%s' ", namespace);
717 
718     if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
719         fprintf(output, "nillable ");
720     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
721         fprintf(output, "global ");
722     if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
723         fprintf(output, "default ");
724     if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
725         fprintf(output, "fixed ");
726     if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
727         fprintf(output, "abstract ");
728     if (elem->flags & XML_SCHEMAS_ELEM_REF)
729         fprintf(output, "ref '%s' ", elem->ref);
730     if (elem->id != NULL)
731         fprintf(output, "id '%s' ", elem->id);
732     fprintf(output, "\n");
733     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
734         fprintf(output, "  ");
735         if (elem->minOccurs != 1)
736             fprintf(output, "min: %d ", elem->minOccurs);
737         if (elem->maxOccurs >= UNBOUNDED)
738             fprintf(output, "max: unbounded\n");
739         else if (elem->maxOccurs != 1)
740             fprintf(output, "max: %d\n", elem->maxOccurs);
741         else
742             fprintf(output, "\n");
743     }
744     if (elem->namedType != NULL) {
745         fprintf(output, "  type: %s", elem->namedType);
746         if (elem->namedTypeNs != NULL)
747             fprintf(output, " ns %s\n", elem->namedTypeNs);
748         else
749             fprintf(output, "\n");
750     }
751     if (elem->substGroup != NULL) {
752         fprintf(output, "  substitutionGroup: %s", elem->substGroup);
753         if (elem->substGroupNs != NULL)
754             fprintf(output, " ns %s\n", elem->substGroupNs);
755         else
756             fprintf(output, "\n");
757     }
758     if (elem->value != NULL)
759         fprintf(output, "  default: %s", elem->value);
760 }
761 
762 /**
763  * xmlSchemaAnnotDump:
764  * @param output the file output
765  * @param annot a annotation
766  *
767  * Dump the annotation
768  */
769 static void
xmlSchemaAnnotDump(FILE * output,xmlSchemaAnnotPtr annot)770 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
771 {
772     xmlChar *content;
773 
774     if (annot == NULL)
775         return;
776 
777     content = xmlNodeGetContent(annot->content);
778     if (content != NULL) {
779         fprintf(output, "  Annot: %s\n", content);
780         xmlFree(content);
781     } else
782         fprintf(output, "  Annot: empty\n");
783 }
784 
785 /**
786  * xmlSchemaTypeDump:
787  * @param output the file output
788  * @param type a type structure
789  *
790  * Dump a SchemaType structure
791  */
792 static void
xmlSchemaTypeDump(xmlSchemaTypePtr type,FILE * output)793 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
794 {
795     if (type == NULL) {
796         fprintf(output, "Type: NULL\n");
797         return;
798     }
799     fprintf(output, "Type: ");
800     if (type->name != NULL)
801         fprintf(output, "%s, ", type->name);
802     else
803         fprintf(output, "no name");
804     switch (type->type) {
805         case XML_SCHEMA_TYPE_BASIC:
806             fprintf(output, "basic ");
807             break;
808         case XML_SCHEMA_TYPE_SIMPLE:
809             fprintf(output, "simple ");
810             break;
811         case XML_SCHEMA_TYPE_COMPLEX:
812             fprintf(output, "complex ");
813             break;
814         case XML_SCHEMA_TYPE_SEQUENCE:
815             fprintf(output, "sequence ");
816             break;
817         case XML_SCHEMA_TYPE_CHOICE:
818             fprintf(output, "choice ");
819             break;
820         case XML_SCHEMA_TYPE_ALL:
821             fprintf(output, "all ");
822             break;
823         case XML_SCHEMA_TYPE_UR:
824             fprintf(output, "ur ");
825             break;
826         case XML_SCHEMA_TYPE_RESTRICTION:
827             fprintf(output, "restriction ");
828             break;
829         case XML_SCHEMA_TYPE_EXTENSION:
830             fprintf(output, "extension ");
831             break;
832         default:
833             fprintf(output, "unknowntype%d ", type->type);
834             break;
835     }
836     if (type->base != NULL) {
837         fprintf(output, "base %s, ", type->base);
838     }
839     switch (type->contentType) {
840         case XML_SCHEMA_CONTENT_UNKNOWN:
841             fprintf(output, "unknown ");
842             break;
843         case XML_SCHEMA_CONTENT_EMPTY:
844             fprintf(output, "empty ");
845             break;
846         case XML_SCHEMA_CONTENT_ELEMENTS:
847             fprintf(output, "element ");
848             break;
849         case XML_SCHEMA_CONTENT_MIXED:
850             fprintf(output, "mixed ");
851             break;
852         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
853             fprintf(output, "mixed_or_elems ");
854             break;
855         case XML_SCHEMA_CONTENT_BASIC:
856             fprintf(output, "basic ");
857             break;
858         case XML_SCHEMA_CONTENT_SIMPLE:
859             fprintf(output, "simple ");
860             break;
861         case XML_SCHEMA_CONTENT_ANY:
862             fprintf(output, "any ");
863             break;
864     }
865     fprintf(output, "\n");
866     if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
867         fprintf(output, "  ");
868         if (type->minOccurs != 1)
869             fprintf(output, "min: %d ", type->minOccurs);
870         if (type->maxOccurs >= UNBOUNDED)
871             fprintf(output, "max: unbounded\n");
872         else if (type->maxOccurs != 1)
873             fprintf(output, "max: %d\n", type->maxOccurs);
874         else
875             fprintf(output, "\n");
876     }
877     if (type->annot != NULL)
878         xmlSchemaAnnotDump(output, type->annot);
879     if (type->subtypes != NULL) {
880         xmlSchemaTypePtr sub = type->subtypes;
881 
882         fprintf(output, "  subtypes: ");
883         while (sub != NULL) {
884             fprintf(output, "%s ", sub->name);
885             sub = sub->next;
886         }
887         fprintf(output, "\n");
888     }
889 
890 }
891 
892 /**
893  * xmlSchemaDump:
894  * @param output the file output
895  * @param schema a schema structure
896  *
897  * Dump a Schema structure.
898  */
899 void
xmlSchemaDump(FILE * output,xmlSchemaPtr schema)900 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
901 {
902     if (schema == NULL) {
903         fprintf(output, "Schemas: NULL\n");
904         return;
905     }
906     fprintf(output, "Schemas: ");
907     if (schema->name != NULL)
908         fprintf(output, "%s, ", schema->name);
909     else
910         fprintf(output, "no name, ");
911     if (schema->targetNamespace != NULL)
912         fprintf(output, "%s", (const char *) schema->targetNamespace);
913     else
914         fprintf(output, "no target namespace");
915     fprintf(output, "\n");
916     if (schema->annot != NULL)
917         xmlSchemaAnnotDump(output, schema->annot);
918 
919     xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
920                 output);
921     xmlHashScanFull(schema->elemDecl,
922                     (xmlHashScannerFull) xmlSchemaElementDump, output);
923 }
924 #endif /* LIBXML_OUTPUT_ENABLED */
925 
926 /************************************************************************
927  *                                  *
928  *          Utilities                   *
929  *                                  *
930  ************************************************************************/
931 
932 /**
933  * xmlSchemaGetProp:
934  * @param ctxt the parser context
935  * @param node the node
936  * @param name the property name
937  *
938  * Read a attribute value and internalize the string
939  *
940  * Returns the string or NULL if not present.
941  */
942 static const xmlChar *
xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name)943 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
944                  const char *name)
945 {
946     xmlChar *val;
947     const xmlChar *ret;
948 
949     val = xmlGetProp(node, BAD_CAST name);
950     if (val == NULL)
951         return(NULL);
952     ret = xmlDictLookup(ctxt->dict, val, -1);
953     xmlFree(val);
954     return(ret);
955 }
956 
957 #if 0
958 /**
959  * xmlSchemaGetNamespace:
960  * @param ctxt the parser context
961  * @param schema the schemas containing the declaration
962  * @param node the node
963  * @param qname the QName to analyze
964  *
965  * Find the namespace name for the given declaration.
966  *
967  * Returns the local name for that declaration, as well as the namespace name
968  * NOTE: This function is no longer used (Buchcik, May '04)
969  */
970 static const xmlChar *
971 xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
972                   xmlNodePtr node, const xmlChar *qname,
973          const xmlChar **namespace) {
974     int len;
975     const xmlChar *name, *prefix, *def = NULL;
976     xmlNsPtr ns;
977 
978     *namespace = NULL;
979 
980     /* The following seems to be not correct here:
981      * 1. The name of a declaration is a NCName, not a QName.
982      * 2. The attribute "targetNamespace" is allowed for the
983      *    <schema> Element Information Item only.
984      * 3. One cannot evaluate the target namespace, by the type
985      *    of declaration, since it is dependant on the xxxFormDefault
986      *    of <schema> and the form attribute of an <element> or <attribute>.
987      */
988 
989     if (xmlStrEqual(node->name, BAD_CAST "element") ||
990         xmlStrEqual(node->name, BAD_CAST "attribute") ||
991     xmlStrEqual(node->name, BAD_CAST "simpleType") ||
992     xmlStrEqual(node->name, BAD_CAST "complexType")) {
993     def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
994     }
995 
996 
997     qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
998     name = xmlSplitQName3(qname, &len);
999     if (name == NULL) {
1000         if (def == NULL) {
1001         if (xmlStrEqual(node->name, BAD_CAST "element")) {
1002         if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
1003             *namespace = schema->targetNamespace;
1004         } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
1005         if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
1006             *namespace = schema->targetNamespace;
1007         } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
1008                    (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
1009         *namespace = schema->targetNamespace;
1010         }
1011     } else {
1012         *namespace = def;
1013     }
1014     return(qname);
1015     }
1016 
1017     name = xmlDictLookup(ctxt->dict, name, -1);
1018     prefix = xmlDictLookup(ctxt->dict, qname, len);
1019     if (def != NULL) {
1020         xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
1021                       "%s: presence of both prefix %s and targetNamespace\n",
1022                       node->name, prefix);
1023     }
1024     ns = xmlSearchNs(node->doc, node, prefix);
1025     if (ns == NULL) {
1026         xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1027                       "%s: the QName prefix %s is undefined\n",
1028                       node->name, prefix);
1029     return(name);
1030     }
1031     *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1032     return(name);
1033 }
1034 #endif
1035 
1036 /************************************************************************
1037  *                                  *
1038  *          Parsing functions               *
1039  *                                  *
1040  ************************************************************************/
1041 
1042 /**
1043  * xmlSchemaGetElem:
1044  * @param schema the schemas context
1045  * @param name the element name
1046  * @param ns the element namespace
1047  * @param level how deep is the request
1048  *
1049  * Lookup a an element in the schemas or the accessible schemas
1050  *
1051  * Returns the element definition or NULL if not found.
1052  */
1053 static xmlSchemaElementPtr
xmlSchemaGetElem(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * namespace,int level)1054 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
1055                  const xmlChar * namespace, int level)
1056 {
1057     xmlSchemaElementPtr ret;
1058     xmlSchemaImportPtr import = NULL;
1059 
1060     if ((name == NULL) || (schema == NULL))
1061         return (NULL);
1062 
1063     if (namespace == NULL) {
1064         ret = xmlHashLookup2(schema->elemDecl, name, namespace);
1065         if ((ret != NULL) &&
1066         ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
1067             return (ret);
1068     }
1069     /*
1070      * This one was removed, since top level element declarations have
1071      * the target namespace specified in targetNamespace of the <schema>
1072      * information element, even if elementFormDefault is "unqualified".
1073      */
1074 
1075     /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
1076         if (xmlStrEqual(namespace, schema->targetNamespace))
1077         ret = xmlHashLookup2(schema->elemDecl, name, NULL);
1078     else
1079         ret = xmlHashLookup2(schema->elemDecl, name, namespace);
1080         if ((ret != NULL) &&
1081         ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
1082             return (ret);
1083     }
1084     */
1085     } else {
1086     ret = xmlHashLookup2(schema->elemDecl, name, namespace);
1087         if ((ret != NULL) &&
1088         ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
1089             return (ret);
1090     }
1091     }
1092     if (level > 0)
1093     import = xmlHashLookup(schema->schemasImports, namespace);
1094     if (import != NULL)
1095     ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
1096 #ifdef DEBUG
1097     if (ret == NULL) {
1098         if (namespace == NULL)
1099             fprintf(stderr, "Unable to lookup type %s", name);
1100         else
1101             fprintf(stderr, "Unable to lookup type %s:%s", name,
1102                     namespace);
1103     }
1104 #endif
1105     return (ret);
1106 }
1107 
1108 /**
1109  * xmlSchemaGetType:
1110  * @param schema the schemas context
1111  * @param name the type name
1112  * @param ns the type namespace
1113  *
1114  * Lookup a type in the schemas or the predefined types
1115  *
1116  * Returns the group definition or NULL if not found.
1117  */
1118 static xmlSchemaTypePtr
xmlSchemaGetType(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * namespace)1119 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
1120                  const xmlChar * namespace)
1121 {
1122     xmlSchemaTypePtr ret;
1123     xmlSchemaImportPtr import;
1124 
1125     if (name == NULL)
1126         return (NULL);
1127     if (schema != NULL) {
1128         ret = xmlHashLookup2(schema->typeDecl, name, namespace);
1129         if (ret != NULL)
1130             return (ret);
1131     }
1132     ret = xmlSchemaGetPredefinedType(name, namespace);
1133     if (ret != NULL)
1134     return (ret);
1135     import = xmlHashLookup(schema->schemasImports, namespace);
1136     if (import != NULL)
1137     ret = xmlSchemaGetType(import->schema, name, namespace);
1138 #ifdef DEBUG
1139     if (ret == NULL) {
1140         if (namespace == NULL)
1141             fprintf(stderr, "Unable to lookup type %s", name);
1142         else
1143             fprintf(stderr, "Unable to lookup type %s:%s", name,
1144                     namespace);
1145     }
1146 #endif
1147     return (ret);
1148 }
1149 
1150 /************************************************************************
1151  *                                  *
1152  *          Parsing functions               *
1153  *                                  *
1154  ************************************************************************/
1155 
1156 #define IS_BLANK_NODE(n)                        \
1157     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1158 
1159 /**
1160  * xmlSchemaIsBlank:
1161  * @param str a string
1162  *
1163  * Check if a string is ignorable
1164  *
1165  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1166  */
1167 static int
xmlSchemaIsBlank(xmlChar * str)1168 xmlSchemaIsBlank(xmlChar * str)
1169 {
1170     if (str == NULL)
1171         return (1);
1172     while (*str != 0) {
1173         if (!(IS_BLANK_CH(*str)))
1174             return (0);
1175         str++;
1176     }
1177     return (1);
1178 }
1179 
1180 /**
1181  * xmlSchemaAddNotation:
1182  * @param ctxt a schema validation context
1183  * @param schema the schema being built
1184  * @param name the item name
1185  *
1186  * Add an XML schema Attrribute declaration
1187  * *WARNING* this interface is highly subject to change
1188  *
1189  * Returns the new struture or NULL in case of error
1190  */
1191 static xmlSchemaNotationPtr
xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name)1192 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1193                      const xmlChar * name)
1194 {
1195     xmlSchemaNotationPtr ret = NULL;
1196     int val;
1197 
1198     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1199         return (NULL);
1200 
1201     if (schema->notaDecl == NULL)
1202         schema->notaDecl = xmlHashCreate(10);
1203     if (schema->notaDecl == NULL)
1204         return (NULL);
1205 
1206     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1207     if (ret == NULL) {
1208         xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
1209         return (NULL);
1210     }
1211     memset(ret, 0, sizeof(xmlSchemaNotation));
1212     ret->name = xmlDictLookup(ctxt->dict, name, -1);
1213     val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1214                            ret);
1215     if (val != 0) {
1216     xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1217               XML_SCHEMAP_REDEFINED_NOTATION,
1218                       "Notation %s already defined\n",
1219                       name, NULL);
1220         xmlFree(ret);
1221         return (NULL);
1222     }
1223     return (ret);
1224 }
1225 
1226 
1227 /**
1228  * xmlSchemaAddAttribute:
1229  * @param ctxt a schema validation context
1230  * @param schema the schema being built
1231  * @param name the item name
1232  * @param namespace the namespace
1233  *
1234  * Add an XML schema Attrribute declaration
1235  * *WARNING* this interface is highly subject to change
1236  *
1237  * Returns the new struture or NULL in case of error
1238  */
1239 static xmlSchemaAttributePtr
xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * namespace)1240 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1241                       const xmlChar * name, const xmlChar * namespace)
1242 {
1243     xmlSchemaAttributePtr ret = NULL;
1244     int val;
1245 
1246     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1247         return (NULL);
1248 
1249 #ifdef DEBUG
1250     fprintf(stderr, "Adding attribute %s\n", name);
1251     if (namespace != NULL)
1252     fprintf(stderr, "  target namespace %s\n", namespace);
1253 #endif
1254 
1255     if (schema->attrDecl == NULL)
1256         schema->attrDecl = xmlHashCreate(10);
1257     if (schema->attrDecl == NULL)
1258         return (NULL);
1259 
1260     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1261     if (ret == NULL) {
1262         xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
1263         return (NULL);
1264     }
1265     memset(ret, 0, sizeof(xmlSchemaAttribute));
1266     ret->name = xmlDictLookup(ctxt->dict, name, -1);
1267     ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
1268     val = xmlHashAddEntry3(schema->attrDecl, name,
1269                            schema->targetNamespace, ctxt->container, ret);
1270     if (val != 0) {
1271     xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1272               XML_SCHEMAP_REDEFINED_ATTR,
1273                       "Attribute %s already defined\n",
1274                       name, NULL);
1275         xmlFree(ret);
1276         return (NULL);
1277     }
1278     return (ret);
1279 }
1280 
1281 /**
1282  * xmlSchemaAddAttributeGroup:
1283  * @param ctxt a schema validation context
1284  * @param schema the schema being built
1285  * @param name the item name
1286  *
1287  * Add an XML schema Attrribute Group declaration
1288  *
1289  * Returns the new struture or NULL in case of error
1290  */
1291 static xmlSchemaAttributeGroupPtr
xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name)1292 xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1293                            xmlSchemaPtr schema, const xmlChar * name)
1294 {
1295     xmlSchemaAttributeGroupPtr ret = NULL;
1296     int val;
1297 
1298     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1299         return (NULL);
1300 
1301     if (schema->attrgrpDecl == NULL)
1302         schema->attrgrpDecl = xmlHashCreate(10);
1303     if (schema->attrgrpDecl == NULL)
1304         return (NULL);
1305 
1306     ret =
1307         (xmlSchemaAttributeGroupPtr)
1308         xmlMalloc(sizeof(xmlSchemaAttributeGroup));
1309     if (ret == NULL) {
1310         xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
1311         return (NULL);
1312     }
1313     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
1314     ret->name = xmlDictLookup(ctxt->dict, name, -1);
1315     val = xmlHashAddEntry3(schema->attrgrpDecl, name,
1316                            schema->targetNamespace, ctxt->container, ret);
1317     if (val != 0) {
1318     xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1319               XML_SCHEMAP_REDEFINED_ATTRGROUP,
1320                       "Attribute group %s already defined\n",
1321                       name, NULL);
1322         xmlFree(ret);
1323         return (NULL);
1324     }
1325     return (ret);
1326 }
1327 
1328 /**
1329  * xmlSchemaAddElement:
1330  * @param ctxt a schema validation context
1331  * @param schema the schema being built
1332  * @param name the type name
1333  * @param namespace the type namespace
1334  *
1335  * Add an XML schema Element declaration
1336  * *WARNING* this interface is highly subject to change
1337  *
1338  * Returns the new struture or NULL in case of error
1339  */
1340 static xmlSchemaElementPtr
xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * namespace)1341 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1342                     const xmlChar * name, const xmlChar * namespace)
1343 {
1344     xmlSchemaElementPtr ret = NULL;
1345     int val;
1346 
1347     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1348         return (NULL);
1349 
1350 #ifdef DEBUG
1351     fprintf(stderr, "Adding element %s\n", name);
1352     if (namespace != NULL)
1353     fprintf(stderr, "  target namespace %s\n", namespace);
1354 #endif
1355 
1356     if (schema->elemDecl == NULL)
1357         schema->elemDecl = xmlHashCreate(10);
1358     if (schema->elemDecl == NULL)
1359         return (NULL);
1360 
1361     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1362     if (ret == NULL) {
1363         xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
1364         return (NULL);
1365     }
1366     memset(ret, 0, sizeof(xmlSchemaElement));
1367     ret->name = xmlDictLookup(ctxt->dict, name, -1);
1368     ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
1369     val = xmlHashAddEntry3(schema->elemDecl, name,
1370                            namespace, ctxt->container, ret);
1371     if (val != 0) {
1372         char buf[100];
1373 
1374         snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
1375         val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1376                                namespace, ret);
1377         if (val != 0) {
1378         xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1379               XML_SCHEMAP_REDEFINED_ELEMENT,
1380               "Element %s already defined\n",
1381               name, NULL);
1382             xmlFree(ret);
1383             return (NULL);
1384         }
1385     }
1386     return (ret);
1387 }
1388 
1389 /**
1390  * xmlSchemaAddType:
1391  * @param ctxt a schema validation context
1392  * @param schema the schema being built
1393  * @param name the item name
1394  * @param namespace the namespace
1395  *
1396  * Add an XML schema Simple Type definition
1397  * *WARNING* this interface is highly subject to change
1398  *
1399  * Returns the new struture or NULL in case of error
1400  */
1401 static xmlSchemaTypePtr
xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * namespace)1402 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1403                  const xmlChar * name, const xmlChar * namespace)
1404 {
1405     xmlSchemaTypePtr ret = NULL;
1406     int val;
1407 
1408     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1409         return (NULL);
1410 
1411 #ifdef DEBUG
1412     fprintf(stderr, "Adding type %s\n", name);
1413     if (namespace != NULL)
1414     fprintf(stderr, "  target namespace %s\n", namespace);
1415 #endif
1416 
1417     if (schema->typeDecl == NULL)
1418         schema->typeDecl = xmlHashCreate(10);
1419     if (schema->typeDecl == NULL)
1420         return (NULL);
1421 
1422     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1423     if (ret == NULL) {
1424         xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
1425         return (NULL);
1426     }
1427     memset(ret, 0, sizeof(xmlSchemaType));
1428     ret->name = xmlDictLookup(ctxt->dict, name, -1);
1429     ret->redef = NULL;
1430     val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
1431     if (val != 0) {
1432         if (ctxt->includes == 0) {
1433         xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1434               XML_SCHEMAP_REDEFINED_TYPE,
1435               "Type %s already defined\n",
1436               name, NULL);
1437         xmlFree(ret);
1438         return (NULL);
1439     } else {
1440         xmlSchemaTypePtr prev;
1441 
1442         prev = xmlHashLookup2(schema->typeDecl, name, namespace);
1443         if (prev == NULL) {
1444         xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1445                   XML_ERR_INTERNAL_ERROR,
1446                   "Internal error on type %s definition\n",
1447                   name, NULL);
1448         xmlFree(ret);
1449         return (NULL);
1450         }
1451         ret->redef = prev->redef;
1452         prev->redef = ret;
1453     }
1454     }
1455     ret->minOccurs = 1;
1456     ret->maxOccurs = 1;
1457 
1458     return (ret);
1459 }
1460 
1461 /**
1462  * xmlSchemaAddGroup:
1463  * @param ctxt a schema validation context
1464  * @param schema the schema being built
1465  * @param name the group name
1466  *
1467  * Add an XML schema Group definition
1468  *
1469  * Returns the new struture or NULL in case of error
1470  */
1471 static xmlSchemaTypePtr
xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name)1472 xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1473                   const xmlChar * name)
1474 {
1475     xmlSchemaTypePtr ret = NULL;
1476     int val;
1477 
1478     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1479         return (NULL);
1480 
1481     if (schema->groupDecl == NULL)
1482         schema->groupDecl = xmlHashCreate(10);
1483     if (schema->groupDecl == NULL)
1484         return (NULL);
1485 
1486     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1487     if (ret == NULL) {
1488         xmlSchemaPErrMemory(ctxt, "adding group", NULL);
1489         return (NULL);
1490     }
1491     memset(ret, 0, sizeof(xmlSchemaType));
1492     ret->name = xmlDictLookup(ctxt->dict, name, -1);
1493     val =
1494         xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1495                          ret);
1496     if (val != 0) {
1497     xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1498               XML_SCHEMAP_REDEFINED_GROUP,
1499                       "Group %s already defined\n",
1500                       name, NULL);
1501         xmlFree(ret);
1502         return (NULL);
1503     }
1504     ret->minOccurs = 1;
1505     ret->maxOccurs = 1;
1506 
1507     return (ret);
1508 }
1509 
1510 /************************************************************************
1511  *                                  *
1512  *      Utilities for parsing                   *
1513  *                                  *
1514  ************************************************************************/
1515 
1516 /**
1517  * xmlGetQNameProp:
1518  * @param ctxt a schema validation context
1519  * @param node a subtree containing XML Schema informations
1520  * @param name the attribute name
1521  * @param namespace the result namespace if any
1522  *
1523  * Extract a QName Attribute value
1524  *
1525  * Returns the NCName or NULL if not found, and also update @namespace
1526  *    with the namespace URI
1527  */
1528 static const xmlChar *
xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name,const xmlChar ** namespace)1529 xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1530                 const char *name, const xmlChar ** namespace)
1531 {
1532     const xmlChar *val;
1533     xmlNsPtr ns;
1534     const xmlChar *ret, *prefix;
1535     int len;
1536 
1537     *namespace = NULL;
1538     val = xmlSchemaGetProp(ctxt, node, name);
1539     if (val == NULL)
1540         return (NULL);
1541 
1542     if (!strchr((char *) val, ':')) {
1543     ns = xmlSearchNs(node->doc, node, 0);
1544     if (ns) {
1545         *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1546         return (val);
1547     }
1548     }
1549     ret = xmlSplitQName3(val, &len);
1550     if (ret == NULL) {
1551         return (val);
1552     }
1553     ret = xmlDictLookup(ctxt->dict, ret, -1);
1554     prefix = xmlDictLookup(ctxt->dict, val, len);
1555 
1556     ns = xmlSearchNs(node->doc, node, prefix);
1557     if (ns == NULL) {
1558         xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1559                       "Attribute %s: the QName prefix %s is undefined\n",
1560                       (const xmlChar *) name, prefix);
1561     } else {
1562         *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1563     }
1564     return (ret);
1565 }
1566 
1567 /**
1568  * xmlGetMaxOccurs:
1569  * @param ctxt a schema validation context
1570  * @param node a subtree containing XML Schema informations
1571  *
1572  * Get the maxOccurs property
1573  *
1574  * Returns the default if not found, or the value
1575  */
1576 static int
xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)1577 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1578 {
1579     const xmlChar *val, *cur;
1580     int ret = 0;
1581 
1582     val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
1583     if (val == NULL)
1584         return (1);
1585 
1586     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
1587         return (UNBOUNDED);  /* encoding it with -1 might be another option */
1588     }
1589 
1590     cur = val;
1591     while (IS_BLANK_CH(*cur))
1592         cur++;
1593     while ((*cur >= '0') && (*cur <= '9')) {
1594         ret = ret * 10 + (*cur - '0');
1595         cur++;
1596     }
1597     while (IS_BLANK_CH(*cur))
1598         cur++;
1599     if (*cur != 0) {
1600         xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1601                       "invalid value for maxOccurs: %s\n", val, NULL);
1602         return (1);
1603     }
1604     return (ret);
1605 }
1606 
1607 /**
1608  * xmlGetMinOccurs:
1609  * @param ctxt a schema validation context
1610  * @param node a subtree containing XML Schema informations
1611  *
1612  * Get the minOccurs property
1613  *
1614  * Returns the default if not found, or the value
1615  */
1616 static int
xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)1617 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1618 {
1619     const xmlChar *val, *cur;
1620     int ret = 0;
1621 
1622     val = xmlSchemaGetProp(ctxt, node, "minOccurs");
1623     if (val == NULL)
1624         return (1);
1625 
1626     cur = val;
1627     while (IS_BLANK_CH(*cur))
1628         cur++;
1629     while ((*cur >= '0') && (*cur <= '9')) {
1630         ret = ret * 10 + (*cur - '0');
1631         cur++;
1632     }
1633     while (IS_BLANK_CH(*cur))
1634         cur++;
1635     if (*cur != 0) {
1636         xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1637                       "invalid value for minOccurs: %s\n", val, NULL);
1638         return (1);
1639     }
1640     return (ret);
1641 }
1642 
1643 /**
1644  * xmlGetBooleanProp:
1645  * @param ctxt a schema validation context
1646  * @param node a subtree containing XML Schema informations
1647  * @param name the attribute name
1648  * @param def the default value
1649  *
1650  * Get is a bolean property is set
1651  *
1652  * Returns the default if not found, 0 if found to be false,
1653  *         1 if found to be true
1654  */
1655 static int
xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name,int def)1656 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1657                   const char *name, int def)
1658 {
1659     const xmlChar *val;
1660 
1661     val = xmlSchemaGetProp(ctxt, node, name);
1662     if (val == NULL)
1663         return (def);
1664 
1665     if (xmlStrEqual(val, BAD_CAST "true"))
1666         def = 1;
1667     else if (xmlStrEqual(val, BAD_CAST "false"))
1668         def = 0;
1669     else {
1670         xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1671                       "Attribute %s: the value %s is not boolean\n",
1672                       (const xmlChar *) name, val);
1673     }
1674     return (def);
1675 }
1676 
1677 /************************************************************************
1678  *                                  *
1679  *      Shema extraction from an Infoset            *
1680  *                                  *
1681  ************************************************************************/
1682 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1683                                                  ctxt, xmlSchemaPtr schema,
1684                                                  xmlNodePtr node);
1685 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1686                                                   ctxt,
1687                                                   xmlSchemaPtr schema,
1688                                                   xmlNodePtr node);
1689 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1690                                                   ctxt,
1691                                                   xmlSchemaPtr schema,
1692                                                   xmlNodePtr node,
1693                                                   int simple);
1694 static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1695                                                xmlSchemaPtr schema,
1696                                                xmlNodePtr node);
1697 static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1698                                           xmlSchemaPtr schema,
1699                                           xmlNodePtr node);
1700 static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1701                                                      ctxt,
1702                                                      xmlSchemaPtr schema,
1703                                                      xmlNodePtr node,
1704                              int topLevel);
1705 static xmlSchemaAttributeGroupPtr
1706 xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1707                              xmlSchemaPtr schema, xmlNodePtr node);
1708 static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1709                                              xmlSchemaPtr schema,
1710                                              xmlNodePtr node);
1711 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1712                                            xmlSchemaPtr schema,
1713                                            xmlNodePtr node);
1714 static xmlSchemaAttributePtr
1715 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1716                            xmlSchemaPtr schema, xmlNodePtr node);
1717 
1718 /**
1719  * xmlSchemaParseAttrDecls:
1720  * @param ctxt a schema validation context
1721  * @param schema the schema being built
1722  * @param node a subtree containing XML Schema informations
1723  * @param type the hosting type
1724  *
1725  * parse a XML schema attrDecls declaration corresponding to
1726  * <!ENTITY % attrDecls
1727  *       '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1728  */
1729 static xmlNodePtr
xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr child,xmlSchemaTypePtr type)1730 xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1731                         xmlNodePtr child, xmlSchemaTypePtr type)
1732 {
1733     xmlSchemaAttributePtr lastattr, attr;
1734 
1735     lastattr = NULL;
1736     while ((IS_SCHEMA(child, "attribute")) ||
1737            (IS_SCHEMA(child, "attributeGroup"))) {
1738         attr = NULL;
1739         if (IS_SCHEMA(child, "attribute")) {
1740             attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
1741         } else if (IS_SCHEMA(child, "attributeGroup")) {
1742             attr = (xmlSchemaAttributePtr)
1743                 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1744         }
1745         if (attr != NULL) {
1746             if (lastattr == NULL) {
1747                 type->attributes = attr;
1748                 lastattr = attr;
1749             } else {
1750                 lastattr->next = attr;
1751                 lastattr = attr;
1752             }
1753         }
1754         child = child->next;
1755     }
1756     if (IS_SCHEMA(child, "anyAttribute")) {
1757         attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1758         if (attr != NULL) {
1759             if (lastattr == NULL) {
1760                 type->attributes = attr;
1761                 lastattr = attr;
1762             } else {
1763                 lastattr->next = attr;
1764                 lastattr = attr;
1765             }
1766         }
1767         child = child->next;
1768     }
1769     return (child);
1770 }
1771 
1772 /**
1773  * xmlSchemaParseAnnotation:
1774  * @param ctxt a schema validation context
1775  * @param schema the schema being built
1776  * @param node a subtree containing XML Schema informations
1777  *
1778  * parse a XML schema Attrribute declaration
1779  * *WARNING* this interface is highly subject to change
1780  *
1781  * Returns -1 in case of error, 0 if the declaration is improper and
1782  *         1 in case of success.
1783  */
1784 static xmlSchemaAnnotPtr
xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)1785 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1786                          xmlNodePtr node)
1787 {
1788     xmlSchemaAnnotPtr ret;
1789 
1790     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1791         return (NULL);
1792     ret = xmlSchemaNewAnnot(ctxt, node);
1793 
1794     return (ret);
1795 }
1796 
1797 /**
1798  * xmlSchemaParseFacet:
1799  * @param ctxt a schema validation context
1800  * @param schema the schema being built
1801  * @param node a subtree containing XML Schema informations
1802  *
1803  * parse a XML schema Facet declaration
1804  * *WARNING* this interface is highly subject to change
1805  *
1806  * Returns the new type structure or NULL in case of error
1807  */
1808 static xmlSchemaFacetPtr
xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)1809 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1810                     xmlNodePtr node)
1811 {
1812     xmlSchemaFacetPtr facet;
1813     xmlNodePtr child = NULL;
1814     const xmlChar *value;
1815 
1816     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1817         return (NULL);
1818 
1819     facet = xmlSchemaNewFacet();
1820     if (facet == NULL) {
1821         xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1822         return (NULL);
1823     }
1824     facet->node = node;
1825     value = xmlSchemaGetProp(ctxt, node, "value");
1826     if (value == NULL) {
1827         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1828                        "Facet %s has no value\n", node->name, NULL);
1829         xmlSchemaFreeFacet(facet);
1830         return (NULL);
1831     }
1832     if (IS_SCHEMA(node, "minInclusive")) {
1833         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
1834     } else if (IS_SCHEMA(node, "minExclusive")) {
1835         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
1836     } else if (IS_SCHEMA(node, "maxInclusive")) {
1837         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
1838     } else if (IS_SCHEMA(node, "maxExclusive")) {
1839         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
1840     } else if (IS_SCHEMA(node, "totalDigits")) {
1841         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
1842     } else if (IS_SCHEMA(node, "fractionDigits")) {
1843         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
1844     } else if (IS_SCHEMA(node, "pattern")) {
1845         facet->type = XML_SCHEMA_FACET_PATTERN;
1846     } else if (IS_SCHEMA(node, "enumeration")) {
1847         facet->type = XML_SCHEMA_FACET_ENUMERATION;
1848     } else if (IS_SCHEMA(node, "whiteSpace")) {
1849         facet->type = XML_SCHEMA_FACET_WHITESPACE;
1850     } else if (IS_SCHEMA(node, "length")) {
1851         facet->type = XML_SCHEMA_FACET_LENGTH;
1852     } else if (IS_SCHEMA(node, "maxLength")) {
1853         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1854     } else if (IS_SCHEMA(node, "minLength")) {
1855         facet->type = XML_SCHEMA_FACET_MINLENGTH;
1856     } else {
1857         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1858                        "Unknown facet type %s\n", node->name, NULL);
1859         xmlSchemaFreeFacet(facet);
1860         return (NULL);
1861     }
1862     facet->id = xmlSchemaGetProp(ctxt, node, "id");
1863     facet->value = value;
1864     child = node->children;
1865 
1866     if (IS_SCHEMA(child, "annotation")) {
1867         facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1868         child = child->next;
1869     }
1870     if (child != NULL) {
1871         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1872                        "Facet %s has unexpected child content\n",
1873                        node->name, NULL);
1874     }
1875     return (facet);
1876 }
1877 
1878 /**
1879  * xmlSchemaParseAny:
1880  * @param ctxt a schema validation context
1881  * @param schema the schema being built
1882  * @param node a subtree containing XML Schema informations
1883  *
1884  * parse a XML schema Any declaration
1885  * *WARNING* this interface is highly subject to change
1886  *
1887  * Returns the new type structure or NULL in case of error
1888  */
1889 static xmlSchemaTypePtr
xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)1890 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1891                   xmlNodePtr node)
1892 {
1893     xmlSchemaTypePtr type;
1894     xmlNodePtr child = NULL;
1895     xmlChar name[30];
1896 
1897     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1898         return (NULL);
1899     snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
1900     type = xmlSchemaAddType(ctxt, schema, name, NULL);
1901     if (type == NULL)
1902         return (NULL);
1903     type->node = node;
1904     type->type = XML_SCHEMA_TYPE_ANY;
1905     child = node->children;
1906     type->minOccurs = xmlGetMinOccurs(ctxt, node);
1907     type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1908 
1909     if (IS_SCHEMA(child, "annotation")) {
1910         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1911         child = child->next;
1912     }
1913     if (child != NULL) {
1914         xmlSchemaPErr2(ctxt, node, child,
1915                        XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1916                        "Sequence %s has unexpected content\n", type->name,
1917                        NULL);
1918     }
1919 
1920     return (type);
1921 }
1922 
1923 /**
1924  * xmlSchemaParseNotation:
1925  * @param ctxt a schema validation context
1926  * @param schema the schema being built
1927  * @param node a subtree containing XML Schema informations
1928  *
1929  * parse a XML schema Notation declaration
1930  *
1931  * Returns the new structure or NULL in case of error
1932  */
1933 static xmlSchemaNotationPtr
xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)1934 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1935                        xmlNodePtr node)
1936 {
1937     const xmlChar *name;
1938     xmlSchemaNotationPtr ret;
1939     xmlNodePtr child = NULL;
1940 
1941     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1942         return (NULL);
1943     name = xmlSchemaGetProp(ctxt, node, "name");
1944     if (name == NULL) {
1945         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1946                        "Notation has no name\n", NULL, NULL);
1947         return (NULL);
1948     }
1949     ret = xmlSchemaAddNotation(ctxt, schema, name);
1950     if (ret == NULL) {
1951         return (NULL);
1952     }
1953     child = node->children;
1954     if (IS_SCHEMA(child, "annotation")) {
1955         ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1956         child = child->next;
1957     }
1958     if (child != NULL) {
1959         xmlSchemaPErr2(ctxt, node, child,
1960                        XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1961                        "notation %s has unexpected content\n", name, NULL);
1962     }
1963 
1964     return (ret);
1965 }
1966 
1967 /**
1968  * xmlSchemaParseAnyAttribute:
1969  * @param ctxt a schema validation context
1970  * @param schema the schema being built
1971  * @param node a subtree containing XML Schema informations
1972  *
1973  * parse a XML schema AnyAttrribute declaration
1974  * *WARNING* this interface is highly subject to change
1975  *
1976  * Returns an attribute def structure or NULL
1977  */
1978 static xmlSchemaAttributePtr
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)1979 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1980                            xmlSchemaPtr schema, xmlNodePtr node)
1981 {
1982     const xmlChar *processContents;
1983     xmlSchemaAttributePtr ret;
1984     xmlNodePtr child = NULL;
1985     char name[100];
1986 
1987 
1988     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1989         return (NULL);
1990 
1991     snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
1992 
1993     /* local = xmlSchemaGetNamespace(ctxt, schema, node, BAD_CAST "anyattr", &ns); */
1994 
1995     /*
1996      *  namespace = ((##any | ##other) | List of (anyURI |
1997      *                    (##targetNamespace | * ##local)) )  : ##any
1998      */
1999     ret = xmlSchemaAddAttribute(ctxt, schema, BAD_CAST name, NULL);
2000     if (ret == NULL) {
2001         return (NULL);
2002     }
2003     ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
2004     ret->id = xmlSchemaGetProp(ctxt, node, "id");
2005     processContents = xmlSchemaGetProp(ctxt, node, "processContents");
2006     if ((processContents == NULL)
2007         || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
2008         ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
2009     } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
2010         ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
2011     } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
2012         ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
2013     } else {
2014         xmlSchemaPErr2(ctxt, node, child,
2015                        XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
2016                        "anyAttribute has unexpected content "
2017                "for processContents: %s\n",
2018                        processContents, NULL);
2019         ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
2020     }
2021 
2022     child = node->children;
2023     if (IS_SCHEMA(child, "annotation")) {
2024         ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2025         child = child->next;
2026     }
2027     if (child != NULL) {
2028         xmlSchemaPErr2(ctxt, node, child,
2029                        XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
2030                        "anyAttribute %s has unexpected content\n",
2031                        (const xmlChar *) name, NULL);
2032     }
2033 
2034     return (ret);
2035 }
2036 
2037 
2038 /**
2039  * xmlSchemaParseAttribute:
2040  * @param ctxt a schema validation context
2041  * @param schema the schema being built
2042  * @param node a subtree containing XML Schema informations
2043  *
2044  * parse a XML schema Attrribute declaration
2045  * *WARNING* this interface is highly subject to change
2046  *
2047  * Returns the attribute declaration.
2048  */
2049 static xmlSchemaAttributePtr
xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)2050 xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2051                         xmlNodePtr node, int topLevel)
2052 {
2053     const xmlChar *name, *refNs = NULL, *ref = NULL, *attrVal;
2054     xmlSchemaAttributePtr ret;
2055     xmlNodePtr child = NULL;
2056     char buf[100];
2057     int hasRefType = 0;
2058 
2059     /*
2060      * Note that the w3c spec assumes the schema to be validated with schema
2061      * for schemas beforehand.
2062      *
2063      * 3.2.3 Constraints on XML Representations of Attribute Declarations
2064      *
2065      *  Complete implementation of:
2066      * 3.2.6 Schema Component Constraint: Attribute Declaration Properties
2067      *       Correct
2068      */
2069 
2070     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2071         return (NULL);
2072 
2073     name = xmlSchemaGetProp(ctxt, node, "name");
2074     if (name == NULL) {
2075         ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2076     /* 3.2.3 : 3.1
2077      * One of ref or name must be present, but not both
2078      */
2079         if (ref == NULL) {
2080             xmlSchemaPErr(ctxt, node,
2081               XML_SCHEMAP_ATTR_NONAME_NOREF,
2082               "Attribute declaration has no \"name\" or \"ref\"\n",
2083               NULL, NULL);
2084         return (NULL);
2085         }
2086     hasRefType = 1;
2087         snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2088         name = (const xmlChar *) buf;
2089     ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
2090     if (!topLevel) {
2091         /* 3.2.3 : 3.2
2092          * If ref is present, then all of <simpleType>,
2093          * form and type must be absent.
2094          */
2095         if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2096         xmlSchemaPErr(ctxt, node,
2097                       XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2098                   "Attribute declaration %s has \"ref\", thus "
2099                   "\"form\" must be absent\n", name, NULL);
2100         }
2101         if (xmlSchemaGetProp(ctxt, node, "type") != NULL) {
2102         xmlSchemaPErr(ctxt, node,
2103                       XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2104                   "Attribute declaration %s has \"ref\", thus "
2105                   "\"type\" must be absent\n", name, NULL);
2106         }
2107     }
2108     } else {
2109         const xmlChar *ns = NULL;
2110     /* 3.2.3 : 3.1
2111      * One of ref or name must be present, but not both
2112      */
2113     if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
2114         xmlSchemaPErr(ctxt, node,
2115                           XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2116                           "Attribute declaration has both, \"name\" and "
2117               "\"ref\"\n", NULL, NULL);
2118     }
2119 
2120         /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2121     /* Evaluate the target namespace */
2122     if (schema->targetNamespace != NULL) {
2123         if (topLevel) {
2124         ns = schema->targetNamespace;
2125         } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2126         if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2127                  BAD_CAST "qualified")) {
2128             ns = schema->targetNamespace;
2129         }
2130         } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2131         ns = schema->targetNamespace;
2132         }
2133     }
2134     ret = xmlSchemaAddAttribute(ctxt, schema, name, ns);
2135 
2136     /* 3.2.6 Schema Component Constraint: xmlns Not Allowed */
2137     if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2138         xmlSchemaPErr(ctxt, node,
2139                       XML_SCHEMAP_INVALID_ATTR_NAME,
2140                       "The name of an attribute declaration must not match "
2141               "\"xmlns\".\n", NULL, NULL);
2142     }
2143 
2144     /* 3.2.6 Schema Component Constraint: xsi: Not Allowed */
2145     if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
2146         xmlSchemaPErr(ctxt, node,
2147                           XML_SCHEMAP_INVALID_ATTR_NAME,
2148                       "The target namespace of an attribute declaration, "
2149               "must not match \"http://www.w3.org/2001/"
2150               "XMLSchema-instance\"", NULL, NULL);
2151     }
2152     }
2153     if (ret == NULL) {
2154         return (NULL);
2155     }
2156     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
2157 
2158     /* Handle the "use" attribute. */
2159     attrVal = xmlSchemaGetProp(ctxt, node, "use");
2160     if (attrVal != NULL) {
2161     if (xmlStrEqual(attrVal, BAD_CAST "optional"))
2162         ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
2163     else if (xmlStrEqual(attrVal, BAD_CAST "prohibited"))
2164         ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
2165     else if (xmlStrEqual(attrVal, BAD_CAST "required"))
2166         ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
2167     else
2168         xmlSchemaPErr(ctxt, node,
2169               XML_SCHEMAP_INVALID_ATTR_USE,
2170               "Attribute declaration %s has an invalid "
2171               "value for \"use\"\n", name, NULL);
2172     } else
2173     ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
2174 
2175 
2176     if (xmlSchemaGetProp(ctxt, node, "default") != NULL) {
2177     /* 3.2.3 : 1
2178      * default and fixed must not both be present.
2179      */
2180     if (xmlSchemaGetProp(ctxt, node, "fixed") != NULL) {
2181         xmlSchemaPErr(ctxt, node,
2182                           XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2183                           "Attribute declaration has both, \"default\" "
2184               "and \"fixed\"\n", NULL, NULL);
2185     }
2186     /* 3.2.3 : 2
2187      * If default and use are both present, use must have
2188      * the actual value optional.
2189      */
2190     if (ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) {
2191         xmlSchemaPErr(ctxt, node,
2192                           XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2193                           "Attribute declaration has \"default\" but "
2194               "\"use\" is not \"optional\"\n", NULL, NULL);
2195     }
2196     }
2197 
2198     ret->ref = ref;
2199     ret->refNs = refNs;
2200     /*
2201      * The setting of XML_SCHEMAS_ATTR_NSDEFAULT is not needed anymore,
2202      * since the target namespace was already evaluated and took
2203      * attributeFormDefault into account.
2204      */
2205     /*
2206     if ((ret->targetNamespace != NULL) &&
2207         ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2208     (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2209     ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
2210     */
2211     ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
2212     if (ret->typeName != NULL)
2213     hasRefType = 1;
2214     ret->node = node;
2215     child = node->children;
2216     if (IS_SCHEMA(child, "annotation")) {
2217         ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2218         child = child->next;
2219     }
2220     if (IS_SCHEMA(child, "simpleType")) {
2221     if (hasRefType) {
2222         /* 3.2.3 : 4
2223          * type and <simpleType> must not both be present.
2224          *
2225          *
2226          *
2227          */
2228         xmlSchemaPErr2(ctxt, node, child,
2229                        XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2230                            "Attribute declaration %s has both (\"ref\" or "
2231                "\"type\") and <simpleType>\n", name, NULL);
2232     } else
2233         ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
2234         child = child->next;
2235     }
2236     if (child != NULL) {
2237         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2238                        "attribute %s has unexpected content\n", name,
2239                        NULL);
2240     }
2241 
2242     return (ret);
2243 }
2244 
2245 /**
2246  * xmlSchemaParseAttributeGroup:
2247  * @param ctxt a schema validation context
2248  * @param schema the schema being built
2249  * @param node a subtree containing XML Schema informations
2250  *
2251  * parse a XML schema Attribute Group declaration
2252  * *WARNING* this interface is highly subject to change
2253  *
2254  * Returns the attribute group or NULL in case of error.
2255  */
2256 static xmlSchemaAttributeGroupPtr
xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)2257 xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
2258                              xmlSchemaPtr schema, xmlNodePtr node)
2259 {
2260     const xmlChar *name, *refNs = NULL, *ref = NULL;
2261     xmlSchemaAttributeGroupPtr ret;
2262     xmlSchemaAttributePtr last = NULL, attr;
2263     xmlNodePtr child = NULL;
2264     const xmlChar *oldcontainer;
2265     char buf[100];
2266 
2267     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2268         return (NULL);
2269     oldcontainer = ctxt->container;
2270     name = xmlSchemaGetProp(ctxt, node, "name");
2271     if (name == NULL) {
2272 
2273         ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2274         if (ref == NULL) {
2275             xmlSchemaPErr2(ctxt, node, child,
2276                            XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
2277                            "AttributeGroup has no name nor ref\n", NULL,
2278                            NULL);
2279             return (NULL);
2280         }
2281         snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
2282         name = (const xmlChar *) buf;
2283         if (name == NULL) {
2284         xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
2285             return (NULL);
2286         }
2287     }
2288     ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2289     if (ret == NULL) {
2290         return (NULL);
2291     }
2292     ret->ref = ref;
2293     ret->refNs = refNs;
2294     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
2295     ret->node = node;
2296     child = node->children;
2297     ctxt->container = name;
2298     if (IS_SCHEMA(child, "annotation")) {
2299         ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2300         child = child->next;
2301     }
2302     while ((IS_SCHEMA(child, "attribute")) ||
2303            (IS_SCHEMA(child, "attributeGroup"))) {
2304         attr = NULL;
2305         if (IS_SCHEMA(child, "attribute")) {
2306             attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
2307         } else if (IS_SCHEMA(child, "attributeGroup")) {
2308             attr = (xmlSchemaAttributePtr)
2309                 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2310         }
2311         if (attr != NULL) {
2312             if (last == NULL) {
2313                 ret->attributes = attr;
2314                 last = attr;
2315             } else {
2316                 last->next = attr;
2317                 last = attr;
2318             }
2319         }
2320         child = child->next;
2321     }
2322     if (IS_SCHEMA(child, "anyAttribute")) {
2323         TODO
2324     child = child->next;
2325     }
2326     if (child != NULL) {
2327         xmlSchemaPErr2(ctxt, node, child,
2328                        XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2329                        "attribute group %s has unexpected content\n", name,
2330                        NULL);
2331     }
2332     ctxt->container = oldcontainer;
2333     return (ret);
2334 }
2335 
2336 /**
2337  * xmlSchemaParseElement:
2338  * @param ctxt a schema validation context
2339  * @param schema the schema being built
2340  * @param node a subtree containing XML Schema informations
2341  *
2342  * parse a XML schema Element declaration
2343  * *WARNING* this interface is highly subject to change
2344  *
2345  * Returns the parsed element declaration.
2346  */
2347 static xmlSchemaElementPtr
xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int toplevel)2348 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2349                       xmlNodePtr node, int toplevel)
2350 {
2351     const xmlChar *name, *fixed;
2352     const xmlChar *refNs = NULL, *ref = NULL;
2353     xmlSchemaElementPtr ret;
2354     xmlNodePtr child = NULL;
2355     const xmlChar *oldcontainer;
2356     char buf[100];
2357     xmlAttrPtr attr;
2358 
2359     /* 3.3.3 Constraints on XML Representations of Element Declarations */
2360 
2361 
2362     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2363         return (NULL);
2364     oldcontainer = ctxt->container;
2365     name = xmlSchemaGetProp(ctxt, node, "name");
2366     if (name == NULL) {
2367 
2368         ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2369     /* 3.3.3 : 2.1
2370      * One of ref or name must be present, but not both
2371      */
2372         if (ref == NULL) {
2373             xmlSchemaPErr(ctxt, node,
2374                            XML_SCHEMAP_ELEM_NONAME_NOREF,
2375                            "Element has no name nor ref\n", NULL, NULL);
2376             return (NULL);
2377         }
2378         snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2379         name = (const xmlChar *) buf;
2380     ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2381     } else {
2382     const xmlChar *ns = NULL;
2383 
2384     /* Evaluate the target namespace */
2385     if (schema->targetNamespace != NULL) {
2386         if (toplevel) {
2387         ns = schema->targetNamespace;
2388         } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2389         if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2390                  BAD_CAST "qualified")) {
2391             ns = schema->targetNamespace;
2392         }
2393         } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2394         ns = schema->targetNamespace;
2395         }
2396     }
2397     /*local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2398     ret = xmlSchemaAddElement(ctxt, schema, name, ns);
2399     /* 3.3.3 : 2.1
2400      * One of ref or name must be present, but not both
2401      */
2402     if ((!toplevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
2403         xmlSchemaPErr(ctxt, node,
2404                           XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2405                           "Element declaration has both, \"name\" and "
2406               "\"ref\"\n", NULL, NULL);
2407     }
2408     }
2409     if (ret != NULL)
2410     ret->node = node;
2411     if (ret == NULL) {
2412         return (NULL);
2413     }
2414     ret->type = XML_SCHEMA_TYPE_ELEMENT;
2415     ret->ref = ref;
2416     ret->refNs = refNs;
2417     if (ref != NULL)
2418         ret->flags |= XML_SCHEMAS_ELEM_REF;
2419 
2420     /* 3.3.3 : 2.2 */
2421     if ((!toplevel) && (ref != NULL)) {
2422     attr = node->properties;
2423     while (attr != NULL) {
2424         if ((attr->ns == NULL) &&
2425         (!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
2426         (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
2427         (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
2428         (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
2429 
2430         xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2431                        "Element declaration %s: only minOccurs, maxOccurs "
2432                "and id are allowed in addition to ref\n",
2433                ret->name, NULL);
2434         }
2435         attr = attr->next;
2436     }
2437     }
2438 
2439     if (toplevel)
2440         ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
2441     if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
2442         ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2443     if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
2444         ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2445     ctxt->container = name;
2446 
2447     ret->id = xmlSchemaGetProp(ctxt, node, "id");
2448     ret->namedType =
2449         xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
2450     ret->substGroup =
2451         xmlGetQNameProp(ctxt, node, "substitutionGroup",
2452                         &(ret->substGroupNs));
2453     if ((ret->substGroup != NULL) && (!toplevel)) {
2454     /* 3.3.6 : 3 */
2455     /*
2456      *  This seems to be redundant, since the schema for schemas
2457      * already prohibits the use of the "substitutionGroup" attribute
2458      * in local element declarations.
2459      */
2460         xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2461                   "Element declaration %s: substitutionGroup is allowed "
2462               "on top-level declarations only\n", ret->name, NULL);
2463 
2464     }
2465     fixed = xmlSchemaGetProp(ctxt, node, "fixed");
2466     ret->minOccurs = xmlGetMinOccurs(ctxt, node);
2467     ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2468 
2469     ret->value = xmlSchemaGetProp(ctxt, node, "default");
2470     if ((ret->value != NULL) && (fixed != NULL)) {
2471     /* 3.3.3 : 1
2472      * default and fixed must not both be present.
2473      */
2474         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
2475                        "Element %s has both default and fixed\n",
2476                ret->name, NULL);
2477     } else if (fixed != NULL) {
2478         ret->flags |= XML_SCHEMAS_ELEM_FIXED;
2479         ret->value = fixed;
2480     }
2481 
2482     child = node->children;
2483     if (IS_SCHEMA(child, "annotation")) {
2484         ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2485         child = child->next;
2486     }
2487     if (ref != NULL) {
2488     /* 3.3.3 (2.2) */
2489     while (child != NULL) {
2490         if ((IS_SCHEMA(child, "complexType")) ||
2491         (IS_SCHEMA(child, "simpleType")) ||
2492         (IS_SCHEMA(child, "unique")) ||
2493             (IS_SCHEMA(child, "key")) ||
2494         (IS_SCHEMA(child, "keyref"))) {
2495 
2496         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_REF_AND_CONTENT,
2497                        "Element declaration %s: only annotation is "
2498                    "allowed as content in addition to ref\n",
2499                    ret->name, NULL);
2500         } else {
2501         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2502                    "element %s has unexpected content\n", name, NULL);
2503         }
2504         child = child->next;
2505     }
2506     } else {
2507     if (IS_SCHEMA(child, "complexType")) {
2508         /* 3.3.3 : 3
2509          * type and either <simpleType> or <complexType> are mutually
2510          * exclusive
2511          */
2512         if (ret->namedType != NULL) {
2513         xmlSchemaPErr2(ctxt, node, child,
2514                    XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
2515                        "Element declaration %s has both \"type\" "
2516                    "and a local complex type\n",
2517                    ret->name, NULL);
2518         } else
2519         ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
2520         child = child->next;
2521     } else if (IS_SCHEMA(child, "simpleType")) {
2522         /* 3.3.3 : 3
2523          * type and either <simpleType> or <complexType> are
2524          * mutually exclusive
2525          */
2526         if (ret->namedType != NULL) {
2527         xmlSchemaPErr2(ctxt, node, child,
2528                    XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
2529                        "Element declaration %s has both \"type\" "
2530                    "and a local simple type\n",
2531                    ret->name, NULL);
2532         } else
2533         ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
2534         child = child->next;
2535     }
2536 
2537     while ((IS_SCHEMA(child, "unique")) ||
2538            (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2539         TODO child = child->next;
2540     }
2541     if (child != NULL) {
2542         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2543                    "element %s has unexpected content\n", name, NULL);
2544     }
2545     }
2546 
2547     ctxt->container = oldcontainer;
2548     return (ret);
2549 }
2550 
2551 /**
2552  * xmlSchemaParseUnion:
2553  * @param ctxt a schema validation context
2554  * @param schema the schema being built
2555  * @param node a subtree containing XML Schema informations
2556  *
2557  * parse a XML schema Union definition
2558  * *WARNING* this interface is highly subject to change
2559  *
2560  * Returns -1 in case of error, 0 if the declaration is improper and
2561  *         1 in case of success.
2562  */
2563 static xmlSchemaTypePtr
xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)2564 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2565                     xmlNodePtr node)
2566 {
2567     xmlSchemaTypePtr type, subtype, last = NULL;
2568     xmlNodePtr child = NULL;
2569     xmlChar name[30];
2570 
2571     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2572         return (NULL);
2573 
2574 
2575     snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
2576     type = xmlSchemaAddType(ctxt, schema, name, NULL);
2577     if (type == NULL)
2578         return (NULL);
2579     type->node = node;
2580     type->type = XML_SCHEMA_TYPE_UNION;
2581     type->id = xmlSchemaGetProp(ctxt, node, "id");
2582     type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
2583 
2584     child = node->children;
2585     if (IS_SCHEMA(child, "annotation")) {
2586         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2587         child = child->next;
2588     }
2589     while (IS_SCHEMA(child, "simpleType")) {
2590         subtype = (xmlSchemaTypePtr)
2591             xmlSchemaParseSimpleType(ctxt, schema, child);
2592         if (subtype != NULL) {
2593             if (last == NULL) {
2594                 type->subtypes = subtype;
2595                 last = subtype;
2596             } else {
2597                 last->next = subtype;
2598                 last = subtype;
2599             }
2600             last->next = NULL;
2601         }
2602         child = child->next;
2603     }
2604     if (child != NULL) {
2605         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2606                        "Union %s has unexpected content\n", type->name,
2607                        NULL);
2608     }
2609     return (type);
2610 }
2611 
2612 /**
2613  * xmlSchemaParseList:
2614  * @param ctxt a schema validation context
2615  * @param schema the schema being built
2616  * @param node a subtree containing XML Schema informations
2617  *
2618  * parse a XML schema List definition
2619  * *WARNING* this interface is highly subject to change
2620  *
2621  * Returns -1 in case of error, 0 if the declaration is improper and
2622  *         1 in case of success.
2623  */
2624 static xmlSchemaTypePtr
xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)2625 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2626                    xmlNodePtr node)
2627 {
2628     xmlSchemaTypePtr type, subtype;
2629     xmlNodePtr child = NULL;
2630     xmlChar name[30];
2631 
2632     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2633         return (NULL);
2634 
2635     snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
2636     type = xmlSchemaAddType(ctxt, schema, name, NULL);
2637     if (type == NULL)
2638         return (NULL);
2639     type->node = node;
2640     type->type = XML_SCHEMA_TYPE_LIST;
2641     type->id = xmlSchemaGetProp(ctxt, node, "id");
2642     type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
2643 
2644     child = node->children;
2645     if (IS_SCHEMA(child, "annotation")) {
2646         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2647         child = child->next;
2648     }
2649 
2650     subtype = NULL;
2651     if (IS_SCHEMA(child, "simpleType")) {
2652         subtype = (xmlSchemaTypePtr)
2653             xmlSchemaParseSimpleType(ctxt, schema, child);
2654         child = child->next;
2655         type->subtypes = subtype;
2656     }
2657     if (child != NULL) {
2658         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2659                        "List %s has unexpected content\n", type->name,
2660                        NULL);
2661     }
2662     return (type);
2663 }
2664 
2665 /**
2666  * xmlSchemaParseSimpleType:
2667  * @param ctxt a schema validation context
2668  * @param schema the schema being built
2669  * @param node a subtree containing XML Schema informations
2670  *
2671  * parse a XML schema Simple Type definition
2672  * *WARNING* this interface is highly subject to change
2673  *
2674  * Returns -1 in case of error, 0 if the declaration is improper and
2675  *         1 in case of success.
2676  */
2677 static xmlSchemaTypePtr
xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)2678 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2679                          xmlNodePtr node)
2680 {
2681     xmlSchemaTypePtr type, subtype;
2682     xmlNodePtr child = NULL;
2683     const xmlChar *name;
2684 
2685     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2686         return (NULL);
2687 
2688 
2689     name = xmlSchemaGetProp(ctxt, node, "name");
2690     if (name == NULL) {
2691         char buf[100];
2692 
2693         snprintf(buf, 99, "simpleType %d", ctxt->counter++ + 1);
2694     type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
2695     } else {
2696         /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2697     type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
2698     }
2699     if (type == NULL)
2700         return (NULL);
2701     type->node = node;
2702     type->type = XML_SCHEMA_TYPE_SIMPLE;
2703     type->id = xmlSchemaGetProp(ctxt, node, "id");
2704 
2705     child = node->children;
2706     if (IS_SCHEMA(child, "annotation")) {
2707         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2708         child = child->next;
2709     }
2710     subtype = NULL;
2711     if (IS_SCHEMA(child, "restriction")) {
2712         subtype = (xmlSchemaTypePtr)
2713             xmlSchemaParseRestriction(ctxt, schema, child, 1);
2714         child = child->next;
2715     } else if (IS_SCHEMA(child, "list")) {
2716         subtype = (xmlSchemaTypePtr)
2717             xmlSchemaParseList(ctxt, schema, child);
2718         child = child->next;
2719     } else if (IS_SCHEMA(child, "union")) {
2720         subtype = (xmlSchemaTypePtr)
2721             xmlSchemaParseUnion(ctxt, schema, child);
2722         child = child->next;
2723     }
2724     type->subtypes = subtype;
2725     if (subtype == NULL) {
2726     xmlSchemaPErr2(ctxt, node, child,
2727                        XML_SCHEMAP_MISSING_SIMPLETYPE_CHILD,
2728                        "SimpleType %s does not define a variety\n",
2729                        type->name, NULL);
2730     }
2731     if (child != NULL) {
2732         xmlSchemaPErr2(ctxt, node, child,
2733                        XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2734                        "SimpleType %s has unexpected content\n",
2735                        type->name, NULL);
2736     }
2737 
2738     return (type);
2739 }
2740 
2741 
2742 /**
2743  * xmlSchemaParseGroup:
2744  * @param ctxt a schema validation context
2745  * @param schema the schema being built
2746  * @param node a subtree containing XML Schema informations
2747  *
2748  * parse a XML schema Group definition
2749  * *WARNING* this interface is highly subject to change
2750  *
2751  * Returns -1 in case of error, 0 if the declaration is improper and
2752  *         1 in case of success.
2753  */
2754 static xmlSchemaTypePtr
xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)2755 xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2756                     xmlNodePtr node)
2757 {
2758     xmlSchemaTypePtr type, subtype;
2759     xmlNodePtr child = NULL;
2760     const xmlChar *name;
2761     const xmlChar *ref = NULL, *refNs = NULL;
2762     char buf[100];
2763 
2764     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2765         return (NULL);
2766 
2767 
2768     name = xmlSchemaGetProp(ctxt, node, "name");
2769     if (name == NULL) {
2770 
2771         ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2772         if (ref == NULL) {
2773             xmlSchemaPErr2(ctxt, node, child,
2774                            XML_SCHEMAP_GROUP_NONAME_NOREF,
2775                            "Group has no name nor ref\n", NULL, NULL);
2776             return (NULL);
2777         }
2778     if (refNs == NULL)
2779         refNs = schema->targetNamespace;
2780         snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
2781         name = (const xmlChar *) buf;
2782     }
2783     type = xmlSchemaAddGroup(ctxt, schema, name);
2784     if (type == NULL)
2785         return (NULL);
2786 
2787     type->node = node;
2788     type->type = XML_SCHEMA_TYPE_GROUP;
2789     type->id = xmlSchemaGetProp(ctxt, node, "id");
2790     type->ref = ref;
2791     type->refNs = refNs;
2792     type->minOccurs = xmlGetMinOccurs(ctxt, node);
2793     type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2794 
2795     child = node->children;
2796     if (IS_SCHEMA(child, "annotation")) {
2797         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2798         child = child->next;
2799     }
2800     subtype = NULL;
2801     if (IS_SCHEMA(child, "all")) {
2802         subtype = (xmlSchemaTypePtr)
2803             xmlSchemaParseAll(ctxt, schema, child);
2804         child = child->next;
2805     } else if (IS_SCHEMA(child, "choice")) {
2806         subtype = xmlSchemaParseChoice(ctxt, schema, child);
2807         child = child->next;
2808     } else if (IS_SCHEMA(child, "sequence")) {
2809         subtype = (xmlSchemaTypePtr)
2810             xmlSchemaParseSequence(ctxt, schema, child);
2811         child = child->next;
2812     }
2813     if (subtype != NULL)
2814         type->subtypes = subtype;
2815     if (child != NULL) {
2816         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2817                        "Group %s has unexpected content\n", type->name,
2818                        NULL);
2819     }
2820 
2821     return (type);
2822 }
2823 
2824 /**
2825  * xmlSchemaParseAll:
2826  * @param ctxt a schema validation context
2827  * @param schema the schema being built
2828  * @param node a subtree containing XML Schema informations
2829  *
2830  * parse a XML schema All definition
2831  * *WARNING* this interface is highly subject to change
2832  *
2833  * Returns -1 in case of error, 0 if the declaration is improper and
2834  *         1 in case of success.
2835  */
2836 static xmlSchemaTypePtr
xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)2837 xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2838                   xmlNodePtr node)
2839 {
2840     xmlSchemaTypePtr type, subtype, last = NULL;
2841     xmlNodePtr child = NULL;
2842     xmlChar name[30];
2843 
2844     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2845         return (NULL);
2846 
2847 
2848     snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
2849     type = xmlSchemaAddType(ctxt, schema, name, NULL);
2850     if (type == NULL)
2851         return (NULL);
2852     type->node = node;
2853     type->type = XML_SCHEMA_TYPE_ALL;
2854     type->id = xmlSchemaGetProp(ctxt, node, "id");
2855     type->minOccurs = xmlGetMinOccurs(ctxt, node);
2856     if (type->minOccurs > 1)
2857         xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
2858         "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
2859     type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2860     if (type->maxOccurs > 1)
2861         xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
2862         "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
2863 
2864     child = node->children;
2865     if (IS_SCHEMA(child, "annotation")) {
2866         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2867         child = child->next;
2868     }
2869     while (IS_SCHEMA(child, "element")) {
2870         subtype = (xmlSchemaTypePtr)
2871             xmlSchemaParseElement(ctxt, schema, child, 0);
2872         if (subtype != NULL) {
2873         if (subtype->minOccurs > 1)
2874                 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
2875                  "invalid value for minOccurs (must be 0 or 1)\n",
2876              NULL, NULL);
2877         if (subtype->maxOccurs > 1)
2878             xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
2879                  "invalid value for maxOccurs (must be 0 or 1)\n",
2880              NULL, NULL);
2881             if (last == NULL) {
2882                 type->subtypes = subtype;
2883                 last = subtype;
2884             } else {
2885                 last->next = subtype;
2886                 last = subtype;
2887             }
2888             last->next = NULL;
2889         }
2890         child = child->next;
2891     }
2892     if (child != NULL) {
2893         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2894                        "All %s has unexpected content\n", type->name,
2895                        NULL);
2896     }
2897 
2898     return (type);
2899 }
2900 
2901 /**
2902  * xmlSchemaImportSchema
2903  *
2904  * @param ctxt a schema validation context
2905  * @param schemaLocation an URI defining where to find the imported schema
2906  *
2907  * import a XML schema
2908  * *WARNING* this interface is highly subject to change
2909  *
2910  * Returns -1 in case of error and 1 in case of success.
2911  */
2912 static xmlSchemaImportPtr
xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,const xmlChar * schemaLocation)2913 xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
2914                       const xmlChar *schemaLocation)
2915 {
2916     xmlSchemaImportPtr import;
2917     xmlSchemaParserCtxtPtr newctxt;
2918 
2919     newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
2920     if (newctxt == NULL) {
2921         xmlSchemaPErrMemory(ctxt, "allocating schama parser context",
2922                             NULL);
2923         return (NULL);
2924     }
2925     memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
2926     /* Keep the same dictionnary for parsing, really */
2927     xmlDictReference(ctxt->dict);
2928     newctxt->dict = ctxt->dict;
2929     newctxt->includes = 0;
2930     newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
2931 
2932     xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
2933                          ctxt->userData);
2934 
2935     import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
2936     if (import == NULL) {
2937         xmlSchemaPErrMemory(NULL, "allocating imported schema",
2938                             NULL);
2939     xmlSchemaFreeParserCtxt(newctxt);
2940         return (NULL);
2941     }
2942 
2943     memset(import, 0, sizeof(xmlSchemaImport));
2944     import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
2945     import->schema = xmlSchemaParse(newctxt);
2946 
2947     if (import->schema == NULL) {
2948 
2949         xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
2950                   "failed to import schema at location %s\n",
2951               schemaLocation, NULL);
2952 
2953     xmlSchemaFreeParserCtxt(newctxt);
2954     if (import->schemaLocation != NULL)
2955         xmlFree((xmlChar *)import->schemaLocation);
2956     xmlFree(import);
2957     return NULL;
2958     }
2959 
2960     xmlSchemaFreeParserCtxt(newctxt);
2961     return import;
2962 }
2963 
2964 
2965 /**
2966  * xmlSchemaParseImport:
2967  * @param ctxt a schema validation context
2968  * @param schema the schema being built
2969  * @param node a subtree containing XML Schema informations
2970  *
2971  * parse a XML schema Import definition
2972  * *WARNING* this interface is highly subject to change
2973  *
2974  * Returns -1 in case of error, 0 if the declaration is improper and
2975  *         1 in case of success.
2976  */
2977 static int
xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)2978 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2979                      xmlNodePtr node)
2980 {
2981     xmlNodePtr child = NULL;
2982     xmlSchemaImportPtr import = NULL;
2983     const xmlChar *namespace;
2984     const xmlChar *schemaLocation;
2985     const xmlChar *previous;
2986     xmlURIPtr check;
2987 
2988 
2989     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2990         return (-1);
2991 
2992     namespace = xmlSchemaGetProp(ctxt, node, "namespace");
2993     if (namespace != NULL) {
2994         check = xmlParseURI((const char *) namespace);
2995         if (check == NULL) {
2996             xmlSchemaPErr2(ctxt, node, child,
2997                            XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2998                            "Import namespace attribute is not an URI: %s\n",
2999                            namespace, NULL);
3000             return (-1);
3001         } else {
3002             xmlFreeURI(check);
3003         }
3004     }
3005     schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
3006     if (schemaLocation != NULL) {
3007         xmlChar *base = NULL;
3008         xmlChar *URI = NULL;
3009         check = xmlParseURI((const char *) schemaLocation);
3010         if (check == NULL) {
3011             xmlSchemaPErr2(ctxt, node, child,
3012                            XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
3013                            "Import schemaLocation attribute is not an URI: %s\n",
3014                            schemaLocation, NULL);
3015             return (-1);
3016         } else {
3017             xmlFreeURI(check);
3018         }
3019     base = xmlNodeGetBase(node->doc, node);
3020     if (base == NULL) {
3021         URI = xmlBuildURI(schemaLocation, node->doc->URL);
3022     } else {
3023         URI = xmlBuildURI(schemaLocation, base);
3024         xmlFree(base);
3025     }
3026     if (URI != NULL) {
3027         schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3028         xmlFree(URI);
3029     }
3030     }
3031     if (schema->schemasImports == NULL) {
3032         schema->schemasImports = xmlHashCreate(10);
3033         if (schema->schemasImports == NULL) {
3034             xmlSchemaPErr2(ctxt, node, child,
3035                            XML_SCHEMAP_FAILED_BUILD_IMPORT,
3036                            "Internal: failed to build import table\n",
3037                            NULL, NULL);
3038             return (-1);
3039         }
3040     }
3041     if (namespace == NULL) {
3042         import = xmlHashLookup(schema->schemasImports,
3043                                    XML_SCHEMAS_DEFAULT_NAMESPACE);
3044     if (import != NULL)
3045             previous = import->schemaLocation;
3046     else
3047         previous = NULL;
3048 
3049         if (schemaLocation != NULL) {
3050             if (previous != NULL) {
3051                 if (!xmlStrEqual(schemaLocation, previous)) {
3052                     xmlSchemaPErr2(ctxt, node, child,
3053                                    XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
3054                                    "Redefining import for default namespace "
3055                    "with a different URI: %s\n",
3056                                    schemaLocation, NULL);
3057                 }
3058             } else {
3059             import = xmlSchemaImportSchema(ctxt, schemaLocation);
3060         if (import == NULL) {
3061             return (-1);
3062         }
3063                 xmlHashAddEntry(schema->schemasImports,
3064                                 XML_SCHEMAS_DEFAULT_NAMESPACE,
3065                                 import);
3066             }
3067         }
3068     } else {
3069         import = xmlHashLookup(schema->schemasImports, namespace);
3070     if (import != NULL)
3071         previous = import->schemaLocation;
3072     else
3073         previous = NULL;
3074 
3075         if (schemaLocation != NULL) {
3076             if (previous != NULL) {
3077                 if (!xmlStrEqual(schemaLocation, previous)) {
3078                     xmlSchemaPErr2(ctxt, node, child,
3079                                    XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
3080                                    "Redefining import for namespace %s with "
3081                    "a different URI: %s\n",
3082                                    namespace, schemaLocation);
3083                 }
3084             } else {
3085             import = xmlSchemaImportSchema(ctxt, schemaLocation);
3086         if (import == NULL) {
3087             return (-1);
3088         }
3089                 xmlHashAddEntry(schema->schemasImports,
3090                                 namespace, import);
3091             }
3092         }
3093     }
3094 
3095     child = node->children;
3096     while (IS_SCHEMA(child, "annotation")) {
3097         /*
3098          * the annotations here are simply discarded ...
3099          */
3100         child = child->next;
3101     }
3102     if (child != NULL) {
3103         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
3104                        "Import has unexpected content\n", NULL, NULL);
3105         return (-1);
3106     }
3107     return (1);
3108 }
3109 
3110 /**
3111  * xmlSchemaCleanupDoc:
3112  * @param ctxt a schema validation context
3113  * @param node the root of the document.
3114  *
3115  * removes unwanted nodes in a schemas document tree
3116  */
3117 static void
xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr root)3118 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
3119 {
3120     xmlNodePtr delete, cur;
3121 
3122     if ((ctxt == NULL) || (root == NULL)) return;
3123 
3124     /*
3125      * Remove all the blank text nodes
3126      */
3127     delete = NULL;
3128     cur = root;
3129     while (cur != NULL) {
3130         if (delete != NULL) {
3131             xmlUnlinkNode(delete);
3132             xmlFreeNode(delete);
3133             delete = NULL;
3134         }
3135         if (cur->type == XML_TEXT_NODE) {
3136             if (IS_BLANK_NODE(cur)) {
3137                 if (xmlNodeGetSpacePreserve(cur) != 1) {
3138                     delete = cur;
3139                 }
3140             }
3141         } else if ((cur->type != XML_ELEMENT_NODE) &&
3142                    (cur->type != XML_CDATA_SECTION_NODE)) {
3143             delete = cur;
3144             goto skip_children;
3145         }
3146 
3147         /*
3148          * Skip to next node
3149          */
3150         if (cur->children != NULL) {
3151             if ((cur->children->type != XML_ENTITY_DECL) &&
3152                 (cur->children->type != XML_ENTITY_REF_NODE) &&
3153                 (cur->children->type != XML_ENTITY_NODE)) {
3154                 cur = cur->children;
3155                 continue;
3156             }
3157         }
3158       skip_children:
3159         if (cur->next != NULL) {
3160             cur = cur->next;
3161             continue;
3162         }
3163 
3164         do {
3165             cur = cur->parent;
3166             if (cur == NULL)
3167                 break;
3168             if (cur == root) {
3169                 cur = NULL;
3170                 break;
3171             }
3172             if (cur->next != NULL) {
3173                 cur = cur->next;
3174                 break;
3175             }
3176         } while (cur != NULL);
3177     }
3178     if (delete != NULL) {
3179         xmlUnlinkNode(delete);
3180         xmlFreeNode(delete);
3181         delete = NULL;
3182     }
3183 }
3184 
3185 /**
3186  * xmlSchemaParseSchemaTopLevel:
3187  * @param ctxt a schema validation context
3188  * @param schema the schemas
3189  * @param nodes the list of top level nodes
3190  *
3191  * Returns the internal XML Schema structure built from the resource or
3192  *         NULL in case of error
3193  */
3194 static void
xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr nodes)3195 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
3196                              xmlSchemaPtr schema, xmlNodePtr nodes)
3197 {
3198     xmlNodePtr child;
3199     xmlSchemaAnnotPtr annot;
3200 
3201     if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
3202         return;
3203 
3204     child = nodes;
3205     while ((IS_SCHEMA(child, "include")) ||
3206        (IS_SCHEMA(child, "import")) ||
3207        (IS_SCHEMA(child, "redefine")) ||
3208        (IS_SCHEMA(child, "annotation"))) {
3209     if (IS_SCHEMA(child, "annotation")) {
3210         annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3211         if (schema->annot == NULL)
3212         schema->annot = annot;
3213         else
3214         xmlSchemaFreeAnnot(annot);
3215     } else if (IS_SCHEMA(child, "import")) {
3216         xmlSchemaParseImport(ctxt, schema, child);
3217     } else if (IS_SCHEMA(child, "include")) {
3218         ctxt->includes++;
3219         xmlSchemaParseInclude(ctxt, schema, child);
3220         ctxt->includes--;
3221     } else if (IS_SCHEMA(child, "redefine")) {
3222         TODO
3223     }
3224     child = child->next;
3225     }
3226     while (child != NULL) {
3227     if (IS_SCHEMA(child, "complexType")) {
3228         xmlSchemaParseComplexType(ctxt, schema, child);
3229         child = child->next;
3230     } else if (IS_SCHEMA(child, "simpleType")) {
3231         xmlSchemaParseSimpleType(ctxt, schema, child);
3232         child = child->next;
3233     } else if (IS_SCHEMA(child, "element")) {
3234         xmlSchemaParseElement(ctxt, schema, child, 1);
3235         child = child->next;
3236     } else if (IS_SCHEMA(child, "attribute")) {
3237         xmlSchemaParseAttribute(ctxt, schema, child, 1);
3238         child = child->next;
3239     } else if (IS_SCHEMA(child, "attributeGroup")) {
3240         xmlSchemaParseAttributeGroup(ctxt, schema, child);
3241         child = child->next;
3242     } else if (IS_SCHEMA(child, "group")) {
3243         xmlSchemaParseGroup(ctxt, schema, child);
3244         child = child->next;
3245     } else if (IS_SCHEMA(child, "notation")) {
3246         xmlSchemaParseNotation(ctxt, schema, child);
3247         child = child->next;
3248     } else {
3249         xmlSchemaPErr2(ctxt, NULL, child,
3250                XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
3251                "Schemas: unexpected element %s here \n",
3252                child->name, NULL);
3253         child = child->next;
3254     }
3255     while (IS_SCHEMA(child, "annotation")) {
3256         annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3257         if (schema->annot == NULL)
3258         schema->annot = annot;
3259         else
3260         xmlSchemaFreeAnnot(annot);
3261         child = child->next;
3262     }
3263     }
3264 }
3265 
3266 /**
3267  * xmlSchemaParseInclude:
3268  * @param ctxt a schema validation context
3269  * @param schema the schema being built
3270  * @param node a subtree containing XML Schema informations
3271  *
3272  * parse a XML schema Include definition
3273  *
3274  * Returns -1 in case of error, 0 if the declaration is improper and
3275  *         1 in case of success.
3276  */
3277 static int
xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)3278 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3279                       xmlNodePtr node)
3280 {
3281     xmlNodePtr child = NULL;
3282     const xmlChar *schemaLocation;
3283     xmlURIPtr check;
3284     xmlDocPtr doc;
3285     xmlNodePtr root;
3286     xmlSchemaIncludePtr include;
3287 
3288 
3289     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3290         return (-1);
3291 
3292     /*
3293      * Preliminary step, extract the URI-Reference for the include and
3294      * make an URI from the base.
3295      */
3296     schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
3297     if (schemaLocation != NULL) {
3298         xmlChar *base = NULL;
3299         xmlChar *URI = NULL;
3300         check = xmlParseURI((const char *) schemaLocation);
3301         if (check == NULL) {
3302             xmlSchemaPErr2(ctxt, node, child,
3303                            XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
3304                "Include schemaLocation attribute is not an URI: %s\n",
3305                            schemaLocation, NULL);
3306             return (-1);
3307         } else {
3308             xmlFreeURI(check);
3309         }
3310     base = xmlNodeGetBase(node->doc, node);
3311     if (base == NULL) {
3312         URI = xmlBuildURI(schemaLocation, node->doc->URL);
3313     } else {
3314         URI = xmlBuildURI(schemaLocation, base);
3315         xmlFree(base);
3316     }
3317     if (URI != NULL) {
3318         schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3319         xmlFree(URI);
3320     }
3321     } else {
3322     xmlSchemaPErr2(ctxt, node, child,
3323                XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
3324            "Include schemaLocation attribute missing\n",
3325                NULL, NULL);
3326     return (-1);
3327     }
3328 
3329     child = node->children;
3330     while (IS_SCHEMA(child, "annotation")) {
3331         /*
3332          * the annotations here are simply discarded ...
3333          */
3334         child = child->next;
3335     }
3336     if (child != NULL) {
3337         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
3338                        "Include has unexpected content\n", NULL, NULL);
3339         return (-1);
3340     }
3341 
3342     /*
3343      * First step is to parse the input document into an DOM/Infoset
3344      */
3345     doc = xmlReadFile((const char *) schemaLocation, NULL,
3346                       SCHEMAS_PARSE_OPTIONS);
3347     if (doc == NULL) {
3348     xmlSchemaPErr(ctxt, NULL,
3349               XML_SCHEMAP_FAILED_LOAD,
3350               "xmlSchemaParse: could not load %s\n",
3351               ctxt->URL, NULL);
3352     return(-1);
3353     }
3354 
3355     /*
3356      * Then extract the root of the schema
3357      */
3358     root = xmlDocGetRootElement(doc);
3359     if (root == NULL) {
3360     xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3361               XML_SCHEMAP_NOROOT,
3362               "schemas %s has no root", schemaLocation, NULL);
3363     xmlFreeDoc(doc);
3364         return (-1);
3365     }
3366 
3367     /*
3368      * Remove all the blank text nodes
3369      */
3370     xmlSchemaCleanupDoc(ctxt, root);
3371 
3372     /*
3373      * Check the schemas top level element
3374      */
3375     if (!IS_SCHEMA(root, "schema")) {
3376     xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3377               XML_SCHEMAP_NOT_SCHEMA,
3378               "File %s is not a schemas", schemaLocation, NULL);
3379     xmlFreeDoc(doc);
3380         return (-1);
3381     }
3382 
3383     /*
3384      * register the include
3385      */
3386     include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
3387     if (include == NULL) {
3388         xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
3389     xmlFreeDoc(doc);
3390         return (-1);
3391     }
3392 
3393     memset(include, 0, sizeof(xmlSchemaInclude));
3394     include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
3395     include->doc = doc;
3396     include->next = schema->includes;
3397     schema->includes = include;
3398 
3399 
3400     /*
3401      * parse the declarations in the included file like if they
3402      * were in the original file.
3403      */
3404     xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
3405 
3406     return (1);
3407 }
3408 
3409 /**
3410  * xmlSchemaParseChoice:
3411  * @param ctxt a schema validation context
3412  * @param schema the schema being built
3413  * @param node a subtree containing XML Schema informations
3414  *
3415  * parse a XML schema Choice definition
3416  * *WARNING* this interface is highly subject to change
3417  *
3418  * Returns -1 in case of error, 0 if the declaration is improper and
3419  *         1 in case of success.
3420  */
3421 static xmlSchemaTypePtr
xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)3422 xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3423                      xmlNodePtr node)
3424 {
3425     xmlSchemaTypePtr type, subtype, last = NULL;
3426     xmlNodePtr child = NULL;
3427     xmlChar name[30];
3428 
3429     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3430         return (NULL);
3431 
3432 
3433     snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
3434     type = xmlSchemaAddType(ctxt, schema, name, NULL);
3435     if (type == NULL)
3436         return (NULL);
3437     type->node = node;
3438     type->type = XML_SCHEMA_TYPE_CHOICE;
3439     type->id = xmlSchemaGetProp(ctxt, node, "id");
3440     type->minOccurs = xmlGetMinOccurs(ctxt, node);
3441     type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3442 
3443     child = node->children;
3444     if (IS_SCHEMA(child, "annotation")) {
3445         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3446         child = child->next;
3447     }
3448     while ((IS_SCHEMA(child, "element")) ||
3449            (IS_SCHEMA(child, "group")) ||
3450            (IS_SCHEMA(child, "any")) ||
3451            (IS_SCHEMA(child, "choice")) ||
3452            (IS_SCHEMA(child, "sequence"))) {
3453         subtype = NULL;
3454         if (IS_SCHEMA(child, "element")) {
3455             subtype = (xmlSchemaTypePtr)
3456                 xmlSchemaParseElement(ctxt, schema, child, 0);
3457         } else if (IS_SCHEMA(child, "group")) {
3458             subtype = xmlSchemaParseGroup(ctxt, schema, child);
3459         } else if (IS_SCHEMA(child, "any")) {
3460             subtype = xmlSchemaParseAny(ctxt, schema, child);
3461         } else if (IS_SCHEMA(child, "sequence")) {
3462             subtype = xmlSchemaParseSequence(ctxt, schema, child);
3463         } else if (IS_SCHEMA(child, "choice")) {
3464             subtype = xmlSchemaParseChoice(ctxt, schema, child);
3465         }
3466         if (subtype != NULL) {
3467             if (last == NULL) {
3468                 type->subtypes = subtype;
3469                 last = subtype;
3470             } else {
3471                 last->next = subtype;
3472                 last = subtype;
3473             }
3474             last->next = NULL;
3475         }
3476         child = child->next;
3477     }
3478     if (child != NULL) {
3479         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
3480                        "Choice %s has unexpected content\n", type->name,
3481                        NULL);
3482     }
3483 
3484     return (type);
3485 }
3486 
3487 /**
3488  * xmlSchemaParseSequence:
3489  * @param ctxt a schema validation context
3490  * @param schema the schema being built
3491  * @param node a subtree containing XML Schema informations
3492  *
3493  * parse a XML schema Sequence definition
3494  * *WARNING* this interface is highly subject to change
3495  *
3496  * Returns -1 in case of error, 0 if the declaration is improper and
3497  *         1 in case of success.
3498  */
3499 static xmlSchemaTypePtr
xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)3500 xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3501                        xmlNodePtr node)
3502 {
3503     xmlSchemaTypePtr type, subtype, last = NULL;
3504     xmlNodePtr child = NULL;
3505     xmlChar name[30];
3506 
3507     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3508         return (NULL);
3509 
3510 
3511     snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
3512     type = xmlSchemaAddType(ctxt, schema, name, NULL);
3513     if (type == NULL)
3514         return (NULL);
3515     type->node = node;
3516     type->type = XML_SCHEMA_TYPE_SEQUENCE;
3517     type->id = xmlSchemaGetProp(ctxt, node, "id");
3518     type->minOccurs = xmlGetMinOccurs(ctxt, node);
3519     type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3520 
3521     child = node->children;
3522     if (IS_SCHEMA(child, "annotation")) {
3523         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3524         child = child->next;
3525     }
3526     while ((IS_SCHEMA(child, "element")) ||
3527            (IS_SCHEMA(child, "group")) ||
3528            (IS_SCHEMA(child, "any")) ||
3529            (IS_SCHEMA(child, "choice")) ||
3530            (IS_SCHEMA(child, "sequence"))) {
3531         subtype = NULL;
3532         if (IS_SCHEMA(child, "element")) {
3533             subtype = (xmlSchemaTypePtr)
3534                 xmlSchemaParseElement(ctxt, schema, child, 0);
3535         } else if (IS_SCHEMA(child, "group")) {
3536             subtype = xmlSchemaParseGroup(ctxt, schema, child);
3537         } else if (IS_SCHEMA(child, "any")) {
3538             subtype = xmlSchemaParseAny(ctxt, schema, child);
3539         } else if (IS_SCHEMA(child, "choice")) {
3540             subtype = xmlSchemaParseChoice(ctxt, schema, child);
3541         } else if (IS_SCHEMA(child, "sequence")) {
3542             subtype = xmlSchemaParseSequence(ctxt, schema, child);
3543         }
3544         if (subtype != NULL) {
3545             if (last == NULL) {
3546                 type->subtypes = subtype;
3547                 last = subtype;
3548             } else {
3549                 last->next = subtype;
3550                 last = subtype;
3551             }
3552             last->next = NULL;
3553         }
3554         child = child->next;
3555     }
3556     if (child != NULL) {
3557         xmlSchemaPErr2(ctxt, node, child,
3558                        XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
3559                        "Sequence %s has unexpected content\n", type->name,
3560                        NULL);
3561     }
3562 
3563     return (type);
3564 }
3565 
3566 /**
3567  * xmlSchemaParseRestriction:
3568  * @param ctxt a schema validation context
3569  * @param schema the schema being built
3570  * @param node a subtree containing XML Schema informations
3571  * @param simple is that part of a simple type.
3572  *
3573  * parse a XML schema Restriction definition
3574  * *WARNING* this interface is highly subject to change
3575  *
3576  * Returns the type definition or NULL in case of error
3577  */
3578 static xmlSchemaTypePtr
xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int simple)3579 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3580                           xmlNodePtr node, int simple)
3581 {
3582     xmlSchemaTypePtr type, subtype;
3583     xmlSchemaFacetPtr facet, lastfacet = NULL;
3584     xmlNodePtr child = NULL;
3585     xmlChar name[30];
3586     const xmlChar *oldcontainer;
3587 
3588     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3589         return (NULL);
3590 
3591     oldcontainer = ctxt->container;
3592 
3593     snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
3594     type = xmlSchemaAddType(ctxt, schema, name, NULL);
3595     if (type == NULL)
3596         return (NULL);
3597     type->node = node;
3598     type->type = XML_SCHEMA_TYPE_RESTRICTION;
3599     type->id = xmlSchemaGetProp(ctxt, node, "id");
3600     type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3601     if ((!simple) && (type->base == NULL)) {
3602         xmlSchemaPErr2(ctxt, node, child,
3603                        XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
3604                        "Restriction %s has no base\n", type->name, NULL);
3605     }
3606     ctxt->container = name;
3607 
3608     child = node->children;
3609     if (IS_SCHEMA(child, "annotation")) {
3610         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3611         child = child->next;
3612     }
3613     subtype = NULL;
3614 
3615     if (IS_SCHEMA(child, "all")) {
3616         subtype = (xmlSchemaTypePtr)
3617             xmlSchemaParseAll(ctxt, schema, child);
3618         child = child->next;
3619         type->subtypes = subtype;
3620     } else if (IS_SCHEMA(child, "choice")) {
3621         subtype = xmlSchemaParseChoice(ctxt, schema, child);
3622         child = child->next;
3623         type->subtypes = subtype;
3624     } else if (IS_SCHEMA(child, "sequence")) {
3625         subtype = (xmlSchemaTypePtr)
3626             xmlSchemaParseSequence(ctxt, schema, child);
3627         child = child->next;
3628         type->subtypes = subtype;
3629     } else if (IS_SCHEMA(child, "group")) {
3630         subtype = (xmlSchemaTypePtr)
3631             xmlSchemaParseGroup(ctxt, schema, child);
3632         child = child->next;
3633         type->subtypes = subtype;
3634     } else {
3635         if (IS_SCHEMA(child, "simpleType")) {
3636             subtype = (xmlSchemaTypePtr)
3637                 xmlSchemaParseSimpleType(ctxt, schema, child);
3638             child = child->next;
3639             type->baseType = subtype;
3640         }
3641         /*
3642          * Facets
3643          */
3644         while ((IS_SCHEMA(child, "minInclusive")) ||
3645                (IS_SCHEMA(child, "minExclusive")) ||
3646                (IS_SCHEMA(child, "maxInclusive")) ||
3647                (IS_SCHEMA(child, "maxExclusive")) ||
3648                (IS_SCHEMA(child, "totalDigits")) ||
3649                (IS_SCHEMA(child, "fractionDigits")) ||
3650                (IS_SCHEMA(child, "pattern")) ||
3651                (IS_SCHEMA(child, "enumeration")) ||
3652                (IS_SCHEMA(child, "whiteSpace")) ||
3653                (IS_SCHEMA(child, "length")) ||
3654                (IS_SCHEMA(child, "maxLength")) ||
3655                (IS_SCHEMA(child, "minLength"))) {
3656             facet = xmlSchemaParseFacet(ctxt, schema, child);
3657             if (facet != NULL) {
3658                 if (lastfacet == NULL) {
3659                     type->facets = facet;
3660                     lastfacet = facet;
3661                 } else {
3662                     lastfacet->next = facet;
3663                     lastfacet = facet;
3664                 }
3665                 lastfacet->next = NULL;
3666             }
3667             child = child->next;
3668         }
3669     }
3670     child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3671     if (child != NULL) {
3672         xmlSchemaPErr2(ctxt, node, child,
3673                        XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
3674                        "Restriction %s has unexpected content\n",
3675                        type->name, NULL);
3676     }
3677     ctxt->container = oldcontainer;
3678     return (type);
3679 }
3680 
3681 /**
3682  * xmlSchemaParseExtension:
3683  * @param ctxt a schema validation context
3684  * @param schema the schema being built
3685  * @param node a subtree containing XML Schema informations
3686  *
3687  * parse a XML schema Extension definition
3688  * *WARNING* this interface is highly subject to change
3689  *
3690  * Returns the type definition or NULL in case of error
3691  */
3692 static xmlSchemaTypePtr
xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)3693 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3694                         xmlNodePtr node)
3695 {
3696     xmlSchemaTypePtr type, subtype;
3697     xmlNodePtr child = NULL;
3698     xmlChar name[30];
3699     const xmlChar *oldcontainer;
3700 
3701     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3702         return (NULL);
3703 
3704     oldcontainer = ctxt->container;
3705 
3706     snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
3707     type = xmlSchemaAddType(ctxt, schema, name, NULL);
3708     if (type == NULL)
3709         return (NULL);
3710     type->node = node;
3711     type->type = XML_SCHEMA_TYPE_EXTENSION;
3712     type->id = xmlSchemaGetProp(ctxt, node, "id");
3713     ctxt->container = name;
3714 
3715     type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3716     if (type->base == NULL) {
3717         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
3718                        "Extension %s has no base\n", type->name, NULL);
3719     }
3720     child = node->children;
3721     if (IS_SCHEMA(child, "annotation")) {
3722         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3723         child = child->next;
3724     }
3725     subtype = NULL;
3726 
3727     if (IS_SCHEMA(child, "all")) {
3728         subtype = xmlSchemaParseAll(ctxt, schema, child);
3729         child = child->next;
3730     } else if (IS_SCHEMA(child, "choice")) {
3731         subtype = xmlSchemaParseChoice(ctxt, schema, child);
3732         child = child->next;
3733     } else if (IS_SCHEMA(child, "sequence")) {
3734         subtype = xmlSchemaParseSequence(ctxt, schema, child);
3735         child = child->next;
3736     } else if (IS_SCHEMA(child, "group")) {
3737         subtype = xmlSchemaParseGroup(ctxt, schema, child);
3738         child = child->next;
3739     }
3740     if (subtype != NULL)
3741         type->subtypes = subtype;
3742     child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3743     if (child != NULL) {
3744         xmlSchemaPErr2(ctxt, node, child,
3745                        XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
3746                        "Extension %s has unexpected content\n", type->name,
3747                        NULL);
3748     }
3749     ctxt->container = oldcontainer;
3750     return (type);
3751 }
3752 
3753 /**
3754  * xmlSchemaParseSimpleContent:
3755  * @param ctxt a schema validation context
3756  * @param schema the schema being built
3757  * @param node a subtree containing XML Schema informations
3758  *
3759  * parse a XML schema SimpleContent definition
3760  * *WARNING* this interface is highly subject to change
3761  *
3762  * Returns the type definition or NULL in case of error
3763  */
3764 static xmlSchemaTypePtr
xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)3765 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
3766                             xmlSchemaPtr schema, xmlNodePtr node)
3767 {
3768     xmlSchemaTypePtr type, subtype;
3769     xmlNodePtr child = NULL;
3770     xmlChar name[30];
3771 
3772     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3773         return (NULL);
3774 
3775 
3776     snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
3777     type = xmlSchemaAddType(ctxt, schema, name, NULL);
3778     if (type == NULL)
3779         return (NULL);
3780     type->node = node;
3781     type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
3782     type->id = xmlSchemaGetProp(ctxt, node, "id");
3783 
3784     child = node->children;
3785     if (IS_SCHEMA(child, "annotation")) {
3786         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3787         child = child->next;
3788     }
3789     subtype = NULL;
3790     if (IS_SCHEMA(child, "restriction")) {
3791         subtype = (xmlSchemaTypePtr)
3792             xmlSchemaParseRestriction(ctxt, schema, child, 0);
3793         child = child->next;
3794     } else if (IS_SCHEMA(child, "extension")) {
3795         subtype = (xmlSchemaTypePtr)
3796             xmlSchemaParseExtension(ctxt, schema, child);
3797         child = child->next;
3798     }
3799     type->subtypes = subtype;
3800     if (child != NULL) {
3801         xmlSchemaPErr2(ctxt, node, child,
3802                        XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
3803                        "SimpleContent %s has unexpected content\n",
3804                        type->name, NULL);
3805     }
3806     return (type);
3807 }
3808 
3809 /**
3810  * xmlSchemaParseComplexContent:
3811  * @param ctxt a schema validation context
3812  * @param schema the schema being built
3813  * @param node a subtree containing XML Schema informations
3814  *
3815  * parse a XML schema ComplexContent definition
3816  * *WARNING* this interface is highly subject to change
3817  *
3818  * Returns the type definition or NULL in case of error
3819  */
3820 static xmlSchemaTypePtr
xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)3821 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
3822                              xmlSchemaPtr schema, xmlNodePtr node)
3823 {
3824     xmlSchemaTypePtr type, subtype;
3825     xmlNodePtr child = NULL;
3826     xmlChar name[30];
3827 
3828     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3829         return (NULL);
3830 
3831 
3832     snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
3833     type = xmlSchemaAddType(ctxt, schema, name, NULL);
3834     if (type == NULL)
3835         return (NULL);
3836     type->node = node;
3837     type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
3838     type->id = xmlSchemaGetProp(ctxt, node, "id");
3839 
3840     child = node->children;
3841     if (IS_SCHEMA(child, "annotation")) {
3842         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3843         child = child->next;
3844     }
3845     subtype = NULL;
3846     if (IS_SCHEMA(child, "restriction")) {
3847         subtype = (xmlSchemaTypePtr)
3848             xmlSchemaParseRestriction(ctxt, schema, child, 0);
3849         child = child->next;
3850     } else if (IS_SCHEMA(child, "extension")) {
3851         subtype = (xmlSchemaTypePtr)
3852             xmlSchemaParseExtension(ctxt, schema, child);
3853         child = child->next;
3854     }
3855     type->subtypes = subtype;
3856     if (child != NULL) {
3857         xmlSchemaPErr2(ctxt, node, child,
3858                        XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
3859                        "ComplexContent %s has unexpected content\n",
3860                        type->name, NULL);
3861     }
3862     return (type);
3863 }
3864 
3865 /**
3866  * xmlSchemaParseComplexType:
3867  * @param ctxt a schema validation context
3868  * @param schema the schema being built
3869  * @param node a subtree containing XML Schema informations
3870  *
3871  * parse a XML schema Complex Type definition
3872  * *WARNING* this interface is highly subject to change
3873  *
3874  * Returns the type definition or NULL in case of error
3875  */
3876 static xmlSchemaTypePtr
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)3877 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3878                           xmlNodePtr node)
3879 {
3880     xmlSchemaTypePtr type, subtype;
3881     xmlNodePtr child = NULL;
3882     const xmlChar *name;
3883     const xmlChar *oldcontainer;
3884     char buf[100];
3885 
3886     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3887         return (NULL);
3888 
3889     oldcontainer = ctxt->container;
3890     name = xmlSchemaGetProp(ctxt, node, "name");
3891     if (name == NULL) {
3892 
3893         snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
3894     name = (const xmlChar *)buf;
3895     type = xmlSchemaAddType(ctxt, schema, name, NULL);
3896     } else {
3897 
3898         /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
3899     type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
3900     }
3901     if (type == NULL) {
3902         return (NULL);
3903     }
3904 
3905     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))
3906     type->flags |= XML_SCHEMAS_TYPE_MIXED;
3907 
3908     type->node = node;
3909     type->type = XML_SCHEMA_TYPE_COMPLEX;
3910     type->id = xmlSchemaGetProp(ctxt, node, "id");
3911     ctxt->container = name;
3912 
3913     child = node->children;
3914     if (IS_SCHEMA(child, "annotation")) {
3915         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3916         child = child->next;
3917     }
3918     if (IS_SCHEMA(child, "simpleContent")) {
3919     /* 3.4.3 : 2.2
3920      * Specifying mixed='true' when the <simpleContent>
3921      * alternative is chosen has no effect
3922      */
3923     if (type->flags & XML_SCHEMAS_TYPE_MIXED)
3924         type->flags ^= XML_SCHEMAS_TYPE_MIXED;
3925         type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
3926         child = child->next;
3927     } else if (IS_SCHEMA(child, "complexContent")) {
3928         type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
3929         child = child->next;
3930     } else {
3931         subtype = NULL;
3932 
3933         if (IS_SCHEMA(child, "all")) {
3934             subtype = xmlSchemaParseAll(ctxt, schema, child);
3935             child = child->next;
3936         } else if (IS_SCHEMA(child, "choice")) {
3937             subtype = xmlSchemaParseChoice(ctxt, schema, child);
3938             child = child->next;
3939         } else if (IS_SCHEMA(child, "sequence")) {
3940             subtype = xmlSchemaParseSequence(ctxt, schema, child);
3941             child = child->next;
3942         } else if (IS_SCHEMA(child, "group")) {
3943             subtype = xmlSchemaParseGroup(ctxt, schema, child);
3944             child = child->next;
3945         }
3946         if (subtype != NULL)
3947             type->subtypes = subtype;
3948         child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3949     }
3950     if (child != NULL) {
3951         xmlSchemaPErr2(ctxt, node, child,
3952                        XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
3953                        "ComplexType %s has unexpected content\n",
3954                        type->name, NULL);
3955     }
3956     ctxt->container = oldcontainer;
3957     return (type);
3958 }
3959 
3960 /**
3961  * xmlSchemaParseSchema:
3962  * @param ctxt a schema validation context
3963  * @param node a subtree containing XML Schema informations
3964  *
3965  * parse a XML schema definition from a node set
3966  * *WARNING* this interface is highly subject to change
3967  *
3968  * Returns the internal XML Schema structure built from the resource or
3969  *         NULL in case of error
3970  */
3971 static xmlSchemaPtr
xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)3972 xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3973 {
3974     xmlSchemaPtr schema = NULL;
3975     xmlNodePtr child = NULL;
3976     const xmlChar *val;
3977     int nberrors;
3978 
3979     if ((ctxt == NULL) || (node == NULL))
3980         return (NULL);
3981 
3982     nberrors = ctxt->nberrors;
3983     ctxt->nberrors = 0;
3984     if (IS_SCHEMA(node, "schema")) {
3985         schema = xmlSchemaNewSchema(ctxt);
3986         if (schema == NULL)
3987             return (NULL);
3988     val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
3989     if (val != NULL) {
3990         schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
3991     } else {
3992         schema->targetNamespace = NULL;
3993     }
3994         schema->id = xmlSchemaGetProp(ctxt, node, "id");
3995         schema->version = xmlSchemaGetProp(ctxt, node, "version");
3996         val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
3997         if (val != NULL) {
3998             if (xmlStrEqual(val, BAD_CAST "qualified"))
3999                 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
4000             else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
4001                 xmlSchemaPErr2(ctxt, node, child,
4002                                XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
4003                                "Invalid value %s for elementFormDefault\n",
4004                                val, NULL);
4005             }
4006         } else {
4007         schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
4008     }
4009         val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
4010         if (val != NULL) {
4011             if (xmlStrEqual(val, BAD_CAST "qualified"))
4012                 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
4013             else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
4014                 xmlSchemaPErr2(ctxt, node, child,
4015                                XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
4016                                "Invalid value %s for attributeFormDefault\n",
4017                                val, NULL);
4018             }
4019         }
4020 
4021         xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
4022     } else {
4023         xmlDocPtr doc;
4024 
4025     doc = node->doc;
4026 
4027         if ((doc != NULL) && (doc->URL != NULL)) {
4028         xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4029               XML_SCHEMAP_NOT_SCHEMA,
4030               "File %s is not a schemas", doc->URL, NULL);
4031     } else {
4032         xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4033               XML_SCHEMAP_NOT_SCHEMA,
4034               "File is not a schemas", NULL, NULL);
4035     }
4036     return(NULL);
4037     }
4038     if (ctxt->nberrors != 0) {
4039         if (schema != NULL) {
4040             xmlSchemaFree(schema);
4041             schema = NULL;
4042         }
4043     }
4044     ctxt->nberrors = nberrors;
4045 #ifdef DEBUG
4046     if (schema == NULL)
4047         xmlGenericError(xmlGenericErrorContext,
4048                         "xmlSchemaParse() failed\n");
4049 #endif
4050 
4051     return (schema);
4052 }
4053 
4054 /************************************************************************
4055  *                                  *
4056  *          Validating using Schemas            *
4057  *                                  *
4058  ************************************************************************/
4059 
4060 /************************************************************************
4061  *                                  *
4062  *          Reading/Writing Schemas             *
4063  *                                  *
4064  ************************************************************************/
4065 
4066 /**
4067  * xmlSchemaNewParserCtxt:
4068  * @param URL the location of the schema
4069  *
4070  * Create an XML Schemas parse context for that file/resource expected
4071  * to contain an XML Schemas file.
4072  *
4073  * Returns the parser context or NULL in case of error
4074  */
4075 xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxt(const char * URL)4076 xmlSchemaNewParserCtxt(const char *URL)
4077 {
4078     xmlSchemaParserCtxtPtr ret;
4079 
4080     if (URL == NULL)
4081         return (NULL);
4082 
4083     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4084     if (ret == NULL) {
4085         xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4086                             NULL);
4087         return (NULL);
4088     }
4089     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4090     ret->dict = xmlDictCreate();
4091     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
4092     ret->includes = 0;
4093     return (ret);
4094 }
4095 
4096 /**
4097  * xmlSchemaNewMemParserCtxt:
4098  * @param buffer a pointer to a char array containing the schemas
4099  * @param size the size of the array
4100  *
4101  * Create an XML Schemas parse context for that memory buffer expected
4102  * to contain an XML Schemas file.
4103  *
4104  * Returns the parser context or NULL in case of error
4105  */
4106 xmlSchemaParserCtxtPtr
xmlSchemaNewMemParserCtxt(const char * buffer,int size)4107 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
4108 {
4109     xmlSchemaParserCtxtPtr ret;
4110 
4111     if ((buffer == NULL) || (size <= 0))
4112         return (NULL);
4113 
4114     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4115     if (ret == NULL) {
4116         xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4117                             NULL);
4118         return (NULL);
4119     }
4120     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4121     ret->buffer = buffer;
4122     ret->size = size;
4123     ret->dict = xmlDictCreate();
4124     return (ret);
4125 }
4126 
4127 /**
4128  * xmlSchemaNewDocParserCtxt:
4129  * @param doc a preparsed document tree
4130  *
4131  * Create an XML Schemas parse context for that document.
4132  * NB. The document may be modified during the parsing process.
4133  *
4134  * Returns the parser context or NULL in case of error
4135  */
4136 xmlSchemaParserCtxtPtr
xmlSchemaNewDocParserCtxt(xmlDocPtr doc)4137 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
4138 {
4139     xmlSchemaParserCtxtPtr ret;
4140 
4141     if (doc == NULL)
4142       return (NULL);
4143 
4144     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4145     if (ret == NULL) {
4146       xmlSchemaPErrMemory(NULL, "allocating schema parser context",
4147               NULL);
4148       return (NULL);
4149     }
4150     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4151     ret->doc = doc;
4152     ret->dict = xmlDictCreate();
4153     /* The application has responsibility for the document */
4154     ret->preserve = 1;
4155 
4156     return (ret);
4157 }
4158 
4159 /**
4160  * xmlSchemaFreeParserCtxt:
4161  * @param ctxt the schema parser context
4162  *
4163  * Free the resources associated to the schema parser context
4164  */
4165 void
xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)4166 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
4167 {
4168     if (ctxt == NULL)
4169         return;
4170     if (ctxt->doc != NULL && !ctxt->preserve)
4171         xmlFreeDoc(ctxt->doc);
4172     xmlDictFree(ctxt->dict);
4173     xmlFree(ctxt);
4174 }
4175 
4176 /************************************************************************
4177  *                                  *
4178  *          Building the content models         *
4179  *                                  *
4180  ************************************************************************/
4181 
4182 /**
4183  * xmlSchemaBuildAContentModel:
4184  * @param type the schema type definition
4185  * @param ctxt the schema parser context
4186  * @param name the element name whose content is being built
4187  *
4188  * Generate the automata sequence needed for that type
4189  */
4190 static void
xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name)4191 xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
4192                             xmlSchemaParserCtxtPtr ctxt,
4193                             const xmlChar * name)
4194 {
4195     if (type == NULL) {
4196         xmlGenericError(xmlGenericErrorContext,
4197                         "Found unexpected type = NULL in %s content model\n",
4198                         name);
4199         return;
4200     }
4201     switch (type->type) {
4202         case XML_SCHEMA_TYPE_ANY:
4203 
4204 
4205             TODO ctxt->state =
4206                 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
4207                                          BAD_CAST "*", NULL);
4208             break;
4209         case XML_SCHEMA_TYPE_ELEMENT:{
4210                 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
4211 
4212 
4213                 xmlAutomataStatePtr oldstate = ctxt->state;
4214 
4215                 if (elem->maxOccurs >= UNBOUNDED) {
4216                     if (elem->minOccurs > 1) {
4217                         xmlAutomataStatePtr tmp;
4218                         int counter;
4219 
4220                         ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4221                                                             oldstate,
4222                                                             NULL);
4223                         oldstate = ctxt->state;
4224 
4225                         counter = xmlAutomataNewCounter(ctxt->am,
4226                                                         elem->minOccurs -
4227                                                         1, UNBOUNDED);
4228 
4229                         if (elem->refDecl != NULL) {
4230                             xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4231                                                         elem->refDecl,
4232                                                         ctxt,
4233                                                         elem->refDecl->
4234                                                         name);
4235                         } else {
4236                             ctxt->state =
4237                                 xmlAutomataNewTransition(ctxt->am,
4238                                                          ctxt->state, NULL,
4239                                                          elem->name, type);
4240                         }
4241                         tmp = ctxt->state;
4242                         xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4243                                                    counter);
4244                         ctxt->state =
4245                             xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4246                                                        counter);
4247 
4248                     } else {
4249                         if (elem->refDecl != NULL) {
4250                             xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4251                                                         elem->refDecl,
4252                                                         ctxt,
4253                                                         elem->refDecl->
4254                                                         name);
4255                         } else {
4256                             ctxt->state =
4257                                 xmlAutomataNewTransition(ctxt->am,
4258                                                          ctxt->state, NULL,
4259                                                          elem->name, type);
4260                         }
4261                         xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4262                                               oldstate);
4263                         if (elem->minOccurs == 0) {
4264                             /* basically an elem* */
4265                             xmlAutomataNewEpsilon(ctxt->am, oldstate,
4266                                                   ctxt->state);
4267                         }
4268                     }
4269                 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
4270                     xmlAutomataStatePtr tmp;
4271                     int counter;
4272 
4273                     ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4274                                                         oldstate, NULL);
4275                     oldstate = ctxt->state;
4276 
4277                     counter = xmlAutomataNewCounter(ctxt->am,
4278                                                     elem->minOccurs - 1,
4279                                                     elem->maxOccurs - 1);
4280 
4281                     if (elem->refDecl != NULL) {
4282                         xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4283                                                     elem->refDecl, ctxt,
4284                                                     elem->refDecl->name);
4285                     } else {
4286                         ctxt->state = xmlAutomataNewTransition(ctxt->am,
4287                                                                ctxt->state,
4288                                                                NULL,
4289                                                                elem->name,
4290                                                                type);
4291                     }
4292                     tmp = ctxt->state;
4293                     xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4294                                                counter);
4295                     ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
4296                                                              NULL,
4297                                                              counter);
4298                     if (elem->minOccurs == 0) {
4299                         /* basically an elem? */
4300                         xmlAutomataNewEpsilon(ctxt->am, oldstate,
4301                                               ctxt->state);
4302                     }
4303 
4304                 } else {
4305                     if (elem->refDecl != NULL) {
4306                         xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4307                                                     elem->refDecl, ctxt,
4308                                                     elem->refDecl->name);
4309                     } else {
4310                         ctxt->state = xmlAutomataNewTransition(ctxt->am,
4311                                                                ctxt->state,
4312                                                                NULL,
4313                                                                elem->name,
4314                                                                type);
4315                     }
4316                     if (elem->minOccurs == 0) {
4317                         /* basically an elem? */
4318                         xmlAutomataNewEpsilon(ctxt->am, oldstate,
4319                                               ctxt->state);
4320                     }
4321                 }
4322                 break;
4323             }
4324         case XML_SCHEMA_TYPE_SEQUENCE:{
4325                 xmlSchemaTypePtr subtypes;
4326 
4327                 /*
4328                  * If max and min occurances are default (1) then
4329                  * simply iterate over the subtypes
4330                  */
4331                 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
4332                     subtypes = type->subtypes;
4333                     while (subtypes != NULL) {
4334                         xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4335                         subtypes = subtypes->next;
4336                     }
4337                 } else {
4338                     xmlAutomataStatePtr oldstate = ctxt->state;
4339 
4340                     if (type->maxOccurs >= UNBOUNDED) {
4341                         if (type->minOccurs > 1) {
4342                             xmlAutomataStatePtr tmp;
4343                             int counter;
4344 
4345                             ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4346                                                                 oldstate,
4347                                                                 NULL);
4348                             oldstate = ctxt->state;
4349 
4350                             counter = xmlAutomataNewCounter(ctxt->am,
4351                                                             type->
4352                                                             minOccurs - 1,
4353                                                             UNBOUNDED);
4354 
4355                             subtypes = type->subtypes;
4356                             while (subtypes != NULL) {
4357                                 xmlSchemaBuildAContentModel(subtypes, ctxt,
4358                                                             name);
4359                                 subtypes = subtypes->next;
4360                             }
4361                             tmp = ctxt->state;
4362                             xmlAutomataNewCountedTrans(ctxt->am, tmp,
4363                                                        oldstate, counter);
4364                             ctxt->state =
4365                                 xmlAutomataNewCounterTrans(ctxt->am, tmp,
4366                                                            NULL, counter);
4367 
4368                         } else {
4369                             subtypes = type->subtypes;
4370                             while (subtypes != NULL) {
4371                                 xmlSchemaBuildAContentModel(subtypes, ctxt,
4372                                                             name);
4373                                 subtypes = subtypes->next;
4374                             }
4375                             xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4376                                                   oldstate);
4377                             if (type->minOccurs == 0) {
4378                                 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4379                                                       ctxt->state);
4380                             }
4381                         }
4382                     } else if ((type->maxOccurs > 1)
4383                                || (type->minOccurs > 1)) {
4384                         xmlAutomataStatePtr tmp;
4385                         int counter;
4386 
4387                         ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4388                                                             oldstate,
4389                                                             NULL);
4390                         oldstate = ctxt->state;
4391 
4392                         counter = xmlAutomataNewCounter(ctxt->am,
4393                                                         type->minOccurs -
4394                                                         1,
4395                                                         type->maxOccurs -
4396                                                         1);
4397 
4398                         subtypes = type->subtypes;
4399                         while (subtypes != NULL) {
4400                             xmlSchemaBuildAContentModel(subtypes, ctxt,
4401                                                         name);
4402                             subtypes = subtypes->next;
4403                         }
4404                         tmp = ctxt->state;
4405                         xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4406                                                    counter);
4407                         ctxt->state =
4408                             xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4409                                                        counter);
4410                         if (type->minOccurs == 0) {
4411                             xmlAutomataNewEpsilon(ctxt->am, oldstate,
4412                                                   ctxt->state);
4413                         }
4414 
4415                     } else {
4416                         subtypes = type->subtypes;
4417                         while (subtypes != NULL) {
4418                             xmlSchemaBuildAContentModel(subtypes, ctxt,
4419                                                         name);
4420                             subtypes = subtypes->next;
4421                         }
4422                         if (type->minOccurs == 0) {
4423                             xmlAutomataNewEpsilon(ctxt->am, oldstate,
4424                                                   ctxt->state);
4425                         }
4426                     }
4427                 }
4428                 break;
4429             }
4430         case XML_SCHEMA_TYPE_CHOICE:{
4431                 xmlSchemaTypePtr subtypes;
4432                 xmlAutomataStatePtr start, end;
4433 
4434                 start = ctxt->state;
4435                 end = xmlAutomataNewState(ctxt->am);
4436 
4437                 /*
4438                  * iterate over the subtypes and remerge the end with an
4439                  * epsilon transition
4440                  */
4441                 if (type->maxOccurs == 1) {
4442                     subtypes = type->subtypes;
4443                     while (subtypes != NULL) {
4444                         ctxt->state = start;
4445                         xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4446                         xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
4447                         subtypes = subtypes->next;
4448                     }
4449                 } else {
4450                     int counter;
4451                     xmlAutomataStatePtr hop;
4452                     int maxOccurs = type->maxOccurs == UNBOUNDED ?
4453                         UNBOUNDED : type->maxOccurs - 1;
4454                     int minOccurs =
4455                         type->minOccurs < 1 ? 0 : type->minOccurs - 1;
4456 
4457                     /*
4458                      * use a counter to keep track of the number of transtions
4459                      * which went through the choice.
4460                      */
4461                     counter =
4462                         xmlAutomataNewCounter(ctxt->am, minOccurs,
4463                                               maxOccurs);
4464                     hop = xmlAutomataNewState(ctxt->am);
4465 
4466                     subtypes = type->subtypes;
4467                     while (subtypes != NULL) {
4468                         ctxt->state = start;
4469                         xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4470                         xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
4471                         subtypes = subtypes->next;
4472                     }
4473                     xmlAutomataNewCountedTrans(ctxt->am, hop, start,
4474                                                counter);
4475                     xmlAutomataNewCounterTrans(ctxt->am, hop, end,
4476                                                counter);
4477                 }
4478                 if (type->minOccurs == 0) {
4479                     xmlAutomataNewEpsilon(ctxt->am, start, end);
4480                 }
4481                 ctxt->state = end;
4482                 break;
4483             }
4484         case XML_SCHEMA_TYPE_ALL:{
4485                 xmlAutomataStatePtr start;
4486                 xmlSchemaTypePtr subtypes;
4487                 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
4488                 int lax;
4489 
4490                 subtypes = type->subtypes;
4491                 if (subtypes == NULL)
4492                     break;
4493                 start = ctxt->state;
4494                 while (subtypes != NULL) {
4495                     ctxt->state = start;
4496             /*
4497              * the following 'if' was needed to fix bug139897
4498              * not quite sure why it only needs to be done for
4499              * elements with a 'ref', but it seems to work ok.
4500              */
4501             if (subtypes->ref != NULL)
4502                 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4503                     elem = (xmlSchemaElementPtr) subtypes;
4504 
4505                     if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
4506                         xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
4507                                                 ctxt->state, elem->name, 1,
4508                                                 1, subtypes);
4509                     } else {
4510                         xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
4511                                                  ctxt->state, elem->name,
4512                                                  elem->minOccurs,
4513                                                  elem->maxOccurs,
4514                                                  subtypes);
4515                     }
4516                     subtypes = subtypes->next;
4517                 }
4518                 lax = type->minOccurs == 0;
4519                 ctxt->state =
4520                     xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
4521                                            lax);
4522                 break;
4523             }
4524         case XML_SCHEMA_TYPE_RESTRICTION:
4525             if (type->subtypes != NULL)
4526                 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4527             break;
4528         case XML_SCHEMA_TYPE_EXTENSION:
4529             if (type->baseType != NULL) {
4530                 xmlSchemaTypePtr subtypes;
4531 
4532         if (type->recurse) {
4533             xmlSchemaPErr(ctxt, type->node,
4534                           XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4535                 "Schemas: extension type %s is recursive\n",
4536                   type->name, NULL);
4537             return;
4538                 }
4539                 type->recurse = 1;
4540                 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
4541                 type->recurse = 0;
4542                 subtypes = type->subtypes;
4543                 while (subtypes != NULL) {
4544                     xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4545                     subtypes = subtypes->next;
4546                 }
4547             } else if (type->subtypes != NULL)
4548                 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4549             break;
4550         case XML_SCHEMA_TYPE_GROUP:
4551             if (type->subtypes == NULL) {
4552             xmlSchemaTypePtr rgroup;
4553         if (type->ref != NULL) {
4554             rgroup = xmlHashLookup2(ctxt->schema->groupDecl, type->ref,
4555                            type->refNs);
4556             if (rgroup == NULL) {
4557                 xmlSchemaPErr(ctxt, type->node,
4558                       XML_SCHEMAP_UNKNOWN_REF,
4559                 "Schemas: group %s reference %s is not found",
4560                 name, type->ref);
4561             return;
4562             }
4563             xmlSchemaBuildAContentModel(rgroup, ctxt, name);
4564             break;
4565         }
4566             }
4567         case XML_SCHEMA_TYPE_COMPLEX:
4568         case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4569             if (type->subtypes != NULL)
4570                 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4571             break;
4572         default:
4573             xmlGenericError(xmlGenericErrorContext,
4574                             "Found unexpected type %d in %s content model\n",
4575                             type->type, name);
4576             return;
4577     }
4578 }
4579 
4580 /**
4581  * xmlSchemaBuildContentModel:
4582  * @param elem the element
4583  * @param ctxt the schema parser context
4584  * @param name the element name
4585  *
4586  * Builds the content model of the element.
4587  */
4588 static void
xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name)4589 xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
4590                            xmlSchemaParserCtxtPtr ctxt,
4591                            const xmlChar * name)
4592 {
4593     xmlAutomataStatePtr start;
4594 
4595     if (elem->contModel != NULL)
4596         return;
4597     if (elem->subtypes == NULL) {
4598         elem->contentType = XML_SCHEMA_CONTENT_ANY;
4599         return;
4600     }
4601     if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
4602         return;
4603     if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
4604         (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
4605         return;
4606 
4607 #ifdef DEBUG_CONTENT
4608     xmlGenericError(xmlGenericErrorContext,
4609                     "Building content model for %s\n", name);
4610 #endif
4611 
4612     ctxt->am = xmlNewAutomata();
4613     if (ctxt->am == NULL) {
4614         xmlGenericError(xmlGenericErrorContext,
4615                         "Cannot create automata for elem %s\n", name);
4616         return;
4617     }
4618     start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
4619     xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
4620     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
4621     elem->contModel = xmlAutomataCompile(ctxt->am);
4622     if (elem->contModel == NULL) {
4623         xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
4624                       "failed to compile %s content model\n", name, NULL);
4625     } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
4626         xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
4627                       "Content model of %s is not determinist:\n", name,
4628                       NULL);
4629     } else {
4630 #ifdef DEBUG_CONTENT_REGEXP
4631         xmlGenericError(xmlGenericErrorContext,
4632                         "Content model of %s:\n", name);
4633         xmlRegexpPrint(stderr, elem->contModel);
4634 #endif
4635     }
4636     ctxt->state = NULL;
4637     xmlFreeAutomata(ctxt->am);
4638     ctxt->am = NULL;
4639 }
4640 
4641 /**
4642  * xmlSchemaRefFixupCallback:
4643  * @param elem the schema element context
4644  * @param ctxt the schema parser context
4645  *
4646  * Free the resources associated to the schema parser context
4647  */
4648 static void
xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name,const xmlChar * context ATTRIBUTE_UNUSED,const xmlChar * namespace ATTRIBUTE_UNUSED)4649 xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
4650                           xmlSchemaParserCtxtPtr ctxt,
4651                           const xmlChar * name,
4652                           const xmlChar * context ATTRIBUTE_UNUSED,
4653                           const xmlChar * namespace ATTRIBUTE_UNUSED)
4654 {
4655     if ((ctxt == NULL) || (elem == NULL))
4656         return;
4657     if (elem->ref != NULL) {
4658         xmlSchemaElementPtr elemDecl;
4659 
4660         if (elem->subtypes != NULL) {
4661             xmlSchemaPErr(ctxt, elem->node,
4662                           XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
4663                           "Schemas: element %s have both ref and subtype\n",
4664                           name, NULL);
4665             return;
4666         }
4667         elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
4668 
4669         if (elemDecl == NULL) {
4670             xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
4671                           "Schemas: element %s ref to %s not found\n",
4672                           name, elem->ref);
4673             return;
4674         }
4675         elem->refDecl = elemDecl;
4676     } else if (elem->namedType != NULL) {
4677         xmlSchemaTypePtr typeDecl;
4678 
4679         if (elem->subtypes != NULL) {
4680             xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
4681                           "Schemas: element %s have both type and subtype\n",
4682                           name, NULL);
4683             return;
4684         }
4685         typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
4686                                     elem->namedTypeNs);
4687 
4688         if (typeDecl == NULL) {
4689             xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
4690                           "Schemas: element %s type %s not found\n", name,
4691                           elem->namedType);
4692             return;
4693         }
4694         elem->subtypes = typeDecl;
4695     }
4696 }
4697 
4698 /**
4699  * xmlSchemaParseListRefFixup:
4700  * @param type the schema type definition
4701  * @param ctxt the schema parser context
4702  *
4703  * Fixup of the itemType reference of the list type.
4704  */
4705 static void
xmlSchemaParseListRefFixup(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt)4706 xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
4707 {
4708     const xmlChar *itemType, *namespace;
4709     xmlSchemaTypePtr subtype;
4710 
4711     /* Handle the "itemType" attribute. */
4712     itemType = xmlGetQNameProp(ctxt, type->node, "itemType", &namespace);
4713     if (itemType != NULL) {
4714         /* Do not allow more that one item type. */
4715         if (type->subtypes != NULL) {
4716             xmlSchemaPErr(ctxt, type->node,
4717                   XML_SCHEMAP_SUPERNUMEROUS_LIST_ITEM_TYPE,
4718                           "List %s has more than one item type defined\n",
4719               type->name, NULL);
4720         }
4721         subtype = xmlSchemaGetType(ctxt->schema, itemType, namespace);
4722         if (subtype == NULL) {
4723             xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_TYPE,
4724                           "List %s references an unknown item type: %s\n",
4725                           type->name, xmlSchemaGetProp(ctxt, type->node,
4726               "itemType"));
4727         } else
4728             type->subtypes = subtype;
4729     }
4730 }
4731 
4732 /**
4733  * xmlSchemaParseUnionRefCheck:
4734  * @param typeDecl the schema type definition
4735  * @param ctxt the schema parser context
4736  *
4737  * Checks the memberTypes references of the union type.
4738  */
4739 static void
xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt)4740 xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
4741                    xmlSchemaParserCtxtPtr ctxt)
4742 {
4743     const xmlChar *cur, *end, *prefix, *ncName, *namespace;
4744     xmlChar *tmp;
4745     xmlSchemaTypePtr subtype;
4746     xmlNsPtr ns;
4747     int len;
4748 
4749      if ((type->type != XML_SCHEMA_TYPE_UNION) || (type->ref == NULL))
4750         return;
4751 
4752     cur = type->ref;
4753     do {
4754         while (IS_BLANK_CH(*cur))
4755             cur++;
4756         end = cur;
4757         while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4758             end++;
4759         if (end == cur)
4760             break;
4761         tmp = xmlStrndup(cur, end - cur);
4762         ncName = xmlSplitQName3(tmp, &len);
4763         if (ncName != NULL) {
4764             prefix = xmlDictLookup(ctxt->dict, tmp, len);
4765         } else {
4766             prefix = NULL;
4767             ncName = tmp;
4768         }
4769         ns = xmlSearchNs(type->node->doc, type->node, prefix);
4770         if (ns == NULL) {
4771             if (prefix != NULL) {
4772                 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_PREFIX_UNDEFINED,
4773                               "Union %s: the namespace prefix of member type "
4774                   "%s is undefined\n",
4775                               type->name, (const xmlChar *) tmp);
4776             }
4777             namespace = NULL;
4778         } else {
4779             namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4780         }
4781         /* Lookup the referenced type */
4782         subtype = xmlSchemaGetType(ctxt->schema, ncName, namespace);
4783         if (subtype == NULL) {
4784             xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
4785                        "Union %s references an unknown member type %s\n",
4786                        type->name,  (const xmlChar *) tmp);
4787         }
4788         xmlFree(tmp);
4789         cur = end;
4790     } while (*cur != 0);
4791 }
4792 
4793 /**
4794  * xmlSchemaTypeFixup:
4795  * @param typeDecl the schema type definition
4796  * @param ctxt the schema parser context
4797  *
4798  * Fixes the content model of the type.
4799  */
4800 static void
xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name)4801 xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
4802                    xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
4803 {
4804     if (typeDecl == NULL)
4805         return;
4806     if (name == NULL)
4807         name = typeDecl->name;
4808     if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
4809         switch (typeDecl->type) {
4810             case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
4811                     xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4812                     if (typeDecl->subtypes != NULL)
4813                         typeDecl->contentType =
4814                             typeDecl->subtypes->contentType;
4815                     break;
4816                 }
4817             case XML_SCHEMA_TYPE_RESTRICTION:{
4818                     if (typeDecl->subtypes != NULL)
4819                         xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4820 
4821                     if (typeDecl->base != NULL) {
4822                         xmlSchemaTypePtr baseType;
4823 
4824                         baseType =
4825                             xmlSchemaGetType(ctxt->schema, typeDecl->base,
4826                                              typeDecl->baseNs);
4827                         if (baseType == NULL) {
4828                 xmlSchemaPErr(ctxt, typeDecl->node,
4829                               XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4830                 "Schemas: type %s base type %s not found\n",
4831                                           name, typeDecl->base);
4832                         }
4833                         typeDecl->baseType = baseType;
4834                     }
4835             if (typeDecl->subtypes == NULL)
4836             if (typeDecl->baseType != NULL) {
4837                 /* The base type might be not "type fixed" yet,
4838                  * so do it now. */
4839                 if (typeDecl->baseType->contentType ==
4840                         XML_SCHEMA_CONTENT_UNKNOWN)
4841                 xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL);
4842                 typeDecl->contentType =
4843                          typeDecl->baseType->contentType;
4844             } else
4845                             /* 1.1.1 */
4846                             typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4847                     else if ((typeDecl->subtypes->subtypes == NULL) &&
4848                              ((typeDecl->subtypes->type ==
4849                                XML_SCHEMA_TYPE_ALL)
4850                               || (typeDecl->subtypes->type ==
4851                                   XML_SCHEMA_TYPE_SEQUENCE)))
4852                         /* 1.1.2 */
4853                         typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4854                     else if ((typeDecl->subtypes->type ==
4855                               XML_SCHEMA_TYPE_CHOICE)
4856                              && (typeDecl->subtypes->subtypes == NULL))
4857                         /* 1.1.3 */
4858                         typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4859                     else {
4860                         /* 1.2 and 2.X are applied at the other layer */
4861                         typeDecl->contentType =
4862                             XML_SCHEMA_CONTENT_ELEMENTS;
4863                     }
4864                     break;
4865                 }
4866             case XML_SCHEMA_TYPE_EXTENSION:{
4867                     xmlSchemaContentType explicitContentType;
4868                     xmlSchemaTypePtr base;
4869 
4870                     if (typeDecl->base != NULL) {
4871                         xmlSchemaTypePtr baseType;
4872 
4873                         baseType =
4874                             xmlSchemaGetType(ctxt->schema, typeDecl->base,
4875                                              typeDecl->baseNs);
4876                         if (baseType == NULL) {
4877                 xmlSchemaPErr(ctxt, typeDecl->node,
4878                               XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4879                 "Schemas: type %s base type %s not found\n",
4880                                           name, typeDecl->base);
4881                         }
4882                         typeDecl->baseType = baseType;
4883                     }
4884                     if (typeDecl->subtypes != NULL)
4885                         xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4886 
4887                     explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
4888                     if (typeDecl->subtypes == NULL)
4889                         /* 1.1.1 */
4890                         explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4891                     else if ((typeDecl->subtypes->subtypes == NULL) &&
4892                              ((typeDecl->subtypes->type ==
4893                                XML_SCHEMA_TYPE_ALL)
4894                               || (typeDecl->subtypes->type ==
4895                                   XML_SCHEMA_TYPE_SEQUENCE)))
4896                         /* 1.1.2 */
4897                         explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4898                     else if ((typeDecl->subtypes->type ==
4899                               XML_SCHEMA_TYPE_CHOICE)
4900                              && (typeDecl->subtypes->subtypes == NULL))
4901                         /* 1.1.3 */
4902                         explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4903 
4904                     base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
4905                                             typeDecl->baseNs);
4906                     if (base == NULL) {
4907                         xmlSchemaPErr(ctxt, typeDecl->node,
4908                                       XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4909                                       "Schemas: base type %s of type %s not found\n",
4910                                       typeDecl->base, name);
4911                         return;
4912                     }
4913                     if (typeDecl->recurse) {
4914                         xmlSchemaPErr(ctxt, typeDecl->node,
4915                                       XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4916                   "Schemas: extension type %s is recursive\n",
4917                                       name, NULL);
4918                         return;
4919             }
4920             typeDecl->recurse = 1;
4921                     xmlSchemaTypeFixup(base, ctxt, NULL);
4922             typeDecl->recurse = 0;
4923                     if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
4924                         /* 2.1 */
4925                         typeDecl->contentType = base->contentType;
4926                     } else if (base->contentType ==
4927                                XML_SCHEMA_CONTENT_EMPTY) {
4928                         /* 2.2 imbitable ! */
4929                         typeDecl->contentType =
4930                             XML_SCHEMA_CONTENT_ELEMENTS;
4931                     } else {
4932                         /* 2.3 imbitable pareil ! */
4933                         typeDecl->contentType =
4934                             XML_SCHEMA_CONTENT_ELEMENTS;
4935                     }
4936                     break;
4937                 }
4938             case XML_SCHEMA_TYPE_COMPLEX:{
4939                     if (typeDecl->subtypes == NULL) {
4940                         typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4941 
4942                         if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4943                             typeDecl->contentType =
4944                                 XML_SCHEMA_CONTENT_MIXED;
4945                     } else {
4946                         if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4947                             typeDecl->contentType =
4948                                 XML_SCHEMA_CONTENT_MIXED;
4949                         else {
4950                             xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4951                                                NULL);
4952                             if (typeDecl->subtypes != NULL)
4953                                 typeDecl->contentType =
4954                                     typeDecl->subtypes->contentType;
4955                         }
4956             if (typeDecl->attributes == NULL)
4957                 typeDecl->attributes =
4958                     typeDecl->subtypes->attributes;
4959                     }
4960                     break;
4961                 }
4962             case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4963                     if (typeDecl->subtypes == NULL) {
4964                         typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4965                         if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4966                             typeDecl->contentType =
4967                                 XML_SCHEMA_CONTENT_MIXED;
4968                     } else {
4969                         if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4970                             typeDecl->contentType =
4971                                 XML_SCHEMA_CONTENT_MIXED;
4972                         else {
4973                             xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4974                                                NULL);
4975                             if (typeDecl->subtypes != NULL)
4976                                 typeDecl->contentType =
4977                                     typeDecl->subtypes->contentType;
4978                         }
4979             if (typeDecl->attributes == NULL)
4980                 typeDecl->attributes =
4981                     typeDecl->subtypes->attributes;
4982                     }
4983                     break;
4984                 }
4985             case XML_SCHEMA_TYPE_SEQUENCE:
4986             case XML_SCHEMA_TYPE_GROUP:
4987             case XML_SCHEMA_TYPE_ALL:
4988             case XML_SCHEMA_TYPE_CHOICE:
4989                 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4990                 break;
4991             case XML_SCHEMA_TYPE_BASIC:
4992             case XML_SCHEMA_TYPE_ANY:
4993             case XML_SCHEMA_TYPE_FACET:
4994             case XML_SCHEMA_TYPE_SIMPLE:
4995             case XML_SCHEMA_TYPE_UR:
4996             case XML_SCHEMA_TYPE_ELEMENT:
4997             case XML_SCHEMA_TYPE_ATTRIBUTE:
4998             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4999             case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
5000             case XML_SCHEMA_TYPE_NOTATION:
5001             case XML_SCHEMA_TYPE_LIST:
5002         xmlSchemaParseListRefFixup(typeDecl, ctxt);
5003             case XML_SCHEMA_TYPE_UNION:
5004                 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
5005             case XML_SCHEMA_FACET_MININCLUSIVE:
5006             case XML_SCHEMA_FACET_MINEXCLUSIVE:
5007             case XML_SCHEMA_FACET_MAXINCLUSIVE:
5008             case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5009             case XML_SCHEMA_FACET_TOTALDIGITS:
5010             case XML_SCHEMA_FACET_FRACTIONDIGITS:
5011             case XML_SCHEMA_FACET_PATTERN:
5012             case XML_SCHEMA_FACET_ENUMERATION:
5013             case XML_SCHEMA_FACET_WHITESPACE:
5014             case XML_SCHEMA_FACET_LENGTH:
5015             case XML_SCHEMA_FACET_MAXLENGTH:
5016             case XML_SCHEMA_FACET_MINLENGTH:
5017                 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
5018         if (typeDecl->subtypes != NULL)
5019             xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
5020                 break;
5021         }
5022     }
5023 #ifdef DEBUG_TYPE
5024     if (typeDecl->node != NULL) {
5025         xmlGenericError(xmlGenericErrorContext,
5026                         "Type of %s : %s:%d :", name,
5027                         typeDecl->node->doc->URL,
5028 #ifdef LIBXML_ENABLE_NODE_LINEINFO
5029                         xmlGetLineNo(typeDecl->node)
5030 #else
5031                         0
5032 #endif
5033                         );
5034     } else {
5035         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
5036     }
5037     switch (typeDecl->contentType) {
5038         case XML_SCHEMA_CONTENT_SIMPLE:
5039             xmlGenericError(xmlGenericErrorContext, "simple\n");
5040             break;
5041         case XML_SCHEMA_CONTENT_ELEMENTS:
5042             xmlGenericError(xmlGenericErrorContext, "elements\n");
5043             break;
5044         case XML_SCHEMA_CONTENT_UNKNOWN:
5045             xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
5046             break;
5047         case XML_SCHEMA_CONTENT_EMPTY:
5048             xmlGenericError(xmlGenericErrorContext, "empty\n");
5049             break;
5050         case XML_SCHEMA_CONTENT_MIXED:
5051             xmlGenericError(xmlGenericErrorContext, "mixed\n");
5052             break;
5053         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5054             xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
5055             break;
5056         case XML_SCHEMA_CONTENT_BASIC:
5057             xmlGenericError(xmlGenericErrorContext, "basic\n");
5058             break;
5059         default:
5060             xmlGenericError(xmlGenericErrorContext,
5061                             "not registered !!!\n");
5062             break;
5063     }
5064 #endif
5065 }
5066 
5067 ///#if defined(LIBXML_SCHEMAS_ENABLED)
5068 /**
5069  * xmlSchemaCheckFacet:
5070  * @param facet the facet
5071  * @param typeDecl the schema type definition
5072  * @param ctxt the schema parser context or NULL
5073  * @param name name of the type
5074  *
5075  * Checks the default values types, especially for facets
5076  *
5077  * Returns 0 if okay or -1 in cae of error
5078  */
5079 int
xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name)5080 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
5081                     xmlSchemaTypePtr typeDecl,
5082                     xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
5083 {
5084     static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
5085     int ret = 0;
5086 
5087     if (nonNegativeIntegerType == NULL) {
5088         nonNegativeIntegerType =
5089             xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
5090                                        xmlSchemaNs);
5091     }
5092     switch (facet->type) {
5093         case XML_SCHEMA_FACET_MININCLUSIVE:
5094         case XML_SCHEMA_FACET_MINEXCLUSIVE:
5095         case XML_SCHEMA_FACET_MAXINCLUSIVE:
5096         case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
5097                 /*
5098                  * Okay we need to validate the value
5099                  * at that point.
5100                  */
5101                 xmlSchemaValidCtxtPtr vctxt;
5102 
5103                 vctxt = xmlSchemaNewValidCtxt(NULL);
5104                 if (vctxt == NULL)
5105                     break;
5106                 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
5107                                              facet->value);
5108                 facet->val = vctxt->value;
5109                 vctxt->value = NULL;
5110                 if (facet->val == NULL) {
5111                     /* error code */
5112                     if (ctxt != NULL) {
5113                         xmlSchemaPErr(ctxt, facet->node,
5114                                       XML_SCHEMAP_INVALID_FACET,
5115                                       "Schemas: type %s facet value %s invalid\n",
5116                                       name, facet->value);
5117                     }
5118                     ret = -1;
5119                 }
5120                 xmlSchemaFreeValidCtxt(vctxt);
5121                 break;
5122             }
5123         case XML_SCHEMA_FACET_ENUMERATION:{
5124                 /*
5125                  * Okay we need to validate the value
5126                  * at that point.
5127                  */
5128                 xmlSchemaValidCtxtPtr vctxt;
5129                 int tmp;
5130 
5131                 vctxt = xmlSchemaNewValidCtxt(NULL);
5132                 if (vctxt == NULL)
5133                     break;
5134                 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
5135                                                    facet->value);
5136                 if (tmp != 0) {
5137                     if (ctxt != NULL) {
5138                         xmlSchemaPErr(ctxt, facet->node,
5139                                       XML_SCHEMAP_INVALID_ENUM,
5140                                       "Schemas: type %s enumeration value %s invalid\n",
5141                                       name, facet->value);
5142                     }
5143                     ret = -1;
5144                 }
5145                 xmlSchemaFreeValidCtxt(vctxt);
5146                 break;
5147             }
5148         case XML_SCHEMA_FACET_PATTERN:
5149             facet->regexp = xmlRegexpCompile(facet->value);
5150             if (facet->regexp == NULL) {
5151         xmlSchemaPErr(ctxt, typeDecl->node,
5152                   XML_SCHEMAP_REGEXP_INVALID,
5153                               "Schemas: type %s facet regexp %s invalid\n",
5154                               name, facet->value);
5155                 ret = -1;
5156             }
5157             break;
5158         case XML_SCHEMA_FACET_TOTALDIGITS:
5159         case XML_SCHEMA_FACET_FRACTIONDIGITS:
5160         case XML_SCHEMA_FACET_LENGTH:
5161         case XML_SCHEMA_FACET_MAXLENGTH:
5162         case XML_SCHEMA_FACET_MINLENGTH:{
5163                 int tmp;
5164 
5165                 tmp =
5166                     xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
5167                                                     facet->value,
5168                                                     &facet->val);
5169                 if (tmp != 0) {
5170                     /* error code */
5171                     if (ctxt != NULL) {
5172                         xmlSchemaPErr(ctxt, facet->node,
5173                                       XML_SCHEMAP_INVALID_FACET_VALUE,
5174                                       "Schemas: type %s facet value %s invalid\n",
5175                                       name, facet->value);
5176                     }
5177                     ret = -1;
5178                 }
5179                 break;
5180             }
5181         case XML_SCHEMA_FACET_WHITESPACE:{
5182                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
5183                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
5184                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
5185                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
5186                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
5187                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
5188                 } else {
5189                     if (ctxt != NULL) {
5190                         xmlSchemaPErr(ctxt, facet->node,
5191                                       XML_SCHEMAP_INVALID_WHITE_SPACE,
5192                                       "Schemas: type %s whiteSpace value %s invalid\n",
5193                                       name, facet->value);
5194                     }
5195                     ret = -1;
5196                 }
5197             }
5198         default:
5199             break;
5200     }
5201     return (ret);
5202 }
5203 
5204 /**
5205  * xmlSchemaCheckDefaults:
5206  * @param typeDecl the schema type definition
5207  * @param ctxt the schema parser context
5208  *
5209  * Checks the default values types, especially for facets
5210  */
5211 static void
xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name)5212 xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
5213                        xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
5214 {
5215     if (name == NULL)
5216         name = typeDecl->name;
5217     if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
5218         if (typeDecl->facets != NULL) {
5219             xmlSchemaFacetPtr facet = typeDecl->facets;
5220 
5221             while (facet != NULL) {
5222                 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
5223                 facet = facet->next;
5224             }
5225         }
5226     }
5227 }
5228 
5229 /**
5230  * xmlSchemaAttrGrpFixup:
5231  * @param attrgrpDecl the schema attribute definition
5232  * @param ctxt the schema parser context
5233  * @param name the attribute name
5234  *
5235  * Fixes finish doing the computations on the attributes definitions
5236  */
5237 static void
xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name)5238 xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
5239                       xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
5240 {
5241     if (name == NULL)
5242         name = attrgrpDecl->name;
5243     if (attrgrpDecl->attributes != NULL)
5244         return;
5245     if (attrgrpDecl->ref != NULL) {
5246         xmlSchemaAttributeGroupPtr ref;
5247 
5248         ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
5249                              attrgrpDecl->refNs);
5250         if (ref == NULL) {
5251             xmlSchemaPErr(ctxt, attrgrpDecl->node,
5252                           XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
5253                           "Schemas: attribute group %s reference %s not found\n",
5254                           name, attrgrpDecl->ref);
5255             return;
5256         }
5257         xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
5258         attrgrpDecl->attributes = ref->attributes;
5259     } else {
5260         xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
5261                       "Schemas: attribute %s has no attributes nor reference\n",
5262                       name, NULL);
5263     }
5264 }
5265 
5266 /**
5267  * xmlSchemaAttrFixup:
5268  * @param attrDecl the schema attribute definition
5269  * @param ctxt the schema parser context
5270  * @param name the attribute name
5271  *
5272  * Fixes finish doing the computations on the attributes definitions
5273  */
5274 static void
xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name)5275 xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
5276                    xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
5277 {
5278     if (name == NULL)
5279         name = attrDecl->name;
5280     if (attrDecl->subtypes != NULL)
5281         return;
5282     if (attrDecl->typeName != NULL) {
5283         xmlSchemaTypePtr type;
5284 
5285         type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
5286                                 attrDecl->typeNs);
5287         if (type == NULL) {
5288             xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
5289                           "Schemas: attribute %s type %s not found\n",
5290                           name, attrDecl->typeName);
5291         }
5292         attrDecl->subtypes = type;
5293     } else if (attrDecl->ref != NULL) {
5294         xmlSchemaAttributePtr ref;
5295 
5296         ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
5297                              attrDecl->refNs);
5298         if (ref == NULL) {
5299             xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
5300                           "Schemas: attribute %s reference %s not found\n",
5301                           name, attrDecl->ref);
5302             return;
5303         }
5304         xmlSchemaAttrFixup(ref, ctxt, NULL);
5305         attrDecl->subtypes = ref->subtypes;
5306     } else if (attrDecl->type != XML_SCHEMA_TYPE_ANY_ATTRIBUTE) {
5307         xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
5308                       "Schemas: attribute %s has no type nor reference\n",
5309                       name, NULL);
5310     }
5311 }
5312 
5313 /**
5314  * xmlSchemaParse:
5315  * @param ctxt a schema validation context
5316  *
5317  * parse a schema definition resource and build an internal
5318  * XML Shema struture which can be used to validate instances.
5319  * *WARNING* this interface is highly subject to change
5320  *
5321  * Returns the internal XML Schema structure built from the resource or
5322  *         NULL in case of error
5323  */
5324 xmlSchemaPtr
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)5325 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
5326 {
5327     xmlSchemaPtr ret = NULL;
5328     xmlDocPtr doc;
5329     xmlNodePtr root;
5330     int nberrors;
5331     int preserve = 0;
5332 
5333     xmlSchemaInitTypes();
5334 
5335     if (ctxt == NULL)
5336         return (NULL);
5337 
5338     nberrors = ctxt->nberrors;
5339     ctxt->nberrors = 0;
5340     ctxt->counter = 0;
5341     ctxt->container = NULL;
5342 
5343     /*
5344      * First step is to parse the input document into an DOM/Infoset
5345      */
5346     if (ctxt->URL != NULL) {
5347         doc = xmlReadFile((const char *) ctxt->URL, NULL,
5348                       SCHEMAS_PARSE_OPTIONS);
5349         if (doc == NULL) {
5350         xmlSchemaPErr(ctxt, NULL,
5351               XML_SCHEMAP_FAILED_LOAD,
5352                           "xmlSchemaParse: could not load %s\n",
5353                           ctxt->URL, NULL);
5354             return (NULL);
5355         }
5356     } else if (ctxt->buffer != NULL) {
5357         doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
5358                         SCHEMAS_PARSE_OPTIONS);
5359         if (doc == NULL) {
5360         xmlSchemaPErr(ctxt, NULL,
5361               XML_SCHEMAP_FAILED_PARSE,
5362                           "xmlSchemaParse: could not parse\n",
5363                           NULL, NULL);
5364             return (NULL);
5365         }
5366         doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
5367         ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
5368     } else if (ctxt->doc != NULL) {
5369         doc = ctxt->doc;
5370     preserve = 1;
5371     } else {
5372     xmlSchemaPErr(ctxt, NULL,
5373               XML_SCHEMAP_NOTHING_TO_PARSE,
5374               "xmlSchemaParse: could not parse\n",
5375               NULL, NULL);
5376         return (NULL);
5377     }
5378 
5379     /*
5380      * Then extract the root and Schema parse it
5381      */
5382     root = xmlDocGetRootElement(doc);
5383     if (root == NULL) {
5384     xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
5385               XML_SCHEMAP_NOROOT,
5386               "schemas has no root", NULL, NULL);
5387     if (!preserve) {
5388         xmlFreeDoc(doc);
5389     }
5390         return (NULL);
5391     }
5392 
5393     /*
5394      * Remove all the blank text nodes
5395      */
5396     xmlSchemaCleanupDoc(ctxt, root);
5397 
5398     /*
5399      * Then do the parsing for good
5400      */
5401     ret = xmlSchemaParseSchema(ctxt, root);
5402     if (ret == NULL) {
5403         if (!preserve) {
5404         xmlFreeDoc(doc);
5405     }
5406         return (NULL);
5407     }
5408     ret->doc = doc;
5409     ret->preserve = preserve;
5410 
5411     /*
5412      * Then fix all the references.
5413      */
5414     ctxt->schema = ret;
5415     xmlHashScanFull(ret->elemDecl,
5416                     (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
5417 
5418     /*
5419      * Then fixup all attributes declarations
5420      */
5421     xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
5422 
5423     /*
5424      * Then fixup all attributes group declarations
5425      */
5426     xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
5427                 ctxt);
5428 
5429     /*
5430      * Then fixup all types properties
5431      */
5432     xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
5433 
5434     /*
5435      * Then build the content model for all elements
5436      */
5437     xmlHashScan(ret->elemDecl,
5438                 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
5439 
5440     /*
5441      * Then check the defaults part of the type like facets values
5442      */
5443     xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
5444                 ctxt);
5445 
5446     if (ctxt->nberrors != 0) {
5447         xmlSchemaFree(ret);
5448         ret = NULL;
5449     }
5450     return (ret);
5451 }
5452 
5453 /**
5454  * xmlSchemaSetParserErrors:
5455  * @param ctxt a schema validation context
5456  * @param err the error callback
5457  * @param warn the warning callback
5458  * @param ctx contextual data for the callbacks
5459  *
5460  * Set the callback functions used to handle errors for a validation context
5461  */
5462 void
xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)5463 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
5464                          xmlSchemaValidityErrorFunc err,
5465                          xmlSchemaValidityWarningFunc warn, void *ctx)
5466 {
5467     if (ctxt == NULL)
5468         return;
5469     ctxt->error = err;
5470     ctxt->warning = warn;
5471     ctxt->userData = ctx;
5472 }
5473 
5474 /**
5475  * xmlSchemaFacetTypeToString:
5476  * @param type the facet type
5477  *
5478  * Convert the xmlSchemaTypeType to a char string.
5479  *
5480  * Returns the char string representation of the facet type if the
5481  *     type is a facet and an "Internal Error" string otherwise.
5482  */
5483 static const char *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type)5484 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
5485 {
5486     switch (type) {
5487         case XML_SCHEMA_FACET_PATTERN:
5488             return ("pattern");
5489         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5490             return ("maxExclusive");
5491         case XML_SCHEMA_FACET_MAXINCLUSIVE:
5492             return ("maxInclusive");
5493         case XML_SCHEMA_FACET_MINEXCLUSIVE:
5494             return ("minExclusive");
5495         case XML_SCHEMA_FACET_MININCLUSIVE:
5496             return ("minInclusive");
5497         case XML_SCHEMA_FACET_WHITESPACE:
5498             return ("whiteSpace");
5499         case XML_SCHEMA_FACET_ENUMERATION:
5500             return ("enumeration");
5501         case XML_SCHEMA_FACET_LENGTH:
5502             return ("length");
5503         case XML_SCHEMA_FACET_MAXLENGTH:
5504             return ("maxLength");
5505         case XML_SCHEMA_FACET_MINLENGTH:
5506             return ("minLength");
5507         case XML_SCHEMA_FACET_TOTALDIGITS:
5508             return ("totalDigits");
5509         case XML_SCHEMA_FACET_FRACTIONDIGITS:
5510             return ("fractionDigits");
5511         default:
5512             break;
5513     }
5514     return ("Internal Error");
5515 }
5516 
5517 /**
5518  * xmlSchemaValidateFacetsInternal:
5519  * @param ctxt a schema validation context
5520  * @param base the base type
5521  * @param facets the list of facets to check
5522  * @param value the lexical repr of the value to validate
5523  * @param val the precomputed value
5524  * @param fireErrors if 0, only internal errors will be fired;
5525  *       otherwise all errors will be fired.
5526  *
5527  * Check a value against all facet conditions
5528  *
5529  * Returns 0 if the element is schemas valid, a positive error code
5530  *     number otherwise and -1 in case of internal or API error.
5531  */
5532 static int
xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,xmlSchemaTypePtr base,xmlSchemaFacetPtr facets,const xmlChar * value,int fireErrors)5533 xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
5534                         xmlSchemaTypePtr base,
5535                         xmlSchemaFacetPtr facets,
5536             const xmlChar * value, int fireErrors)
5537 {
5538     int ret = 0;
5539     int tmp = 0;
5540     xmlSchemaTypeType type;
5541     xmlSchemaFacetPtr facet = facets;
5542 
5543     while (facet != NULL) {
5544         type = facet->type;
5545         if (type == XML_SCHEMA_FACET_ENUMERATION) {
5546             tmp = 1;
5547 
5548             while (facet != NULL) {
5549                 tmp =
5550                     xmlSchemaValidateFacet(base, facet, value,
5551                                            ctxt->value);
5552                 if (tmp == 0) {
5553                     return 0;
5554                 }
5555                 facet = facet->next;
5556             }
5557         } else
5558             tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
5559 
5560         if (tmp != 0) {
5561             ret = tmp;
5562             if (fireErrors)
5563                 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_FACET,
5564                   "Failed to validate type with facet %s\n",
5565                   (const xmlChar *) xmlSchemaFacetTypeToString(type),
5566                   NULL);
5567         }
5568         if (facet != NULL)
5569             facet = facet->next;
5570     }
5571     return (ret);
5572 }
5573 
5574 /**
5575  * xmlSchemaValidateFacets:
5576  * @param ctxt a schema validation context
5577  * @param base the base type
5578  * @param facets the list of facets to check
5579  * @param value the lexical repr of the value to validate
5580  * @param val the precomputed value
5581  *
5582  * Check a value against all facet conditions
5583  *
5584  * Returns 0 if the element is schemas valid, a positive error code
5585  *     number otherwise and -1 in case of internal or API error.
5586  */
5587 static int
xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,xmlSchemaTypePtr base,xmlSchemaFacetPtr facets,const xmlChar * value)5588 xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
5589                         xmlSchemaTypePtr base,
5590                         xmlSchemaFacetPtr facets, const xmlChar * value)
5591 {
5592     return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1));
5593 }
5594 
5595 /************************************************************************
5596  *                                  *
5597  *          Simple type validation              *
5598  *                                  *
5599  ************************************************************************/
5600 
5601 /**
5602  * xmlSchemaValidateSimpleValueUnion:
5603  * @param ctxt a schema validation context
5604  * @param type the type declaration
5605  * @param value the value to validate
5606  *
5607  * Validates a value against a union.
5608  *
5609  * Returns 0 if the value is valid, a positive error code
5610  *     number otherwise and -1 in case of internal or API error.
5611  */
5612 static int
xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,xmlSchemaTypePtr type,const xmlChar * value)5613 xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,
5614                              xmlSchemaTypePtr type, const xmlChar * value)
5615 {
5616     int ret = 0;
5617     const xmlChar *cur, *end, *prefix, *ncName;
5618     xmlChar *tmp;
5619     xmlSchemaTypePtr subtype;
5620     xmlNsPtr ns;
5621     int len;
5622 
5623 
5624     /* Process referenced memberTypes. */
5625     cur = type->ref;
5626     do {
5627         while (IS_BLANK_CH(*cur))
5628             cur++;
5629         end = cur;
5630         while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5631             end++;
5632         if (end == cur)
5633             break;
5634         tmp = xmlStrndup(cur, end - cur);
5635          ncName = xmlSplitQName3(tmp, &len);
5636         if (ncName != NULL) {
5637             prefix = xmlStrndup(tmp, len);
5638             /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */
5639         } else {
5640             prefix = NULL;
5641             ncName = tmp;
5642         }
5643         /* We won't do additional checks here,
5644      * since they have been performed during parsing. */
5645         ns = xmlSearchNs(type->node->doc, type->node, prefix);
5646         /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */
5647         subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href);
5648     if (tmp != NULL)
5649         xmlFree(tmp);
5650     if (prefix != NULL)
5651         xmlFree((void *)prefix);
5652         ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5653         if ((ret == 0) || (ret == -1)) {
5654             return (ret);
5655         }
5656         cur = end;
5657     } while (*cur != 0);
5658 
5659     if (type->subtypes != NULL) {
5660         subtype = type->subtypes;
5661         do {
5662             ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5663             if ((ret == 0) || (ret == -1)) {
5664                 return (ret);
5665             }
5666             subtype = subtype->next;
5667         } while (subtype != NULL);
5668     }
5669     return (ret);
5670 }
5671 
5672 /**
5673  * xmlSchemaValidateSimpleValue:
5674  * @param ctxt a schema validation context
5675  * @param type the type declaration
5676  * @param value the value to validate
5677  *
5678  * Validate a value against a simple type
5679  *
5680  * Returns 0 if the value is valid, a positive error code
5681  *     number otherwise and -1 in case of internal or API error.
5682  */
5683 static int
xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,xmlSchemaTypePtr type,const xmlChar * value)5684 xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
5685                              xmlSchemaTypePtr type, const xmlChar * value)
5686 {
5687   return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1));
5688 }
5689 
5690 /**
5691  * xmlSchemaValidateSimpleValue:
5692  * @param ctxt a schema validation context
5693  * @param type the type declaration
5694  * @param value the value to validate
5695  * @param fireErrors if 0, only internal errors will be fired;
5696  *       otherwise all errors will be fired.
5697  *
5698  * Validate a value against a simple type
5699  *
5700  * Returns 0 if the value is valid, a positive error code
5701  *     number otherwise and -1 in case of internal or API error.
5702  */
5703 static int
xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,xmlSchemaTypePtr type,const xmlChar * value,int fireErrors)5704 xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
5705                              xmlSchemaTypePtr type,
5706                  const xmlChar * value,
5707                  int fireErrors)
5708 {
5709     int ret = 0;
5710 
5711     /*
5712      * First normalize the value accordingly to Schema Datatype
5713      * 4.3.6 whiteSpace definition of the whiteSpace facet of type
5714      *
5715      * Then check the normalized value against the lexical space of the
5716      * type.
5717      */
5718     if (type->type == XML_SCHEMA_TYPE_BASIC) {
5719         if (ctxt->value != NULL) {
5720             xmlSchemaFreeValue(ctxt->value);
5721             ctxt->value = NULL;
5722         }
5723         ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
5724                                          ctxt->cur);
5725         if ((fireErrors) && (ret != 0)) {
5726             xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
5727                   "Failed to validate basic type %s\n",
5728               type->name, NULL);
5729         }
5730     } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
5731         xmlSchemaTypePtr base;
5732         xmlSchemaFacetPtr facet;
5733 
5734         base = type->baseType;
5735         if (base != NULL) {
5736             ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
5737                     value, fireErrors);
5738         } else if (type->subtypes != NULL) {
5739         TODO
5740         }
5741 
5742         /*
5743          * Do not validate facets or attributes when working on
5744      * building the Schemas
5745          */
5746         if (ctxt->schema != NULL) {
5747             if (ret == 0) {
5748                 facet = type->facets;
5749                 ret = xmlSchemaValidateFacetsInternal(ctxt, base, facet,
5750                 value, fireErrors);
5751             }
5752         }
5753     } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
5754         xmlSchemaTypePtr base;
5755 
5756         base = type->subtypes;
5757         if (base != NULL) {
5758             ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
5759                     value, fireErrors);
5760         } else {
5761         TODO}
5762     } else if (type->type == XML_SCHEMA_TYPE_LIST) {
5763         xmlSchemaTypePtr base;
5764         const xmlChar *cur, *end;
5765     xmlChar *tmp;
5766         int ret2;
5767 
5768         base = type->subtypes;
5769         if (base == NULL) {
5770         xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
5771             "Internal: List type %s has no base type\n",
5772             type->name, NULL);
5773             return (-1);
5774         }
5775         cur = value;
5776         do {
5777             while (IS_BLANK_CH(*cur))
5778                 cur++;
5779             end = cur;
5780             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5781                 end++;
5782             if (end == cur)
5783                 break;
5784             tmp = xmlStrndup(cur, end - cur);
5785             ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base,
5786                     tmp, fireErrors);
5787         xmlFree(tmp);
5788             if (ret2 != 0)
5789                 ret = 1;
5790             cur = end;
5791         } while (*cur != 0);
5792     }  else if (type->type == XML_SCHEMA_TYPE_UNION) {
5793         ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value);
5794         if ((fireErrors) && (ret != 0)) {
5795             xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
5796                   "Failed to validate type %s\n", type->name, NULL);
5797         }
5798     } else {
5799         TODO
5800     }
5801     return (ret);
5802 }
5803 
5804 /************************************************************************
5805  *                                  *
5806  *          DOM Validation code             *
5807  *                                  *
5808  ************************************************************************/
5809 
5810 static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
5811                                     xmlNodePtr node);
5812 static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
5813                                        xmlNodePtr elem,
5814                                        xmlSchemaAttributePtr attributes);
5815 static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
5816                                  xmlNodePtr elem,
5817                                  xmlSchemaElementPtr elemDecl,
5818                                  xmlSchemaTypePtr type);
5819 
5820 /**
5821  * xmlSchemaRegisterAttributes:
5822  * @param ctxt a schema validation context
5823  * @param attrs a list of attributes
5824  *
5825  * Register the list of attributes as the set to be validated on that element
5826  *
5827  * Returns -1 in case of error, 0 otherwise
5828  */
5829 static int
xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt,xmlAttrPtr attrs)5830 xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
5831 {
5832     while (attrs != NULL) {
5833         if ((attrs->ns != NULL) &&
5834             (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
5835             attrs = attrs->next;
5836             continue;
5837         }
5838         if (ctxt->attrNr >= ctxt->attrMax) {
5839             xmlSchemaAttrStatePtr tmp;
5840 
5841             ctxt->attrMax *= 2;
5842             tmp = (xmlSchemaAttrStatePtr)
5843                 xmlRealloc(ctxt->attr, ctxt->attrMax *
5844                            sizeof(xmlSchemaAttrState));
5845             if (tmp == NULL) {
5846                 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
5847                 ctxt->attrMax /= 2;
5848                 return (-1);
5849             }
5850             ctxt->attr = tmp;
5851         }
5852         ctxt->attr[ctxt->attrNr].attr = attrs;
5853         ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
5854         ctxt->attrNr++;
5855         attrs = attrs->next;
5856     }
5857     return (0);
5858 }
5859 
5860 /**
5861  * xmlSchemaCheckAttributes:
5862  * @param ctxt a schema validation context
5863  * @param node the node carrying it.
5864  *
5865  * Check that the registered set of attributes on the current node
5866  * has been properly validated.
5867  *
5868  * Returns 0 if validity constraints are met, 1 otherwise.
5869  */
5870 static int
xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node)5871 xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5872 {
5873     int ret = 0;
5874     int i;
5875 
5876     for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5877         if (ctxt->attr[i].attr == NULL)
5878             break;
5879         if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
5880             ret = 1;
5881             xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
5882                   "Attribute %s on %s is unknown\n",
5883               ctxt->attr[i].attr->name, node->name);
5884         }
5885     }
5886     return (ret);
5887 }
5888 
5889 #if 0       /* Not currently used - remove if ever needed */
5890 /**
5891  * xmlSchemaValidateSimpleContent:
5892  * @param ctxt a schema validation context
5893  * @param elem an element
5894  * @param type the type declaration
5895  *
5896  * Validate the content of an element expected to be a simple type
5897  *
5898  * Returns 0 if the element is schemas valid, a positive error code
5899  *     number otherwise and -1 in case of internal or API error.
5900  */
5901 static int
5902 xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
5903                                xmlNodePtr node ATTRIBUTE_UNUSED)
5904 {
5905     xmlNodePtr child;
5906     xmlSchemaTypePtr type, base;
5907     xmlChar *value;
5908     int ret = 0;
5909 
5910     child = ctxt->node;
5911     type = ctxt->type;
5912 
5913     /*
5914      * Validation Rule: Element Locally Valid (Type): 3.1.3
5915      */
5916     value = xmlNodeGetContent(child);
5917     /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
5918     switch (type->type) {
5919         case XML_SCHEMA_TYPE_RESTRICTION:{
5920                 xmlSchemaFacetPtr facet;
5921 
5922                 base = type->baseType;
5923                 if (base != NULL) {
5924                     ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5925                 } else {
5926                 TODO}
5927                 if (ret == 0) {
5928                     facet = type->facets;
5929                     ret =
5930                         xmlSchemaValidateFacets(ctxt, base, facet, value);
5931                 }
5932         if ((ret == 0) && (type->attributes != NULL)) {
5933             ret = xmlSchemaValidateAttributes(ctxt, node,
5934                                               type->attributes);
5935         }
5936                 break;
5937             }
5938         case XML_SCHEMA_TYPE_EXTENSION:{
5939             TODO
5940                 break;
5941             }
5942         default:
5943         TODO
5944     }
5945     if (value != NULL)
5946         xmlFree(value);
5947 
5948     return (ret);
5949 }
5950 #endif
5951 
5952 /**
5953  * xmlSchemaValidateCheckNodeList
5954  * @param nodelist the list of nodes
5955  *
5956  * Check the node list is only made of text nodes and entities pointing
5957  * to text nodes
5958  *
5959  * Returns 1 if true, 0 if false and -1 in case of error
5960  */
5961 static int
xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)5962 xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
5963 {
5964     while (nodelist != NULL) {
5965         if (nodelist->type == XML_ENTITY_REF_NODE) {
5966             TODO                /* implement recursion in the entity content */
5967         }
5968         if ((nodelist->type != XML_TEXT_NODE) &&
5969             (nodelist->type != XML_COMMENT_NODE) &&
5970             (nodelist->type != XML_PI_NODE) &&
5971             (nodelist->type != XML_CDATA_SECTION_NODE)) {
5972             return (0);
5973         }
5974         nodelist = nodelist->next;
5975     }
5976     return (1);
5977 }
5978 
5979 /**
5980  * xmlSchemaSkipIgnored:
5981  * @param ctxt a schema validation context
5982  * @param type the current type context
5983  * @param node the top node.
5984  *
5985  * Skip ignorable nodes in that context
5986  *
5987  * Returns the new sibling
5988  *     number otherwise and -1 in case of internal or API error.
5989  */
5990 static xmlNodePtr
xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlSchemaTypePtr type,xmlNodePtr node)5991 xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
5992                      xmlSchemaTypePtr type, xmlNodePtr node)
5993 {
5994     int mixed = 0;
5995 
5996     /*
5997      *
5998      */
5999     mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
6000              (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
6001     while ((node != NULL) &&
6002            ((node->type == XML_COMMENT_NODE) ||
6003             ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
6004             (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
6005               (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
6006         node = node->next;
6007     }
6008     return (node);
6009 }
6010 
6011 /**
6012  * xmlSchemaValidateCallback:
6013  * @param ctxt a schema validation context
6014  * @param name the name of the element detected (might be NULL)
6015  * @param type the type
6016  *
6017  * A transition has been made in the automata associated to an element
6018  * content model
6019  */
6020 static void
xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,const xmlChar * name ATTRIBUTE_UNUSED,xmlSchemaTypePtr type,xmlNodePtr node)6021 xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
6022                           const xmlChar * name ATTRIBUTE_UNUSED,
6023                           xmlSchemaTypePtr type, xmlNodePtr node)
6024 {
6025     xmlSchemaTypePtr oldtype = ctxt->type;
6026     xmlNodePtr oldnode = ctxt->node;
6027 
6028 #ifdef DEBUG_CONTENT
6029     xmlGenericError(xmlGenericErrorContext,
6030                     "xmlSchemaValidateCallback: %s, %s, %s\n",
6031                     name, type->name, node->name);
6032 #endif
6033     ctxt->type = type;
6034     ctxt->node = node;
6035     xmlSchemaValidateContent(ctxt, node);
6036     ctxt->type = oldtype;
6037     ctxt->node = oldnode;
6038 }
6039 
6040 
6041 #if 0
6042 
6043 /**
6044  * xmlSchemaValidateSimpleRestrictionType:
6045  * @param ctxt a schema validation context
6046  * @param node the top node.
6047  *
6048  * Validate the content of a restriction type.
6049  *
6050  * Returns 0 if the element is schemas valid, a positive error code
6051  *     number otherwise and -1 in case of internal or API error.
6052  */
6053 static int
6054 xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
6055                                        xmlNodePtr node)
6056 {
6057     xmlNodePtr child;
6058     xmlSchemaTypePtr type;
6059     int ret;
6060 
6061     child = ctxt->node;
6062     type = ctxt->type;
6063 
6064     if ((ctxt == NULL) || (type == NULL)) {
6065         xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6066               "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
6067               node->name, NULL);
6068         return (-1);
6069     }
6070     /*
6071      * Only text and text based entities references shall be found there
6072      */
6073     ret = xmlSchemaValidateCheckNodeList(child);
6074     if (ret < 0) {
6075         xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6076               "Internal error: xmlSchemaValidateSimpleType %s content\n",
6077               node->name, NULL);
6078         return (-1);
6079     } else if (ret == 0) {
6080         xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
6081               "Element %s content is not a simple type\n",
6082               node->name, NULL);
6083         return (-1);
6084     }
6085     ctxt->type = type->subtypes;
6086     xmlSchemaValidateContent(ctxt, node);
6087     ctxt->type = type;
6088     return (ret);
6089 }
6090 #endif
6091 
6092 /**
6093  * xmlSchemaValidateSimpleType:
6094  * @param ctxt a schema validation context
6095  * @param node the top node.
6096  *
6097  * Validate the content of an simple type.
6098  *
6099  * Returns 0 if the element is schemas valid, a positive error code
6100  *     number otherwise and -1 in case of internal or API error.
6101  */
6102 static int
xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node)6103 xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6104 {
6105     xmlNodePtr child;
6106     xmlSchemaTypePtr type, base, variety;
6107     xmlAttrPtr attr;
6108     int ret;
6109     xmlChar *value;
6110 
6111 
6112     child = ctxt->node;
6113     type = ctxt->type;
6114 
6115     if ((ctxt == NULL) || (type == NULL)) {
6116         xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6117               "Internal error: xmlSchemaValidateSimpleType %s\n",
6118               node->name, NULL);
6119         return (-1);
6120     }
6121     /*
6122      * Only text and text based entities references shall be found there
6123      */
6124     ret = xmlSchemaValidateCheckNodeList(child);
6125     if (ret < 0) {
6126         xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6127               "Internal error: xmlSchemaValidateSimpleType %s content\n",
6128               node->name, NULL);
6129         return (-1);
6130     } else if (ret == 0) {
6131         xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
6132               "Element %s content is not a simple type\n",
6133               node->name, NULL);
6134         return (-1);
6135     }
6136     /*
6137      * Validation Rule: Element Locally Valid (Type): 3.1.1
6138      */
6139 
6140     attr = node->properties;
6141     while (attr != NULL) {
6142         if ((attr->ns == NULL) ||
6143             (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
6144             ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6145              (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
6146              (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
6147              (!xmlStrEqual
6148               (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
6149             xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR,
6150                   "Element %s: attribute %s should not be present\n",
6151               node->name, attr->name);
6152             return (ctxt->err);
6153         }
6154     }
6155     /*
6156      * If {variety} is �atomic� then the {variety} of {base type definition}
6157      * must be �atomic�.
6158      * If {variety} is �list� then the {variety} of {item type definition}
6159      * must be either �atomic� or �union�.
6160      * If {variety} is �union� then {member type definitions} must be a list
6161      * of datatype definitions.
6162      */
6163     if (type->subtypes == NULL) {
6164     xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6165               "Internal error: xmlSchemaValidateSimpleType; "
6166               "simple type %s does not define a variety\n",
6167               node->name, NULL);
6168     return (ctxt->err);
6169     }
6170     /* Varieties: Restriction or List or Union. */
6171     variety = type->subtypes;
6172     ctxt->type = variety;
6173     value = xmlNodeGetContent(child);
6174     switch (variety->type) {
6175         case XML_SCHEMA_TYPE_RESTRICTION:{
6176                 xmlSchemaFacetPtr facet;
6177 
6178                 base = variety->baseType;
6179                 if (base != NULL) {
6180                     ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
6181                 } else {
6182                 TODO}
6183                 if (ret == 0) {
6184                     facet = variety->facets;
6185                     ret =
6186                         xmlSchemaValidateFacets(ctxt, base, facet, value);
6187                 }
6188         if ((ret == 0) && (variety->attributes != NULL)) {
6189             ret = xmlSchemaValidateAttributes(ctxt, node,
6190                     variety->attributes);
6191         }
6192                 break;
6193             }
6194         case XML_SCHEMA_TYPE_LIST:
6195     case XML_SCHEMA_TYPE_UNION: {
6196             ret = xmlSchemaValidateSimpleValue(ctxt, variety, value);
6197                 break;
6198             }
6199         default:{
6200         xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6201                   "Internal error: xmlSchemaValidateSimpleType; "
6202                   "simple type %s defines unknown content: %s\n",
6203                   variety->name, NULL);
6204         ret = ctxt->err;
6205         }
6206     }
6207     if (value != NULL)
6208         xmlFree(value);
6209 
6210     /* This was removed, since a simple content is not a content of a
6211      * simple type, but of a complex type.
6212      * ret = xmlSchemaValidateSimpleContent(ctxt, node);
6213      */
6214     ctxt->type = type;
6215     return (ret);
6216 }
6217 
6218 /**
6219  * xmlSchemaValidateElementType:
6220  * @param ctxt a schema validation context
6221  * @param node the top node.
6222  *
6223  * Validate the content of an element type.
6224  * Validation Rule: Element Locally Valid (Complex Type)
6225  *
6226  * Returns 0 if the element is schemas valid, a positive error code
6227  *     number otherwise and -1 in case of internal or API error.
6228  */
6229 static int
xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node)6230 xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6231 {
6232     xmlNodePtr child;
6233     xmlSchemaTypePtr type;
6234     xmlRegExecCtxtPtr oldregexp;        /* cont model of the parent */
6235     xmlSchemaElementPtr decl;
6236     int ret, attrBase;
6237 
6238     oldregexp = ctxt->regexp;
6239 
6240     child = ctxt->node;
6241     type = ctxt->type;
6242 
6243     if ((ctxt == NULL) || (type == NULL)) {
6244         xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6245               "Internal error: xmlSchemaValidateElementType\n",
6246               node->name, NULL);
6247         return (-1);
6248     }
6249     if (child == NULL) {
6250         if (type->minOccurs > 0) {
6251             xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
6252                   "Element %s: missing child %s\n",
6253               node->name, type->name);
6254         }
6255         return (ctxt->err);
6256     }
6257 
6258     /*
6259      * Verify the element matches
6260      */
6261     if (!xmlStrEqual(child->name, type->name)) {
6262         xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM,
6263                "Element %s: missing child %s found %s\n",
6264                node->name, type->name, child->name);
6265         return (ctxt->err);
6266     }
6267     /*
6268      * Verify the attributes
6269      */
6270     attrBase = ctxt->attrBase;
6271     ctxt->attrBase = ctxt->attrNr;
6272     xmlSchemaRegisterAttributes(ctxt, child->properties);
6273     xmlSchemaValidateAttributes(ctxt, child, type->attributes);
6274     /*
6275      * Verify the element content recursively
6276      */
6277     decl = (xmlSchemaElementPtr) type;
6278     oldregexp = ctxt->regexp;
6279     if (decl->contModel != NULL) {
6280         ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
6281                                          (xmlRegExecCallbacks)
6282                                          xmlSchemaValidateCallback, ctxt);
6283 #ifdef DEBUG_AUTOMATA
6284         xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
6285 #endif
6286     }
6287     xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
6288                           type->subtypes);
6289 
6290     if (decl->contModel != NULL) {
6291         ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
6292 #ifdef DEBUG_AUTOMATA
6293         xmlGenericError(xmlGenericErrorContext,
6294                         "====> %s : %d\n", node->name, ret);
6295 #endif
6296         if (ret == 0) {
6297             xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
6298                   "Element %s content check failed\n",
6299               node->name, NULL);
6300         } else if (ret < 0) {
6301             xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
6302                   "Element %s content check failure\n",
6303               node->name, NULL);
6304 #ifdef DEBUG_CONTENT
6305         } else {
6306             xmlGenericError(xmlGenericErrorContext,
6307                             "Element %s content check succeeded\n",
6308                             node->name);
6309 
6310 #endif
6311         }
6312         xmlRegFreeExecCtxt(ctxt->regexp);
6313     }
6314     /*
6315      * Verify that all attributes were Schemas-validated
6316      */
6317     xmlSchemaCheckAttributes(ctxt, node);
6318     ctxt->attrNr = ctxt->attrBase;
6319     ctxt->attrBase = attrBase;
6320 
6321     ctxt->regexp = oldregexp;
6322 
6323     ctxt->node = child;
6324     ctxt->type = type;
6325     return (ctxt->err);
6326 }
6327 
6328 /**
6329  * xmlSchemaValidateBasicType:
6330  * @param ctxt a schema validation context
6331  * @param node the top node.
6332  *
6333  * Validate the content of an element expected to be a basic type type
6334  *
6335  * Returns 0 if the element is schemas valid, a positive error code
6336  *     number otherwise and -1 in case of internal or API error.
6337  */
6338 static int
xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node)6339 xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6340 {
6341     int ret;
6342     xmlNodePtr child, cur;
6343     xmlSchemaTypePtr type;
6344     xmlChar *value;             /* lexical representation */
6345 
6346     child = ctxt->node;
6347     type = ctxt->type;
6348 
6349     if ((ctxt == NULL) || (type == NULL)) {
6350         xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6351               "Internal error: xmlSchemaValidateBasicType\n",
6352               node->name, NULL);
6353         return (-1);
6354     }
6355     /*
6356      * First check the content model of the node.
6357      */
6358     cur = child;
6359     while (cur != NULL) {
6360         switch (cur->type) {
6361             case XML_TEXT_NODE:
6362             case XML_CDATA_SECTION_NODE:
6363             case XML_PI_NODE:
6364             case XML_COMMENT_NODE:
6365             case XML_XINCLUDE_START:
6366             case XML_XINCLUDE_END:
6367                 break;
6368             case XML_ENTITY_REF_NODE:
6369             case XML_ENTITY_NODE:
6370                 TODO break;
6371             case XML_ELEMENT_NODE:
6372                 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
6373                   "Element %s: child %s should not be present\n",
6374                   node->name, cur->name);
6375                 return (ctxt->err);
6376             case XML_ATTRIBUTE_NODE:
6377             case XML_DOCUMENT_NODE:
6378             case XML_DOCUMENT_TYPE_NODE:
6379             case XML_DOCUMENT_FRAG_NODE:
6380             case XML_NOTATION_NODE:
6381             case XML_HTML_DOCUMENT_NODE:
6382             case XML_DTD_NODE:
6383             case XML_ELEMENT_DECL:
6384             case XML_ATTRIBUTE_DECL:
6385             case XML_ENTITY_DECL:
6386             case XML_NAMESPACE_DECL:
6387 #ifdef LIBXML_DOCB_ENABLED
6388             case XML_DOCB_DOCUMENT_NODE:
6389 #endif
6390                 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
6391                   "Element %s: node type of node unexpected here\n",
6392                   node->name, NULL);
6393                 return (ctxt->err);
6394         }
6395         cur = cur->next;
6396     }
6397     if (child == NULL)
6398         value = NULL;
6399     else
6400         value = xmlNodeGetContent(child->parent);
6401 
6402     if (ctxt->value != NULL) {
6403         xmlSchemaFreeValue(ctxt->value);
6404         ctxt->value = NULL;
6405     }
6406     ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
6407     if (value != NULL)
6408         xmlFree(value);
6409     if (ret != 0) {
6410         xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE,
6411               "Element %s: failed to validate basic type %s\n",
6412               node->name, type->name);
6413     }
6414     return (ret);
6415 }
6416 
6417 /**
6418  * xmlSchemaValidateComplexType:
6419  * @param ctxt a schema validation context
6420  * @param node the top node.
6421  *
6422  * Validate the content of an element expected to be a complex type type
6423  * xmlschema-1.html#cvc-complex-type
6424  * Validation Rule: Element Locally Valid (Complex Type)
6425  *
6426  * Returns 0 if the element is schemas valid, a positive error code
6427  *     number otherwise and -1 in case of internal or API error.
6428  */
6429 static int
xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node)6430 xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6431 {
6432     xmlNodePtr child;
6433     xmlSchemaTypePtr type, subtype;
6434     int ret;
6435 
6436     child = ctxt->node;
6437     type = ctxt->type;
6438     ctxt->cur = node;
6439 
6440     switch (type->contentType) {
6441         case XML_SCHEMA_CONTENT_EMPTY:
6442         if (type->baseType != NULL) {
6443         } else if (child != NULL) {
6444         xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY,
6445                   "Element %s is supposed to be empty\n",
6446                   node->name, NULL);
6447             }
6448             if (type->attributes != NULL) {
6449                 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6450             }
6451             subtype = type->subtypes;
6452             while (subtype != NULL) {
6453                 ctxt->type = subtype;
6454                 xmlSchemaValidateComplexType(ctxt, node);
6455                 subtype = subtype->next;
6456             }
6457             break;
6458         case XML_SCHEMA_CONTENT_ELEMENTS:
6459         case XML_SCHEMA_CONTENT_MIXED:
6460         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
6461             /*
6462              * Skip ignorable nodes in that context
6463              */
6464             child = xmlSchemaSkipIgnored(ctxt, type, child);
6465             while (child != NULL) {
6466                 if (child->type == XML_ELEMENT_NODE) {
6467                     ret = xmlRegExecPushString(ctxt->regexp,
6468                                                child->name, child);
6469 #ifdef DEBUG_AUTOMATA
6470                     if (ret < 0)
6471                         xmlGenericError(xmlGenericErrorContext,
6472                                         "  --> %s Error\n", child->name);
6473                     else
6474                         xmlGenericError(xmlGenericErrorContext,
6475                                         "  --> %s\n", child->name);
6476 #endif
6477                 }
6478                 child = child->next;
6479                 /*
6480                  * Skip ignorable nodes in that context
6481                  */
6482                 child = xmlSchemaSkipIgnored(ctxt, type, child);
6483             }
6484         if (((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
6485         (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS)) &&
6486         (type->subtypes != NULL)) {
6487         TODO
6488         }
6489 
6490 
6491             if (type->attributes != NULL) {
6492                 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6493             }
6494             break;
6495         case XML_SCHEMA_CONTENT_BASIC:{
6496                 if (type->subtypes != NULL) {
6497                     ctxt->type = type->subtypes;
6498                     xmlSchemaValidateComplexType(ctxt, node);
6499                 }
6500                 if (type->baseType != NULL) {
6501                     ctxt->type = type->baseType;
6502             if (type->baseType->type == XML_SCHEMA_TYPE_BASIC)
6503             xmlSchemaValidateBasicType(ctxt, node);
6504             else if (type->baseType->type == XML_SCHEMA_TYPE_COMPLEX)
6505             xmlSchemaValidateComplexType(ctxt, node);
6506             else if (type->baseType->type == XML_SCHEMA_TYPE_SIMPLE)
6507             xmlSchemaValidateSimpleType(ctxt, node);
6508             else
6509             xmlGenericError(xmlGenericErrorContext,
6510                                  "unexpected content type of base: %d\n",
6511                                  type->contentType);
6512 
6513                 }
6514                 if (type->attributes != NULL) {
6515                     xmlSchemaValidateAttributes(ctxt, node,
6516                                                 type->attributes);
6517                 }
6518                 ctxt->type = type;
6519                 break;
6520             }
6521         case XML_SCHEMA_CONTENT_SIMPLE:{
6522                 if (type->subtypes != NULL) {
6523                     ctxt->type = type->subtypes;
6524                     xmlSchemaValidateComplexType(ctxt, node);
6525                 }
6526                 if (type->baseType != NULL) {
6527                     ctxt->type = type->baseType;
6528                     xmlSchemaValidateComplexType(ctxt, node);
6529                 }
6530                 if (type->attributes != NULL) {
6531                     xmlSchemaValidateAttributes(ctxt, node,
6532                                                 type->attributes);
6533                 }
6534                 ctxt->type = type;
6535                 break;
6536     }
6537         default:
6538             TODO xmlGenericError(xmlGenericErrorContext,
6539                                  "unimplemented content type %d\n",
6540                                  type->contentType);
6541     }
6542     return (ctxt->err);
6543 }
6544 
6545 /**
6546  * xmlSchemaValidateContent:
6547  * @param ctxt a schema validation context
6548  * @param elem an element
6549  * @param type the type declaration
6550  *
6551  * Validate the content of an element against the type.
6552  *
6553  * Returns 0 if the element is schemas valid, a positive error code
6554  *     number otherwise and -1 in case of internal or API error.
6555  */
6556 static int
xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node)6557 xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6558 {
6559     xmlNodePtr child;
6560     xmlSchemaTypePtr type;
6561 
6562     child = ctxt->node;
6563     type = ctxt->type;
6564     ctxt->cur = node;
6565 
6566     xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6567     ctxt->cur = node;
6568 
6569     switch (type->type) {
6570         case XML_SCHEMA_TYPE_ANY:
6571             /* Any type will do it, fine */
6572             TODO                /* handle recursivity */
6573                 break;
6574         case XML_SCHEMA_TYPE_COMPLEX:
6575             xmlSchemaValidateComplexType(ctxt, node);
6576             break;
6577         case XML_SCHEMA_TYPE_ELEMENT:{
6578                 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
6579 
6580                 /*
6581                  * Handle element reference here
6582                  */
6583                 if (decl->ref != NULL) {
6584                     if (decl->refDecl == NULL) {
6585                         xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6586                       "Internal error: element reference %s "
6587                       "not resolved\n", decl->ref, NULL);
6588                         return (-1);
6589                     }
6590                     ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
6591                     decl = decl->refDecl;
6592                 }
6593 
6594                 xmlSchemaValidateElementType(ctxt, node);
6595                 ctxt->type = type;
6596                 break;
6597             }
6598         case XML_SCHEMA_TYPE_BASIC:
6599             xmlSchemaValidateBasicType(ctxt, node);
6600             break;
6601         case XML_SCHEMA_TYPE_FACET:
6602             TODO break;
6603         case XML_SCHEMA_TYPE_SIMPLE:
6604             xmlSchemaValidateSimpleType(ctxt, node);
6605             break;
6606         case XML_SCHEMA_TYPE_SEQUENCE:
6607             TODO break;
6608         case XML_SCHEMA_TYPE_CHOICE:
6609             TODO break;
6610         case XML_SCHEMA_TYPE_ALL:
6611             TODO break;
6612         case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
6613             TODO break;
6614         case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
6615             TODO break;
6616         case XML_SCHEMA_TYPE_UR:
6617             TODO break;
6618         case XML_SCHEMA_TYPE_RESTRICTION:
6619             /*xmlSchemaValidateRestrictionType(ctxt, node); */
6620             TODO break;
6621         case XML_SCHEMA_TYPE_EXTENSION:
6622             TODO break;
6623         case XML_SCHEMA_TYPE_ATTRIBUTE:
6624             TODO break;
6625         case XML_SCHEMA_TYPE_GROUP:
6626             TODO break;
6627         case XML_SCHEMA_TYPE_NOTATION:
6628             TODO break;
6629         case XML_SCHEMA_TYPE_LIST:
6630             TODO break;
6631         case XML_SCHEMA_TYPE_UNION:
6632             TODO break;
6633         case XML_SCHEMA_FACET_MININCLUSIVE:
6634             TODO break;
6635         case XML_SCHEMA_FACET_MINEXCLUSIVE:
6636             TODO break;
6637         case XML_SCHEMA_FACET_MAXINCLUSIVE:
6638             TODO break;
6639         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
6640             TODO break;
6641         case XML_SCHEMA_FACET_TOTALDIGITS:
6642             TODO break;
6643         case XML_SCHEMA_FACET_FRACTIONDIGITS:
6644             TODO break;
6645         case XML_SCHEMA_FACET_PATTERN:
6646             TODO break;
6647         case XML_SCHEMA_FACET_ENUMERATION:
6648             TODO break;
6649         case XML_SCHEMA_FACET_WHITESPACE:
6650             TODO break;
6651         case XML_SCHEMA_FACET_LENGTH:
6652             TODO break;
6653         case XML_SCHEMA_FACET_MAXLENGTH:
6654             TODO break;
6655         case XML_SCHEMA_FACET_MINLENGTH:
6656             TODO break;
6657         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
6658             TODO break;
6659         case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6660             TODO break;
6661     }
6662     xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6663 
6664     if (ctxt->node == NULL)
6665         return (ctxt->err);
6666     ctxt->node = ctxt->node->next;
6667     ctxt->type = type->next;
6668     return (ctxt->err);
6669 }
6670 
6671 /**
6672  * xmlSchemaValidateType:
6673  * @param ctxt a schema validation context
6674  * @param elem an element
6675  * @param type the list of type declarations
6676  *
6677  * Validate the content of an element against the types.
6678  *
6679  * Returns 0 if the element is schemas valid, a positive error code
6680  *     number otherwise and -1 in case of internal or API error.
6681  */
6682 static int
xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem,xmlSchemaElementPtr elemDecl,xmlSchemaTypePtr type)6683 xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
6684                       xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
6685 {
6686     xmlChar *nil;
6687 
6688     if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
6689         return (0);
6690 
6691     /*
6692      * 3.3.4 : 2
6693      */
6694     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
6695         xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
6696               "Element declaration %s is abstract\n",
6697               elemDecl->name, NULL);
6698     /* Changed, since the element declaration is abstract and not
6699      * the element itself. */
6700     /* xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
6701              "Element %s is abstract\n", elem->name, NULL); */
6702         return (ctxt->err);
6703     }
6704     /*
6705      * 3.3.4: 3
6706      */
6707     nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
6708     if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
6709         /* 3.3.4: 3.2 */
6710         if (xmlStrEqual(nil, BAD_CAST "true")) {
6711             if (elem->children != NULL) {
6712                 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY,
6713                   "Element %s is not empty\n", elem->name, NULL);
6714                 return (ctxt->err);
6715             }
6716             if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
6717                 (elemDecl->value != NULL)) {
6718                 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT,
6719                   "Empty element %s cannot get a fixed value\n",
6720                   elem->name, NULL);
6721                 return (ctxt->err);
6722             }
6723         }
6724     } else {
6725         /* 3.3.4: 3.1 */
6726         if (nil != NULL) {
6727             xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE,
6728                   "Element %s with xs:nil but not nillable\n",
6729               elem->name, NULL);
6730             xmlFree(nil);
6731             return (ctxt->err);
6732         }
6733     }
6734 
6735 
6736 
6737     ctxt->type = elemDecl->subtypes;
6738     ctxt->node = elem->children;
6739     xmlSchemaValidateContent(ctxt, elem);
6740     xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
6741 
6742     return (ctxt->err);
6743 }
6744 
6745 
6746 /**
6747  * xmlSchemaValidateAttributes:
6748  * @param ctxt a schema validation context
6749  * @param elem an element
6750  * @param attributes the list of attribute declarations
6751  *
6752  * Validate the attributes of an element.
6753  *
6754  * Returns 0 if the element is schemas valid, a positive error code
6755  *     number otherwise and -1 in case of internal or API error.
6756  */
6757 static int
xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem,xmlSchemaAttributePtr attributes)6758 xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
6759                             xmlSchemaAttributePtr attributes)
6760 {
6761     int i, ret;
6762     xmlAttrPtr attr;
6763     xmlChar *value;
6764     xmlSchemaAttributeGroupPtr group = NULL;
6765     int found;
6766 
6767     if (attributes == NULL)
6768         return (0);
6769     while (attributes != NULL) {
6770         found = 0;
6771         /*
6772          * Handle attribute groups
6773          */
6774         if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6775             group = (xmlSchemaAttributeGroupPtr) attributes;
6776             xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
6777             attributes = group->next;
6778             continue;
6779         }
6780         for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
6781             attr = ctxt->attr[i].attr;
6782             if (attr == NULL)
6783                 continue;
6784             if (attributes->ref != NULL) {
6785                 if (!xmlStrEqual(attr->name, attributes->ref))
6786                     continue;
6787                 if (attr->ns != NULL) {
6788                     if ((attributes->refNs == NULL) ||
6789                         (!xmlStrEqual(attr->ns->href, attributes->refNs)))
6790                         continue;
6791                 } else if (attributes->refNs != NULL) {
6792                     continue;
6793                 }
6794             } else {
6795                 if (!xmlStrEqual(attr->name, attributes->name))
6796                     continue;
6797                 /*
6798                  * handle the namespaces checks here
6799                  */
6800                 if (attr->ns == NULL) {
6801             /*
6802              * accept an unqualified attribute only if the target
6803              * namespace of the declaration is absent.
6804              */
6805             if (attributes->targetNamespace != NULL)
6806             /*
6807              * This check was removed, since the target namespace
6808              * was evaluated during parsing and already took
6809              * "attributeFormDefault" into account.
6810              */
6811                 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
6812                 continue;
6813         } else {
6814             if (attributes->targetNamespace == NULL)
6815                 continue;
6816             if (!xmlStrEqual(attributes->targetNamespace,
6817                              attr->ns->href))
6818             continue;
6819         }
6820             }
6821             found = 1;
6822             ctxt->cur = (xmlNodePtr) attributes;
6823 
6824             if (attributes->subtypes == NULL) {
6825                 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL,
6826                   "Internal error: attribute %s type not resolved\n",
6827                   attr->name, NULL);
6828                 continue;
6829             }
6830 
6831             if (attributes->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
6832                 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INVALIDATTR,
6833                   "attribute %s on %s is prohibited\n",
6834                   attributes->name, elem->name);
6835                 /* Setting the state to XML_SCHEMAS_ATTR_CHECKED seems
6836          * not very logical but it suppresses the
6837          * "attribute is unknown" error report. Please change
6838          * this if you know better */
6839                 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6840                 break;
6841             }
6842 
6843             value = xmlNodeListGetString(elem->doc, attr->children, 1);
6844             ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
6845                                                value);
6846             if (ret != 0) {
6847                 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
6848                   XML_SCHEMAS_ERR_ATTRINVALID,
6849                   "attribute %s on %s does not match type\n",
6850                   attr->name, elem->name);
6851             } else {
6852                 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6853             }
6854             if (value != NULL) {
6855                 xmlFree(value);
6856             }
6857         }
6858         if ((!found) && (attributes->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6859             xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_MISSING,
6860                   "required attribute %s on %s is missing\n",
6861                   attributes->name, elem->name);
6862         }
6863         attributes = attributes->next;
6864     }
6865     return (ctxt->err);
6866 }
6867 
6868 /**
6869  * xmlSchemaValidateElement:
6870  * @param ctxt a schema validation context
6871  * @param elem an element
6872  *
6873  * Validate an element in a tree
6874  *
6875  * Returns 0 if the element is schemas valid, a positive error code
6876  *     number otherwise and -1 in case of internal or API error.
6877  */
6878 static int
xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem)6879 xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
6880 {
6881     xmlSchemaElementPtr elemDecl;
6882     int ret, attrBase;
6883 
6884     if (elem->ns != NULL) {
6885         elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6886                                   elem->name, elem->ns->href, NULL);
6887     } else {
6888         elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6889                                   elem->name, NULL, NULL);
6890     }
6891     /*
6892      * special case whe elementFormDefault is unqualified for top-level elem.
6893      */
6894     /*
6895      * This was removed, since elementFormDefault does not apply to top-level
6896      * element declarations.
6897      */
6898     /*
6899     if ((elemDecl == NULL) && (elem->ns != NULL) &&
6900         (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
6901         (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
6902     ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6903         elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6904                                   elem->name, NULL, NULL);
6905     }
6906     */
6907 
6908     /*
6909      * 3.3.4 : 1
6910      */
6911     if (elemDecl == NULL) {
6912         xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM,
6913               "Element %s not declared\n", elem->name, NULL);
6914         return (ctxt->err);
6915     }
6916     if (elemDecl->subtypes == NULL) {
6917         xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE,
6918               "Element %s has no type\n", elem->name, NULL);
6919         return (ctxt->err);
6920     }
6921     /*
6922      * Verify the attributes
6923      */
6924     attrBase = ctxt->attrBase;
6925     ctxt->attrBase = ctxt->attrNr;
6926     xmlSchemaRegisterAttributes(ctxt, elem->properties);
6927     xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
6928     /*
6929      * Verify the element content recursively
6930      */
6931     if (elemDecl->contModel != NULL) {
6932         ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
6933                                          (xmlRegExecCallbacks)
6934                                          xmlSchemaValidateCallback, ctxt);
6935 #ifdef DEBUG_AUTOMATA
6936         xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
6937 #endif
6938     }
6939     xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
6940     if (elemDecl->contModel != NULL) {
6941         ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
6942 #ifdef DEBUG_AUTOMATA
6943         xmlGenericError(xmlGenericErrorContext,
6944                         "====> %s : %d\n", elem->name, ret);
6945 #endif
6946         if (ret == 0) {
6947             xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
6948                   "Element %s content check failed\n",
6949               elem->name, NULL);
6950         } else if (ret < 0) {
6951             xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
6952                   "Element %s content check failed\n",
6953               elem->name, NULL);
6954 #ifdef DEBUG_CONTENT
6955         } else {
6956             xmlGenericError(xmlGenericErrorContext,
6957                             "Element %s content check succeeded\n",
6958                             elem->name);
6959 
6960 #endif
6961         }
6962         xmlRegFreeExecCtxt(ctxt->regexp);
6963     }
6964     /*
6965      * Verify that all attributes were Schemas-validated
6966      */
6967     xmlSchemaCheckAttributes(ctxt, elem);
6968     ctxt->attrNr = ctxt->attrBase;
6969     ctxt->attrBase = attrBase;
6970 
6971     return (ctxt->err);
6972 }
6973 
6974 /**
6975  * xmlSchemaValidateDocument:
6976  * @param ctxt a schema validation context
6977  * @param doc a parsed document tree
6978  *
6979  * Validate a document tree in memory.
6980  *
6981  * Returns 0 if the document is schemas valid, a positive error code
6982  *     number otherwise and -1 in case of internal or API error.
6983  */
6984 static int
xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt,xmlDocPtr doc)6985 xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6986 {
6987     xmlNodePtr root;
6988     xmlSchemaElementPtr elemDecl;
6989 
6990     root = xmlDocGetRootElement(doc);
6991     if (root == NULL) {
6992         xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT,
6993               "document has no root\n", NULL, NULL);
6994         return (ctxt->err);
6995     }
6996 
6997     if (root->ns != NULL)
6998         elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6999                                   root->name, root->ns->href, NULL);
7000     else
7001         elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
7002                                   root->name, NULL, NULL);
7003     /*
7004      * special case whe elementFormDefault is unqualified for top-level elem.
7005      */
7006     if ((elemDecl == NULL) && (root->ns != NULL) &&
7007         (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
7008     ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
7009         elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
7010                                   root->name, NULL, NULL);
7011     }
7012 
7013     if (elemDecl == NULL) {
7014         xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM,
7015               "Element %s not declared\n", root->name, NULL);
7016     } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
7017         xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
7018               "Root element %s not toplevel\n", root->name, NULL);
7019     }
7020     /*
7021      * Okay, start the recursive validation
7022      */
7023     xmlSchemaValidateElement(ctxt, root);
7024 
7025     return (ctxt->err);
7026 }
7027 
7028 /************************************************************************
7029  *                                  *
7030  *          SAX Validation code             *
7031  *                                  *
7032  ************************************************************************/
7033 
7034 /************************************************************************
7035  *                                  *
7036  *          Validation interfaces               *
7037  *                                  *
7038  ************************************************************************/
7039 
7040 /**
7041  * xmlSchemaNewValidCtxt:
7042  * @param schema a precompiled XML Schemas
7043  *
7044  * Create an XML Schemas validation context based on the given schema
7045  *
7046  * Returns the validation context or NULL in case of error
7047  */
7048 xmlSchemaValidCtxtPtr
xmlSchemaNewValidCtxt(xmlSchemaPtr schema)7049 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
7050 {
7051     xmlSchemaValidCtxtPtr ret;
7052 
7053     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
7054     if (ret == NULL) {
7055         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
7056         return (NULL);
7057     }
7058     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
7059     ret->schema = schema;
7060     ret->attrNr = 0;
7061     ret->attrMax = 10;
7062     ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
7063                                                   sizeof
7064                                                   (xmlSchemaAttrState));
7065     if (ret->attr == NULL) {
7066         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
7067         free(ret);
7068         return (NULL);
7069     }
7070     memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
7071     return (ret);
7072 }
7073 
7074 /**
7075  * xmlSchemaFreeValidCtxt:
7076  * @param ctxt the schema validation context
7077  *
7078  * Free the resources associated to the schema validation context
7079  */
7080 void
xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)7081 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
7082 {
7083     if (ctxt == NULL)
7084         return;
7085     if (ctxt->attr != NULL)
7086         xmlFree(ctxt->attr);
7087     if (ctxt->value != NULL)
7088         xmlSchemaFreeValue(ctxt->value);
7089     xmlFree(ctxt);
7090 }
7091 
7092 /**
7093  * xmlSchemaSetValidErrors:
7094  * @param ctxt a schema validation context
7095  * @param err the error function
7096  * @param warn the warning function
7097  * @param ctx the functions context
7098  *
7099  * Set the error and warning callback informations
7100  */
7101 void
xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)7102 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
7103                         xmlSchemaValidityErrorFunc err,
7104                         xmlSchemaValidityWarningFunc warn, void *ctx)
7105 {
7106     if (ctxt == NULL)
7107         return;
7108     ctxt->error = err;
7109     ctxt->warning = warn;
7110     ctxt->userData = ctx;
7111 }
7112 
7113 /**
7114  * xmlSchemaValidateDoc:
7115  * @param ctxt a schema validation context
7116  * @param doc a parsed document tree
7117  *
7118  * Validate a document tree in memory.
7119  *
7120  * Returns 0 if the document is schemas valid, a positive error code
7121  *     number otherwise and -1 in case of internal or API error.
7122  */
7123 int
xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt,xmlDocPtr doc)7124 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
7125 {
7126     int ret;
7127 
7128     if ((ctxt == NULL) || (doc == NULL))
7129         return (-1);
7130 
7131     ctxt->doc = doc;
7132     ret = xmlSchemaValidateDocument(ctxt, doc);
7133     return (ret);
7134 }
7135 
7136 /**
7137  * xmlSchemaValidateStream:
7138  * @param ctxt a schema validation context
7139  * @param input the input to use for reading the data
7140  * @param enc an optional encoding information
7141  * @param sax a SAX handler for the resulting events
7142  * @param user_data the context to provide to the SAX handler.
7143  *
7144  * Validate a document tree in memory.
7145  *
7146  * Returns 0 if the document is schemas valid, a positive error code
7147  *     number otherwise and -1 in case of internal or API error.
7148  */
7149 int
xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,xmlParserInputBufferPtr input,xmlCharEncoding enc,xmlSAXHandlerPtr sax,void * user_data)7150 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
7151                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
7152                         xmlSAXHandlerPtr sax, void *user_data)
7153 {
7154     if ((ctxt == NULL) || (input == NULL))
7155         return (-1);
7156     ctxt->input = input;
7157     ctxt->enc = enc;
7158     ctxt->sax = sax;
7159     ctxt->user_data = user_data;
7160     TODO return (0);
7161 }
7162 
7163 #endif /* LIBXML_SCHEMAS_ENABLED */
7164